@sentio/cli 3.7.0 → 3.8.0-rc.1

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/lib/index.js CHANGED
@@ -109910,12 +109910,16 @@ function overrideConfigWithOptions(config, options) {
109910
109910
  case "testnet":
109911
109911
  config.sentioNetwork = "7892101";
109912
109912
  break;
109913
+ case "devnet":
109914
+ config.sentioNetwork = "7892201";
109915
+ break;
109913
109916
  case "7892101":
109917
+ case "7892201":
109914
109918
  case "789210":
109915
109919
  config.sentioNetwork = options.sentioNetwork;
109916
109920
  break;
109917
109921
  default:
109918
- console.error(`Invalid sentio network: ${options.sentioNetwork}, only mainnet or testnet is allowed`);
109922
+ console.error(`Invalid sentio network: ${options.sentioNetwork}, only mainnet, testnet or devnet is allowed`);
109919
109923
  process.exit(1);
109920
109924
  }
109921
109925
  }
@@ -139193,15 +139197,25 @@ var TESTNET_CONFIG = {
139193
139197
  explorerUrl: "https://testnet-explorer.sentio.xyz",
139194
139198
  addressBookAddress: "0x94579F0e7873097279B48d7b15043698c522e47c"
139195
139199
  };
139200
+ var DEVNET_CONFIG = {
139201
+ chainId: 7892201,
139202
+ rpcUrl: "https://sentio-devnet.rpc.sentio.xyz",
139203
+ explorerUrl: "https://devnet-explorer.sentio.xyz",
139204
+ // TODO: replace with actual AddressBook address once deployed on devnet
139205
+ addressBookAddress: "0x0000000000000000000000000000000000000000"
139206
+ };
139196
139207
  function getSentioNetworkConfig(network) {
139197
139208
  if (network === "testnet" || network === "7892101") {
139198
139209
  return TESTNET_CONFIG;
139199
139210
  }
139211
+ if (network === "devnet" || network === "7892201") {
139212
+ return DEVNET_CONFIG;
139213
+ }
139200
139214
  if (network === "mainnet" || network === "789210") {
139201
139215
  console.error(source_default.red("Sentio Network mainnet is not yet supported. Only testnet is available."));
139202
139216
  process.exit(1);
139203
139217
  }
139204
- console.error(source_default.red(`Invalid sentio network: ${network}. Only "testnet" is supported.`));
139218
+ console.error(source_default.red(`Invalid sentio network: ${network}. Only "testnet" or "devnet" is supported.`));
139205
139219
  process.exit(1);
139206
139220
  }
139207
139221
  var ADDRESS_BOOK_ABI = [
@@ -139798,6 +139812,18 @@ async function finishUpload(options, auth, sha2565, commitSha, gitUrl, continueF
139798
139812
  }
139799
139813
 
139800
139814
  // src/commands/upload.ts
139815
+ var PROCESSOR_ID_RE = /^[a-zA-Z0-9_-]+$/;
139816
+ function validateProcessorId(id2) {
139817
+ if (id2.length === 0) {
139818
+ throw new Error("Processor ID must not be empty.");
139819
+ }
139820
+ if (id2.length >= 32) {
139821
+ throw new Error(`Processor ID "${id2}" is too long (${id2.length} chars). Maximum length is 31 characters.`);
139822
+ }
139823
+ if (!PROCESSOR_ID_RE.test(id2)) {
139824
+ throw new Error(`Processor ID "${id2}" contains invalid characters. Only alphanumeric, "-", and "_" are allowed.`);
139825
+ }
139826
+ }
139801
139827
  function myParseInt(value, dummyPrevious) {
139802
139828
  const parsedValue = parseInt(value, 10);
139803
139829
  if (isNaN(parsedValue)) {
@@ -139816,12 +139842,12 @@ function createUploadCommand() {
139816
139842
  ).option(
139817
139843
  "--checkpoint <checkpoint...>",
139818
139844
  '(Optional) Checkpoint(s) to rollback to, only available with --continue-from. Format: "chain_id:block_number" or "block_number" (uses default chain). Can specify multiple checkpoints.'
139819
- ).option("--debug", "(Optional) Run driver in debug mode").option("-y --silent-overwrite", "(Optional) Create project or upload new version without confirmation").option("--skip-build", "Skip build & pack file before uploading").option("--skip-gen", "Skip code generation.").option("--skip-deps", "Skip dependency enforce.").option("--example", "Generate example usage of the processor.").option("--walrus", "Store file in walrus").option("--path <path>", "override project path, default to current directory").option("--api-key <key>", "(Optional) Manually provide API key rather than use saved credential").option("--token <token>", "(Optional) Manually provide token rather than use saved credential").option("--host <host>", "(Optional) Override Sentio Host name").option("--num-workers <count>", "(Optional) Number of processor workers to start", myParseInt).option("--sentio-network <network>", "(Optional) Sentio network to connect to, can be testnet or mainnet").option(
139845
+ ).option("--debug", "(Optional) Run driver in debug mode").option("-y --silent-overwrite", "(Optional) Create project or upload new version without confirmation").option("--skip-build", "Skip build & pack file before uploading").option("--skip-gen", "Skip code generation.").option("--skip-deps", "Skip dependency enforce.").option("--example", "Generate example usage of the processor.").option("--walrus", "Store file in walrus").option("--path <path>", "override project path, default to current directory").option("--api-key <key>", "(Optional) Manually provide API key rather than use saved credential").option("--token <token>", "(Optional) Manually provide token rather than use saved credential").option("--host <host>", "(Optional) Override Sentio Host name").option("--num-workers <count>", "(Optional) Number of processor workers to start", myParseInt).option("--sentio-network <network>", "(Optional) Sentio network to connect to, can be testnet, devnet or mainnet").option(
139820
139846
  "--required-chain-id <chain_id...>",
139821
139847
  "(Optional) Specify chain IDs required for the Sentio network. This option is only available when --sentio-network is used. If omitted, all chain IDs from the project configuration (contracts or network overrides) will be used."
139822
139848
  ).option(
139823
139849
  "--no-platform",
139824
- "Upload processor directly to Sentio Network without platform support. Requires $PRIVATE_KEY env var. Only testnet is supported."
139850
+ "Upload processor directly to Sentio Network without platform support. Requires $PRIVATE_KEY env var. Only testnet and devnet are supported."
139825
139851
  ).option(
139826
139852
  "--ipfs-put-url <url>",
139827
139853
  "IPFS upload endpoint (used with --no-platform)",
@@ -139924,6 +139950,7 @@ The owner must call Permissions.addOperator(${walletAddress}) first.`
139924
139950
  process.exit(1);
139925
139951
  }
139926
139952
  let processorId = processorConfig.project.replace("/", "_");
139953
+ validateProcessorId(processorId);
139927
139954
  const sdkVersion = getSdkVersion() || "unknown";
139928
139955
  console.log(source_default.blue("Checking if processor already exists on-chain..."));
139929
139956
  const existingProcessor = await getProcessorOnChain(networkConfig, addresses, processorId);
@@ -139949,13 +139976,22 @@ The owner must call Permissions.addOperator(${walletAddress}) first.`
139949
139976
  );
139950
139977
  const randomSuffix = Math.random().toString(36).substring(2, 8);
139951
139978
  const defaultNewId = `${processorId}-${randomSuffix}`;
139952
- const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
139953
- const newId = await new Promise(
139954
- (resolve) => rl.question(`Enter a new processor ID [${defaultNewId}]: `, (answer) => {
139955
- rl.close();
139956
- resolve(answer.trim() || defaultNewId);
139957
- })
139958
- );
139979
+ let newId;
139980
+ for (; ; ) {
139981
+ const rl = readline3.createInterface({ input: process.stdin, output: process.stdout });
139982
+ newId = await new Promise(
139983
+ (resolve) => rl.question(`Enter a new processor ID [${defaultNewId}]: `, (answer) => {
139984
+ rl.close();
139985
+ resolve(answer.trim() || defaultNewId);
139986
+ })
139987
+ );
139988
+ try {
139989
+ validateProcessorId(newId);
139990
+ break;
139991
+ } catch (e10) {
139992
+ console.log(source_default.red(e10.message));
139993
+ }
139994
+ }
139959
139995
  processorId = newId;
139960
139996
  console.log(source_default.blue(`Using processor ID: ${processorId}`));
139961
139997
  }
@@ -140201,7 +140237,7 @@ async function checkOrCreateProject(options, auth) {
140201
140237
  console.error(
140202
140238
  source_default.red(
140203
140239
  `Project ${project?.slug} is a Sentio Network project. Please add the --sentio-network flag when uploading.
140204
- Example: sentio upload --sentio-network testnet`
140240
+ Example: sentio upload --sentio-network testnet|devnet`
140205
140241
  )
140206
140242
  );
140207
140243
  process.exit(1);
@@ -145453,7 +145489,7 @@ function formatTimestamp3(value) {
145453
145489
  // src/commands/stop-processor.ts
145454
145490
  init_cjs_shim();
145455
145491
  function createStopProcessorCommand() {
145456
- return new Command("stop").description("Stop a processor. Uses Sentio Network contract when --sentio-network is specified.").argument("<processorId>", "ID of the processor to stop").option("--sentio-network <network>", 'Stop via Sentio Network contract (only "testnet" supported)').option("--host <host>", "Override Sentio host").option("--api-key <key>", "Use an explicit API key instead of saved credentials").option("--token <token>", "Use an explicit bearer token instead of saved credentials").option("--project <owner/slug>", "Sentio project in <owner>/<slug> format").option("--owner <owner>", "Sentio project owner").option("--name <name>", "Sentio project name").option("-y, --yes", "Bypass confirmation").showHelpAfterError().action(async (processorId, options) => {
145492
+ return new Command("stop").description("Stop a processor. Uses Sentio Network contract when --sentio-network is specified.").argument("<processorId>", "ID of the processor to stop").option("--sentio-network <network>", "Stop via Sentio Network contract (testnet or devnet)").option("--host <host>", "Override Sentio host").option("--api-key <key>", "Use an explicit API key instead of saved credentials").option("--token <token>", "Use an explicit bearer token instead of saved credentials").option("--project <owner/slug>", "Sentio project in <owner>/<slug> format").option("--owner <owner>", "Sentio project owner").option("--name <name>", "Sentio project name").option("-y, --yes", "Bypass confirmation").option("--no-delete", "Skip deleting the processor after stopping").showHelpAfterError().action(async (processorId, options) => {
145457
145493
  try {
145458
145494
  if (options.sentioNetwork) {
145459
145495
  await runStopProcessorOnChain(processorId, options);
@@ -145473,16 +145509,22 @@ async function runStopProcessorOnChain(processorId, options) {
145473
145509
  console.log(source_default.blue(`Wallet address: ${wallet.address}`));
145474
145510
  console.log(source_default.blue("Resolving contract addresses from AddressBook..."));
145475
145511
  const addresses = await resolveNetworkAddresses(networkConfig);
145512
+ const willDelete = options.delete !== false;
145476
145513
  if (!options.yes) {
145477
- const confirmed = await confirm(`Stop processor "${processorId}" on Sentio Network ${network}?`);
145514
+ const action = willDelete ? "Stop and delete" : "Stop";
145515
+ const confirmed = await confirm(`${action} processor "${processorId}" on Sentio Network ${network}?`);
145478
145516
  if (!confirmed) {
145479
- console.log("Stop cancelled.");
145517
+ console.log("Cancelled.");
145480
145518
  return;
145481
145519
  }
145482
145520
  }
145483
145521
  await stopProcessorOnChain(networkConfig, addresses, wallet, processorId);
145484
- console.log();
145485
145522
  console.log(source_default.green(`Processor "${processorId}" stopped on Sentio Network ${network}.`));
145523
+ if (willDelete) {
145524
+ console.log();
145525
+ await deleteProcessorOnChain(networkConfig, addresses, wallet, processorId);
145526
+ console.log(source_default.green(`Processor "${processorId}" deleted on Sentio Network ${network}.`));
145527
+ }
145486
145528
  }
145487
145529
 
145488
145530
  // src/index.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentio/cli",
3
- "version": "3.7.0",
3
+ "version": "3.8.0-rc.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
@@ -8,14 +8,15 @@ import {
8
8
  resolveNetworkAddresses,
9
9
  getWalletFromPrivateKey,
10
10
  requirePrivateKey,
11
- stopProcessorOnChain
11
+ stopProcessorOnChain,
12
+ deleteProcessorOnChain
12
13
  } from '../network.js'
13
14
 
14
15
  export function createStopProcessorCommand() {
15
16
  return new Command('stop')
16
17
  .description('Stop a processor. Uses Sentio Network contract when --sentio-network is specified.')
17
18
  .argument('<processorId>', 'ID of the processor to stop')
18
- .option('--sentio-network <network>', 'Stop via Sentio Network contract (only "testnet" supported)')
19
+ .option('--sentio-network <network>', 'Stop via Sentio Network contract (testnet or devnet)')
19
20
  .option('--host <host>', 'Override Sentio host')
20
21
  .option('--api-key <key>', 'Use an explicit API key instead of saved credentials')
21
22
  .option('--token <token>', 'Use an explicit bearer token instead of saved credentials')
@@ -23,6 +24,7 @@ export function createStopProcessorCommand() {
23
24
  .option('--owner <owner>', 'Sentio project owner')
24
25
  .option('--name <name>', 'Sentio project name')
25
26
  .option('-y, --yes', 'Bypass confirmation')
27
+ .option('--no-delete', 'Skip deleting the processor after stopping')
26
28
  .showHelpAfterError()
27
29
  .action(async (processorId, options) => {
28
30
  try {
@@ -37,7 +39,10 @@ export function createStopProcessorCommand() {
37
39
  })
38
40
  }
39
41
 
40
- async function runStopProcessorOnChain(processorId: string, options: { sentioNetwork?: string; yes?: boolean }) {
42
+ async function runStopProcessorOnChain(
43
+ processorId: string,
44
+ options: { sentioNetwork?: string; yes?: boolean; delete?: boolean }
45
+ ) {
41
46
  const network = options.sentioNetwork!
42
47
  const networkConfig = getSentioNetworkConfig(network)
43
48
 
@@ -48,16 +53,23 @@ async function runStopProcessorOnChain(processorId: string, options: { sentioNet
48
53
  console.log(chalk.blue('Resolving contract addresses from AddressBook...'))
49
54
  const addresses = await resolveNetworkAddresses(networkConfig)
50
55
 
56
+ const willDelete = options.delete !== false
57
+
51
58
  if (!options.yes) {
52
- const confirmed = await confirm(`Stop processor "${processorId}" on Sentio Network ${network}?`)
59
+ const action = willDelete ? 'Stop and delete' : 'Stop'
60
+ const confirmed = await confirm(`${action} processor "${processorId}" on Sentio Network ${network}?`)
53
61
  if (!confirmed) {
54
- console.log('Stop cancelled.')
62
+ console.log('Cancelled.')
55
63
  return
56
64
  }
57
65
  }
58
66
 
59
67
  await stopProcessorOnChain(networkConfig, addresses, wallet, processorId)
60
-
61
- console.log()
62
68
  console.log(chalk.green(`Processor "${processorId}" stopped on Sentio Network ${network}.`))
69
+
70
+ if (willDelete) {
71
+ console.log()
72
+ await deleteProcessorOnChain(networkConfig, addresses, wallet, processorId)
73
+ console.log(chalk.green(`Processor "${processorId}" deleted on Sentio Network ${network}.`))
74
+ }
63
75
  }
@@ -33,6 +33,20 @@ import { ethers } from 'ethers'
33
33
  import { Auth, DefaultBatchUploader, FileType, IPFSBatchUploader, WalrusBatchUploader } from '../uploader.js'
34
34
  export { type Auth } from '../uploader.js'
35
35
 
36
+ const PROCESSOR_ID_RE = /^[a-zA-Z0-9_-]+$/
37
+
38
+ function validateProcessorId(id: string): void {
39
+ if (id.length === 0) {
40
+ throw new Error('Processor ID must not be empty.')
41
+ }
42
+ if (id.length >= 32) {
43
+ throw new Error(`Processor ID "${id}" is too long (${id.length} chars). Maximum length is 31 characters.`)
44
+ }
45
+ if (!PROCESSOR_ID_RE.test(id)) {
46
+ throw new Error(`Processor ID "${id}" contains invalid characters. Only alphanumeric, "-", and "_" are allowed.`)
47
+ }
48
+ }
49
+
36
50
  function myParseInt(value: string, dummyPrevious: number): number {
37
51
  // parseInt takes a string and a radix
38
52
  const parsedValue = parseInt(value, 10)
@@ -71,14 +85,14 @@ export function createUploadCommand() {
71
85
  .option('--token <token>', '(Optional) Manually provide token rather than use saved credential')
72
86
  .option('--host <host>', '(Optional) Override Sentio Host name')
73
87
  .option('--num-workers <count>', '(Optional) Number of processor workers to start', myParseInt)
74
- .option('--sentio-network <network>', '(Optional) Sentio network to connect to, can be testnet or mainnet')
88
+ .option('--sentio-network <network>', '(Optional) Sentio network to connect to, can be testnet, devnet or mainnet')
75
89
  .option(
76
90
  '--required-chain-id <chain_id...>',
77
91
  '(Optional) Specify chain IDs required for the Sentio network. This option is only available when --sentio-network is used. If omitted, all chain IDs from the project configuration (contracts or network overrides) will be used.'
78
92
  )
79
93
  .option(
80
94
  '--no-platform',
81
- 'Upload processor directly to Sentio Network without platform support. Requires $PRIVATE_KEY env var. Only testnet is supported.'
95
+ 'Upload processor directly to Sentio Network without platform support. Requires $PRIVATE_KEY env var. Only testnet and devnet are supported.'
82
96
  )
83
97
  .option(
84
98
  '--ipfs-put-url <url>',
@@ -208,6 +222,7 @@ async function runNoPlatformUpload(
208
222
 
209
223
  // Step 7: Derive processor ID from project name
210
224
  let processorId = processorConfig.project.replace('/', '_')
225
+ validateProcessorId(processorId)
211
226
  const sdkVersion = getSdkVersion() || 'unknown'
212
227
 
213
228
  // Step 7.5: Check if processor already exists on-chain
@@ -242,13 +257,22 @@ async function runNoPlatformUpload(
242
257
  const randomSuffix = Math.random().toString(36).substring(2, 8)
243
258
  const defaultNewId = `${processorId}-${randomSuffix}`
244
259
 
245
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
246
- const newId: string = await new Promise((resolve) =>
247
- rl.question(`Enter a new processor ID [${defaultNewId}]: `, (answer) => {
248
- rl.close()
249
- resolve(answer.trim() || defaultNewId)
250
- })
251
- )
260
+ let newId: string
261
+ for (;;) {
262
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
263
+ newId = await new Promise((resolve) =>
264
+ rl.question(`Enter a new processor ID [${defaultNewId}]: `, (answer) => {
265
+ rl.close()
266
+ resolve(answer.trim() || defaultNewId)
267
+ })
268
+ )
269
+ try {
270
+ validateProcessorId(newId)
271
+ break
272
+ } catch (e: any) {
273
+ console.log(chalk.red(e.message))
274
+ }
275
+ }
252
276
  processorId = newId
253
277
  console.log(chalk.blue(`Using processor ID: ${processorId}`))
254
278
  }
@@ -538,7 +562,7 @@ async function checkOrCreateProject(options: YamlProjectConfig, auth: Auth) {
538
562
  console.error(
539
563
  chalk.red(
540
564
  `Project ${project?.slug} is a Sentio Network project. Please add the --sentio-network flag when uploading.\n` +
541
- `Example: sentio upload --sentio-network testnet`
565
+ `Example: sentio upload --sentio-network testnet|devnet`
542
566
  )
543
567
  )
544
568
  process.exit(1)
package/src/config.ts CHANGED
@@ -115,12 +115,16 @@ export function overrideConfigWithOptions(config: YamlProjectConfig, options: an
115
115
  case 'testnet':
116
116
  config.sentioNetwork = '7892101'
117
117
  break
118
+ case 'devnet':
119
+ config.sentioNetwork = '7892201'
120
+ break
118
121
  case '7892101':
122
+ case '7892201':
119
123
  case '789210':
120
124
  config.sentioNetwork = options.sentioNetwork
121
125
  break
122
126
  default:
123
- console.error(`Invalid sentio network: ${options.sentioNetwork}, only mainnet or testnet is allowed`)
127
+ console.error(`Invalid sentio network: ${options.sentioNetwork}, only mainnet, testnet or devnet is allowed`)
124
128
  process.exit(1)
125
129
  }
126
130
  }
package/src/network.ts CHANGED
@@ -20,15 +20,26 @@ const TESTNET_CONFIG: SentioNetworkConfig = {
20
20
  addressBookAddress: '0x94579F0e7873097279B48d7b15043698c522e47c'
21
21
  }
22
22
 
23
+ const DEVNET_CONFIG: SentioNetworkConfig = {
24
+ chainId: 7892201,
25
+ rpcUrl: 'https://sentio-devnet.rpc.sentio.xyz',
26
+ explorerUrl: 'https://devnet-explorer.sentio.xyz',
27
+ // TODO: replace with actual AddressBook address once deployed on devnet
28
+ addressBookAddress: '0x0000000000000000000000000000000000000000'
29
+ }
30
+
23
31
  export function getSentioNetworkConfig(network: string): SentioNetworkConfig {
24
32
  if (network === 'testnet' || network === '7892101') {
25
33
  return TESTNET_CONFIG
26
34
  }
35
+ if (network === 'devnet' || network === '7892201') {
36
+ return DEVNET_CONFIG
37
+ }
27
38
  if (network === 'mainnet' || network === '789210') {
28
39
  console.error(chalk.red('Sentio Network mainnet is not yet supported. Only testnet is available.'))
29
40
  process.exit(1)
30
41
  }
31
- console.error(chalk.red(`Invalid sentio network: ${network}. Only "testnet" is supported.`))
42
+ console.error(chalk.red(`Invalid sentio network: ${network}. Only "testnet" or "devnet" is supported.`))
32
43
  process.exit(1)
33
44
  }
34
45