@sentio/cli 3.6.2 → 3.6.3-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.
Files changed (3) hide show
  1. package/lib/index.js +71 -37
  2. package/package.json +1 -1
  3. package/src/network.ts +102 -44
package/lib/index.js CHANGED
@@ -139215,7 +139215,6 @@ var PROCESSOR_REGISTRY_ABI = [
139215
139215
  string sdkVersion
139216
139216
  ) returns (string)`,
139217
139217
  "event ProcessorCreated(string indexed processorId)",
139218
- "function getAllocations(string processorId) view returns (tuple(uint256 indexerId, uint256 timestamp, bool indexerReady)[])",
139219
139218
  `function getProcessor(string processorId) view returns (
139220
139219
  tuple(
139221
139220
  string id,
@@ -139225,12 +139224,17 @@ var PROCESSOR_REGISTRY_ABI = [
139225
139224
  string sdkVersion,
139226
139225
  tuple(string chainId, bool enableRpc, bool enableTrace)[] requireChains,
139227
139226
  tuple(uint8 sourceType, string ipfsCid) source,
139228
- tuple(uint256 indexerId, uint256 timestamp, bool indexerReady)[] allocations
139227
+ tuple(uint256 indexerId, uint256 allocationTime, bool indexerReady, uint256 replicaIndex)[] allocations
139229
139228
  )
139230
139229
  )`,
139231
139230
  "function deleteProcessor(string processorId)"
139232
139231
  ];
139233
- var CONTROLLER_ABI = ["function startProcessor(string processorId)", "function stopProcessor(string processorId)"];
139232
+ var CONTROLLER_ABI = [
139233
+ "function startProcessor(string processorId)",
139234
+ "function stopProcessor(string processorId)",
139235
+ "function getAllocations(string processorId) view returns (tuple(uint256 indexerId, uint256 allocationTime, bool indexerReady, uint256 replicaIndex)[])"
139236
+ ];
139237
+ var DATABASES_ABI = ["function getProcessorDatabases(string processorId) view returns (string[])"];
139234
139238
  var ERC20_ABI = [
139235
139239
  "function balanceOf(address account) view returns (uint256)",
139236
139240
  "function approve(address spender, uint256 amount) returns (bool)"
@@ -139240,7 +139244,8 @@ var ADDRESS_BOOK_KEYS = {
139240
139244
  processorRegistry: "processor_registry",
139241
139245
  controller: "controller",
139242
139246
  token: "sentio_token",
139243
- billing: "billing"
139247
+ billing: "billing",
139248
+ databases: "databases"
139244
139249
  };
139245
139250
  var cachedAddresses;
139246
139251
  async function resolveNetworkAddresses(config) {
@@ -139261,17 +139266,19 @@ async function resolveNetworkAddresses(config) {
139261
139266
  }
139262
139267
  }
139263
139268
  };
139264
- const [processorRegistry, controller, token, billing] = await Promise.all([
139269
+ const [processorRegistry, controller, token, billing, databases] = await Promise.all([
139265
139270
  resolveAddress2(ADDRESS_BOOK_KEYS.processorRegistry),
139266
139271
  resolveAddress2(ADDRESS_BOOK_KEYS.controller),
139267
139272
  resolveAddress2(ADDRESS_BOOK_KEYS.token),
139268
- resolveAddress2(ADDRESS_BOOK_KEYS.billing)
139273
+ resolveAddress2(ADDRESS_BOOK_KEYS.billing),
139274
+ resolveAddress2(ADDRESS_BOOK_KEYS.databases)
139269
139275
  ]);
139270
139276
  console.log(source_default.gray(`ProcessorRegistry: ${processorRegistry}`));
139271
139277
  console.log(source_default.gray(`Controller: ${controller}`));
139272
139278
  console.log(source_default.gray(`ST Token: ${token}`));
139273
139279
  console.log(source_default.gray(`Billing: ${billing}`));
139274
- cachedAddresses = { addressBook: addressBookAddr, processorRegistry, controller, token, billing };
139280
+ console.log(source_default.gray(`Databases: ${databases}`));
139281
+ cachedAddresses = { addressBook: addressBookAddr, processorRegistry, controller, token, billing, databases };
139275
139282
  return cachedAddresses;
139276
139283
  }
139277
139284
  function getWalletFromPrivateKey(privateKey) {
@@ -139322,6 +139329,26 @@ async function uploadToIPFS(fileBuffer, ipfsUrl) {
139322
139329
  const result = await response.json();
139323
139330
  return result.Hash;
139324
139331
  }
139332
+ async function submitAndWait(explorerUrl, label, txPromise) {
139333
+ let tx;
139334
+ try {
139335
+ tx = await txPromise;
139336
+ } catch (err) {
139337
+ throw new Error(`${label} failed to submit: ${err.shortMessage ?? err.message}`);
139338
+ }
139339
+ console.log(source_default.gray(` Tx hash: ${explorerUrl}/tx/${tx.hash}`));
139340
+ console.log(source_default.blue("Waiting for confirmation..."));
139341
+ let receipt;
139342
+ try {
139343
+ receipt = await tx.wait();
139344
+ } catch (err) {
139345
+ throw new Error(`${label} failed: ${err.shortMessage ?? err.message}. Tx: ${explorerUrl}/tx/${tx.hash}`);
139346
+ }
139347
+ if (!receipt || receipt.status === 0) {
139348
+ throw new Error(`${label} transaction reverted. Tx: ${explorerUrl}/tx/${tx.hash}`);
139349
+ }
139350
+ return tx;
139351
+ }
139325
139352
  async function getProcessorOnChain(config, addresses, processorId) {
139326
139353
  const provider = new ethers_exports.JsonRpcProvider(config.rpcUrl);
139327
139354
  const registry = new ethers_exports.Contract(addresses.processorRegistry, PROCESSOR_REGISTRY_ABI, provider);
@@ -139347,16 +139374,30 @@ async function deleteProcessorOnChain(config, addresses, wallet, processorId) {
139347
139374
  const signer = wallet.connect(provider);
139348
139375
  const registry = new ethers_exports.Contract(addresses.processorRegistry, PROCESSOR_REGISTRY_ABI, signer);
139349
139376
  console.log(source_default.blue("Deleting existing processor on-chain..."));
139350
- const tx = await registry.deleteProcessor(processorId);
139351
- console.log(source_default.gray(` Tx hash: ${tx.hash}`));
139352
- console.log(source_default.blue("Waiting for confirmation..."));
139353
- const receipt = await tx.wait();
139354
- if (receipt.status === 0) {
139355
- throw new Error(`deleteProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`);
139356
- }
139377
+ const tx = await submitAndWait(config.explorerUrl, "deleteProcessor", registry.deleteProcessor(processorId));
139357
139378
  console.log(source_default.green(`Processor deleted. Tx: ${config.explorerUrl}/tx/${tx.hash}`));
139379
+ await waitForProcessorDatabaseCleanup(addresses, processorId, provider);
139358
139380
  return tx.hash;
139359
139381
  }
139382
+ async function waitForProcessorDatabaseCleanup(addresses, processorId, provider, timeoutMs = 12e4, pollIntervalMs = 5e3) {
139383
+ const databases = new ethers_exports.Contract(addresses.databases, DATABASES_ABI, provider);
139384
+ const dbIds = await databases.getProcessorDatabases(processorId);
139385
+ if (dbIds.length === 0) {
139386
+ return;
139387
+ }
139388
+ console.log(source_default.blue(`Waiting for ${dbIds.length} replica database(s) to be cleaned up...`));
139389
+ const deadline = Date.now() + timeoutMs;
139390
+ while (Date.now() < deadline) {
139391
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
139392
+ const remaining = await databases.getProcessorDatabases(processorId);
139393
+ if (remaining.length === 0) {
139394
+ console.log(source_default.green("All replica databases cleaned up."));
139395
+ return;
139396
+ }
139397
+ console.log(source_default.gray(` ${remaining.length} replica database(s) still pending cleanup...`));
139398
+ }
139399
+ throw new Error(`Timeout: processor databases not cleaned up within ${timeoutMs / 1e3}s`);
139400
+ }
139360
139401
  async function createProcessorOnChain(config, addresses, wallet, processorId, ipfsCid, requiredChainIds, sdkVersion) {
139361
139402
  const provider = new ethers_exports.JsonRpcProvider(config.rpcUrl);
139362
139403
  const signer = wallet.connect(provider);
@@ -139376,13 +139417,11 @@ async function createProcessorOnChain(config, addresses, wallet, processorId, ip
139376
139417
  console.log(source_default.gray(` IPFS CID: ${ipfsCid}`));
139377
139418
  console.log(source_default.gray(` Chains: ${requiredChainIds.join(", ")}`));
139378
139419
  console.log(source_default.gray(` SDK Version: ${sdkVersion}`));
139379
- const tx = await registry.createProcessor(processorId, source, requireChains, sdkVersion);
139380
- console.log(source_default.gray(` Tx hash: ${tx.hash}`));
139381
- console.log(source_default.blue("Waiting for confirmation..."));
139382
- const receipt = await tx.wait();
139383
- if (receipt.status === 0) {
139384
- throw new Error(`createProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`);
139385
- }
139420
+ const tx = await submitAndWait(
139421
+ config.explorerUrl,
139422
+ "createProcessor",
139423
+ registry.createProcessor(processorId, source, requireChains, sdkVersion)
139424
+ );
139386
139425
  console.log(source_default.green(`Processor created. Tx: ${config.explorerUrl}/tx/${tx.hash}`));
139387
139426
  return tx.hash;
139388
139427
  }
@@ -139391,13 +139430,7 @@ async function startProcessorOnChain(config, addresses, wallet, processorId) {
139391
139430
  const signer = wallet.connect(provider);
139392
139431
  const controller = new ethers_exports.Contract(addresses.controller, CONTROLLER_ABI, signer);
139393
139432
  console.log(source_default.blue("Starting processor on-chain..."));
139394
- const tx = await controller.startProcessor(processorId);
139395
- console.log(source_default.gray(` Tx hash: ${tx.hash}`));
139396
- console.log(source_default.blue("Waiting for confirmation..."));
139397
- const receipt = await tx.wait();
139398
- if (receipt.status === 0) {
139399
- throw new Error(`startProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`);
139400
- }
139433
+ const tx = await submitAndWait(config.explorerUrl, "startProcessor", controller.startProcessor(processorId));
139401
139434
  console.log(source_default.green(`Processor started. Tx: ${config.explorerUrl}/tx/${tx.hash}`));
139402
139435
  return tx.hash;
139403
139436
  }
@@ -139405,14 +139438,13 @@ async function stopProcessorOnChain(config, addresses, wallet, processorId) {
139405
139438
  const provider = new ethers_exports.JsonRpcProvider(config.rpcUrl);
139406
139439
  const signer = wallet.connect(provider);
139407
139440
  const controller = new ethers_exports.Contract(addresses.controller, CONTROLLER_ABI, signer);
139408
- console.log(source_default.blue("Stopping processor on-chain..."));
139409
- const tx = await controller.stopProcessor(processorId);
139410
- console.log(source_default.gray(` Tx hash: ${tx.hash}`));
139411
- console.log(source_default.blue("Waiting for confirmation..."));
139412
- const receipt = await tx.wait();
139413
- if (receipt.status === 0) {
139414
- throw new Error(`stopProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`);
139441
+ const allocations = await controller.getAllocations(processorId);
139442
+ if (allocations.length === 0) {
139443
+ console.log(source_default.gray("Processor has no allocations, skipping stopProcessor."));
139444
+ return "";
139415
139445
  }
139446
+ console.log(source_default.blue("Stopping processor on-chain..."));
139447
+ const tx = await submitAndWait(config.explorerUrl, "stopProcessor", controller.stopProcessor(processorId));
139416
139448
  console.log(source_default.green(`Processor stopped. Tx: ${config.explorerUrl}/tx/${tx.hash}`));
139417
139449
  return tx.hash;
139418
139450
  }
@@ -139430,8 +139462,10 @@ async function confirmNoPlatformUpload(walletAddress, stBalance, billingBalance,
139430
139462
  source_default.yellow(
139431
139463
  ` \u26A0 Your Billing balance is 0. Indexing fees are charged from the Billing contract.
139432
139464
  You must deposit ST tokens into the Billing contract before your processor can run.
139433
- Use: cast send ${addresses.token} "approve(address,uint256)" ${addresses.billing} <amount> --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY
139434
- cast send ${addresses.billing} "deposit(uint256)" <amount> --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY`
139465
+ Example (replace 100 with your desired ST amount):
139466
+ export AMOUNT=$(cast to-wei 100 ether)
139467
+ cast send ${addresses.token} "approve(address,uint256)" ${addresses.billing} $AMOUNT --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY
139468
+ cast send ${addresses.billing} "deposit(uint256)" $AMOUNT --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY`
139435
139469
  )
139436
139470
  );
139437
139471
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentio/cli",
3
- "version": "3.6.2",
3
+ "version": "3.6.3-rc.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "exports": {
package/src/network.ts CHANGED
@@ -49,7 +49,6 @@ const PROCESSOR_REGISTRY_ABI = [
49
49
  string sdkVersion
50
50
  ) returns (string)`,
51
51
  'event ProcessorCreated(string indexed processorId)',
52
- 'function getAllocations(string processorId) view returns (tuple(uint256 indexerId, uint256 timestamp, bool indexerReady)[])',
53
52
  `function getProcessor(string processorId) view returns (
54
53
  tuple(
55
54
  string id,
@@ -59,14 +58,21 @@ const PROCESSOR_REGISTRY_ABI = [
59
58
  string sdkVersion,
60
59
  tuple(string chainId, bool enableRpc, bool enableTrace)[] requireChains,
61
60
  tuple(uint8 sourceType, string ipfsCid) source,
62
- tuple(uint256 indexerId, uint256 timestamp, bool indexerReady)[] allocations
61
+ tuple(uint256 indexerId, uint256 allocationTime, bool indexerReady, uint256 replicaIndex)[] allocations
63
62
  )
64
63
  )`,
65
64
  'function deleteProcessor(string processorId)'
66
65
  ]
67
66
 
68
- // Controller: startProcessor / stopProcessor
69
- const CONTROLLER_ABI = ['function startProcessor(string processorId)', 'function stopProcessor(string processorId)']
67
+ // Controller: startProcessor / stopProcessor / getAllocations
68
+ const CONTROLLER_ABI = [
69
+ 'function startProcessor(string processorId)',
70
+ 'function stopProcessor(string processorId)',
71
+ 'function getAllocations(string processorId) view returns (tuple(uint256 indexerId, uint256 allocationTime, bool indexerReady, uint256 replicaIndex)[])'
72
+ ]
73
+
74
+ // Databases: getProcessorDatabases
75
+ const DATABASES_ABI = ['function getProcessorDatabases(string processorId) view returns (string[])']
70
76
 
71
77
  // ERC20: balanceOf + approve
72
78
  const ERC20_ABI = [
@@ -84,7 +90,8 @@ const ADDRESS_BOOK_KEYS = {
84
90
  processorRegistry: 'processor_registry',
85
91
  controller: 'controller',
86
92
  token: 'sentio_token',
87
- billing: 'billing'
93
+ billing: 'billing',
94
+ databases: 'databases'
88
95
  } as const
89
96
 
90
97
  interface ResolvedAddresses {
@@ -93,6 +100,7 @@ interface ResolvedAddresses {
93
100
  controller: string
94
101
  token: string
95
102
  billing: string
103
+ databases: string
96
104
  }
97
105
 
98
106
  let cachedAddresses: ResolvedAddresses | undefined
@@ -122,19 +130,21 @@ export async function resolveNetworkAddresses(config: SentioNetworkConfig): Prom
122
130
  }
123
131
  }
124
132
 
125
- const [processorRegistry, controller, token, billing] = await Promise.all([
133
+ const [processorRegistry, controller, token, billing, databases] = await Promise.all([
126
134
  resolveAddress(ADDRESS_BOOK_KEYS.processorRegistry),
127
135
  resolveAddress(ADDRESS_BOOK_KEYS.controller),
128
136
  resolveAddress(ADDRESS_BOOK_KEYS.token),
129
- resolveAddress(ADDRESS_BOOK_KEYS.billing)
137
+ resolveAddress(ADDRESS_BOOK_KEYS.billing),
138
+ resolveAddress(ADDRESS_BOOK_KEYS.databases)
130
139
  ])
131
140
 
132
141
  console.log(chalk.gray(`ProcessorRegistry: ${processorRegistry}`))
133
142
  console.log(chalk.gray(`Controller: ${controller}`))
134
143
  console.log(chalk.gray(`ST Token: ${token}`))
135
144
  console.log(chalk.gray(`Billing: ${billing}`))
145
+ console.log(chalk.gray(`Databases: ${databases}`))
136
146
 
137
- cachedAddresses = { addressBook: addressBookAddr, processorRegistry, controller, token, billing }
147
+ cachedAddresses = { addressBook: addressBookAddr, processorRegistry, controller, token, billing, databases }
138
148
  return cachedAddresses
139
149
  }
140
150
 
@@ -207,6 +217,37 @@ export async function uploadToIPFS(fileBuffer: Buffer, ipfsUrl: string): Promise
207
217
  return result.Hash
208
218
  }
209
219
 
220
+ // --- Tx Helpers ---
221
+
222
+ async function submitAndWait(
223
+ explorerUrl: string,
224
+ label: string,
225
+ txPromise: Promise<ethers.TransactionResponse>
226
+ ): Promise<ethers.TransactionResponse> {
227
+ let tx: ethers.TransactionResponse
228
+ try {
229
+ tx = await txPromise
230
+ } catch (err: any) {
231
+ throw new Error(`${label} failed to submit: ${err.shortMessage ?? err.message}`)
232
+ }
233
+
234
+ console.log(chalk.gray(` Tx hash: ${explorerUrl}/tx/${tx.hash}`))
235
+ console.log(chalk.blue('Waiting for confirmation...'))
236
+
237
+ let receipt: ethers.TransactionReceipt | null
238
+ try {
239
+ receipt = await tx.wait()
240
+ } catch (err: any) {
241
+ throw new Error(`${label} failed: ${err.shortMessage ?? err.message}. Tx: ${explorerUrl}/tx/${tx.hash}`)
242
+ }
243
+
244
+ if (!receipt || receipt.status === 0) {
245
+ throw new Error(`${label} transaction reverted. Tx: ${explorerUrl}/tx/${tx.hash}`)
246
+ }
247
+
248
+ return tx
249
+ }
250
+
210
251
  // --- Contract Interactions ---
211
252
 
212
253
  export interface OnChainProcessor {
@@ -260,17 +301,45 @@ export async function deleteProcessorOnChain(
260
301
  const registry = new ethers.Contract(addresses.processorRegistry, PROCESSOR_REGISTRY_ABI, signer)
261
302
 
262
303
  console.log(chalk.blue('Deleting existing processor on-chain...'))
263
- const tx = await registry.deleteProcessor(processorId)
264
- console.log(chalk.gray(` Tx hash: ${tx.hash}`))
265
- console.log(chalk.blue('Waiting for confirmation...'))
304
+ const tx = await submitAndWait(config.explorerUrl, 'deleteProcessor', registry.deleteProcessor(processorId))
305
+ console.log(chalk.green(`Processor deleted. Tx: ${config.explorerUrl}/tx/${tx.hash}`))
306
+ await waitForProcessorDatabaseCleanup(addresses, processorId, provider)
307
+
308
+ return tx.hash
309
+ }
310
+
311
+ async function waitForProcessorDatabaseCleanup(
312
+ addresses: ResolvedAddresses,
313
+ processorId: string,
314
+ provider: ethers.JsonRpcProvider,
315
+ timeoutMs = 120_000,
316
+ pollIntervalMs = 5_000
317
+ ): Promise<void> {
318
+ const databases = new ethers.Contract(addresses.databases, DATABASES_ABI, provider)
319
+
320
+ // getProcessorDatabases has no active check — returns all db IDs still in storage.
321
+ // Only when this returns empty is it safe to recreate databases with the same IDs.
322
+ const dbIds: string[] = await databases.getProcessorDatabases(processorId)
323
+ if (dbIds.length === 0) {
324
+ return
325
+ }
266
326
 
267
- const receipt = await tx.wait()
268
- if (receipt.status === 0) {
269
- throw new Error(`deleteProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`)
327
+ console.log(chalk.blue(`Waiting for ${dbIds.length} replica database(s) to be cleaned up...`))
328
+
329
+ const deadline = Date.now() + timeoutMs
330
+ while (Date.now() < deadline) {
331
+ await new Promise((resolve) => setTimeout(resolve, pollIntervalMs))
332
+
333
+ const remaining: string[] = await databases.getProcessorDatabases(processorId)
334
+ if (remaining.length === 0) {
335
+ console.log(chalk.green('All replica databases cleaned up.'))
336
+ return
337
+ }
338
+
339
+ console.log(chalk.gray(` ${remaining.length} replica database(s) still pending cleanup...`))
270
340
  }
271
341
 
272
- console.log(chalk.green(`Processor deleted. Tx: ${config.explorerUrl}/tx/${tx.hash}`))
273
- return tx.hash
342
+ throw new Error(`Timeout: processor databases not cleaned up within ${timeoutMs / 1000}s`)
274
343
  }
275
344
 
276
345
  export async function createProcessorOnChain(
@@ -304,15 +373,11 @@ export async function createProcessorOnChain(
304
373
  console.log(chalk.gray(` Chains: ${requiredChainIds.join(', ')}`))
305
374
  console.log(chalk.gray(` SDK Version: ${sdkVersion}`))
306
375
 
307
- const tx = await registry.createProcessor(processorId, source, requireChains, sdkVersion)
308
- console.log(chalk.gray(` Tx hash: ${tx.hash}`))
309
- console.log(chalk.blue('Waiting for confirmation...'))
310
-
311
- const receipt = await tx.wait()
312
- if (receipt.status === 0) {
313
- throw new Error(`createProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`)
314
- }
315
-
376
+ const tx = await submitAndWait(
377
+ config.explorerUrl,
378
+ 'createProcessor',
379
+ registry.createProcessor(processorId, source, requireChains, sdkVersion)
380
+ )
316
381
  console.log(chalk.green(`Processor created. Tx: ${config.explorerUrl}/tx/${tx.hash}`))
317
382
  return tx.hash
318
383
  }
@@ -329,15 +394,7 @@ export async function startProcessorOnChain(
329
394
  const controller = new ethers.Contract(addresses.controller, CONTROLLER_ABI, signer)
330
395
 
331
396
  console.log(chalk.blue('Starting processor on-chain...'))
332
- const tx = await controller.startProcessor(processorId)
333
- console.log(chalk.gray(` Tx hash: ${tx.hash}`))
334
- console.log(chalk.blue('Waiting for confirmation...'))
335
-
336
- const receipt = await tx.wait()
337
- if (receipt.status === 0) {
338
- throw new Error(`startProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`)
339
- }
340
-
397
+ const tx = await submitAndWait(config.explorerUrl, 'startProcessor', controller.startProcessor(processorId))
341
398
  console.log(chalk.green(`Processor started. Tx: ${config.explorerUrl}/tx/${tx.hash}`))
342
399
  return tx.hash
343
400
  }
@@ -353,16 +410,15 @@ export async function stopProcessorOnChain(
353
410
 
354
411
  const controller = new ethers.Contract(addresses.controller, CONTROLLER_ABI, signer)
355
412
 
356
- console.log(chalk.blue('Stopping processor on-chain...'))
357
- const tx = await controller.stopProcessor(processorId)
358
- console.log(chalk.gray(` Tx hash: ${tx.hash}`))
359
- console.log(chalk.blue('Waiting for confirmation...'))
360
-
361
- const receipt = await tx.wait()
362
- if (receipt.status === 0) {
363
- throw new Error(`stopProcessor transaction failed. Tx: ${config.explorerUrl}/tx/${tx.hash}`)
413
+ // stopProcessor reverts with ProcessorNotAllocated if the processor has no active allocations
414
+ const allocations: unknown[] = await controller.getAllocations(processorId)
415
+ if (allocations.length === 0) {
416
+ console.log(chalk.gray('Processor has no allocations, skipping stopProcessor.'))
417
+ return ''
364
418
  }
365
419
 
420
+ console.log(chalk.blue('Stopping processor on-chain...'))
421
+ const tx = await submitAndWait(config.explorerUrl, 'stopProcessor', controller.stopProcessor(processorId))
366
422
  console.log(chalk.green(`Processor stopped. Tx: ${config.explorerUrl}/tx/${tx.hash}`))
367
423
  return tx.hash
368
424
  }
@@ -390,8 +446,10 @@ export async function confirmNoPlatformUpload(
390
446
  chalk.yellow(
391
447
  ' ⚠ Your Billing balance is 0. Indexing fees are charged from the Billing contract.\n' +
392
448
  ' You must deposit ST tokens into the Billing contract before your processor can run.\n' +
393
- ` Use: cast send ${addresses.token} "approve(address,uint256)" ${addresses.billing} <amount> --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY\n` +
394
- ` cast send ${addresses.billing} "deposit(uint256)" <amount> --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY`
449
+ ' Example (replace 100 with your desired ST amount):\n' +
450
+ ` export AMOUNT=$(cast to-wei 100 ether)\n` +
451
+ ` cast send ${addresses.token} "approve(address,uint256)" ${addresses.billing} $AMOUNT --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY\n` +
452
+ ` cast send ${addresses.billing} "deposit(uint256)" $AMOUNT --rpc-url ${networkConfig.rpcUrl} --private-key $PRIVATE_KEY`
395
453
  )
396
454
  )
397
455
  }