diff --git a/.env.example b/.env.example index 17f7da5..a0cdc17 100644 --- a/.env.example +++ b/.env.example @@ -1,18 +1,2 @@ -# Example .env for BlazeJob Web3/FinTech/Solana/Email/Cosmos -PRIVATE_KEY=0xYOUR_PRIVATE_KEY -RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_KEY - -# Solana -SOLANA_SECRET_KEY=your_solana_secret_key_base58 -SOLANA_RPC_URL=https://api.mainnet-beta.solana.com - -# Cosmos -COSMOS_MNEMONIC="your cosmos mnemonic phrase" -COSMOS_RPC_URL=https://rpc.cosmos.network:26657 - -# Email SMTP -SMTP_HOST=smtp.example.com -SMTP_PORT=587 -SMTP_USER=your_smtp_user -SMTP_PASS=your_smtp_password -EMAIL_FROM=no-reply@example.com +# Example .env for BlazeJob +# Add your custom environment variables here as needed diff --git a/README.md b/README.md index 0e1877e..00789dc 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,11 @@ Use it as a library in your code to schedule, execute, and manage asynchronous t # Supported Connectors -BlazerJob currently supports only the following connectors for actual execution: +BlazerJob currently supports the following connector: -| Connector Type | Status | Description | -|---------------|---------------|------------------------------------------------------------------| -| `cosmos` | Supported | Send tokens, query balances/transactions, batch Cosmos queries | -| `http` | Supported | Generic HTTP requests (GET, POST, etc.) | -| `shell` | Not supported | Present in types, but not executed (ignored/logged only) | -| `onchain` | Not supported | Present in types, but not executed (ignored/logged only) | -| `solana` | Not supported | Present in types, but not executed (ignored/logged only) | -| `email` | Not supported | Present in types, but not executed (ignored/logged only) | -| `fintech` | Not supported | Present in types, but not executed (ignored/logged only) | - -> Only tasks of type `cosmos` and `http` are actually executed by BlazerJob. All other types are reserved for future extensions or compatibility, but are currently ignored or simply logged by the server. +| Connector Type | Description | +|---------------|------------------------------------------------| +| `http` | Generic HTTP requests (GET, POST, etc.) | ## 1. Custom Tasks (Arbitrary JavaScript/TypeScript) @@ -43,6 +35,36 @@ jobs.schedule(async () => { jobs.start(); ``` +### Storage Options + +BlazerJob supports two storage modes: + +#### Memory Storage (Default) +BlazerJob uses **in-memory storage** by default for maximum performance. Tasks are stored in RAM using SQLite's `:memory:` mode and are lost when the process restarts. + +```typescript +const jobs = new BlazeJob({ + concurrency: 16 +}); +``` + +**Use case**: Ideal for testing, temporary tasks, or when persistence is not required. + +#### SQLite File Storage (Persistent) +For persistent task storage across process restarts, use SQLite file storage: + +```typescript +const jobs = new BlazeJob({ + storage: 'sqlite', + dbPath: './tasks.db', + concurrency: 16 +}); +``` + +**Use case**: Production environments where task persistence is required. + +> **Note**: Custom JavaScript/TypeScript task functions are always stored in memory (via `Map`), regardless of storage mode. Only task metadata and configurations are persisted to SQLite. + --- ## 2. HTTP Tasks (API Calls) @@ -77,51 +99,6 @@ jobs.schedule(async () => {}, { --- -## 3. Cosmos Tasks (Blockchain) - -BlazerJob supports Cosmos blockchain tasks for sending tokens, querying balances, and more. - -- **Accepted type**: `cosmos` -- **Features**: - - Token transfer (sendTokens) - - Balance queries, transactions (tx), and custom queries - - Batch Cosmos queries via `scheduleManyCosmosQueries` - -### Example: Cosmos Balance Query -```typescript -jobs.schedule(async () => {}, { - runAt: new Date(), - type: 'cosmos', - config: JSON.stringify({ - queryType: 'balance', - queryParams: { address: 'cosmos1...' } - }) -}); -``` - -### Example: Send Cosmos Tokens -```typescript -jobs.schedule(async () => {}, { - runAt: new Date(), - type: 'cosmos', - config: JSON.stringify({ - to: 'cosmos1...', - amount: '100000', - denom: 'uatom', - mnemonic: process.env.COSMOS_MNEMONIC, - chainId: 'cosmoshub-4', - rpcUrl: process.env.COSMOS_RPC_URL - }) -}); -``` - -## Required Environment Variables -- `COSMOS_MNEMONIC` – Cosmos mnemonic -- `COSMOS_RPC_URL` – Cosmos RPC endpoint - -## Other Task Types -Any type other than `cosmos` (e.g., `shell`, `onchain`, `solana`, `email`, `fintech`, `http`) will be ignored and simply logged. To extend, you will need to reactivate or develop the corresponding connector. - ## CLI BlazerJob provides a CLI to easily manage your scheduled tasks: @@ -130,8 +107,8 @@ BlazerJob provides a CLI to easily manage your scheduled tasks: # Show help npx ts-node src/bin/cli.ts help -# Schedule a task (e.g., shell) -npx ts-node src/bin/cli.ts schedule --type shell --cmd "echo hello" --runAt "2025-01-01T00:00:00Z" +# Schedule a task (e.g., http) +npx ts-node src/bin/cli.ts schedule --type http --runAt "2025-01-01T00:00:00Z" # List tasks (default blazerjob.db) npx ts-node src/bin/cli.ts list @@ -170,8 +147,7 @@ Shows tasks only from the default database (`blazerjob.db`). #### `schedule` Schedules a new task. Available options: -- `--type`: Task type (`cosmos`) -- `--cmd`: Command to execute (for cosmos tasks) +- `--type`: Task type (`http`) - `--runAt`: Execution time (default: now) - `--interval`: Repeat interval in ms (optional) - `--priority`: Task priority (optional) @@ -183,6 +159,43 @@ Deletes a task by its ID. --- +## HTTP Server + +BlazerJob includes a built-in HTTP server (Fastify) for managing tasks via REST API. + +### Starting the Server + +```typescript +import { startServer } from 'blazerjob'; + +await startServer(9000); // Server runs on http://localhost:9000 +``` + +### API Endpoints + +- **GET /tasks**: List all scheduled tasks +- **POST /task**: Schedule a new task (JSON body with runAt, type, config, etc.) +- **DELETE /task/:id**: Delete a task by ID + +> **Important**: The HTTP server uses **in-memory storage** by default. Tasks will be lost when the server restarts. For persistence, modify the server initialization to use `storage: 'sqlite'`. + +### Example: Schedule via HTTP + +```bash +curl -X POST http://localhost:9000/task \ + -H "Content-Type: application/json" \ + -d '{ + "runAt": "2025-01-01T00:00:00Z", + "type": "http", + "config": { + "url": "https://api.example.com", + "method": "GET" + } + }' +``` + +--- + ## Installation ```bash @@ -195,7 +208,7 @@ npm install blazerjob ## Performance & tuning -- SQLite WAL enabled by default (`journal_mode = WAL`) to avoid reader/writer blocking. +- SQLite WAL enabled by default for file storage (`journal_mode = WAL`) to avoid reader/writer blocking (not applied to in-memory storage). - Concurrency configured via `concurrency` option (default `1` for backward compatibility). - Scheduler interval lowered to 50 ms + immediate drain when all slots are used. @@ -248,8 +261,12 @@ COSMOS_RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_KEY ## API Reference -### `new BlazeJob(options: { dbPath: string })` -- **dbPath**: Path to the SQLite database file where tasks are stored. +### `new BlazeJob(options: BlazeJobOptions)` +- **storage?**: Storage mode - `'memory'` (default, in-memory) or `'sqlite'` (persistent file storage) +- **dbPath?**: Path to the SQLite database file (only used when `storage: 'sqlite'`, defaults to `'blazerjob.db'`) +- **concurrency?**: Number of concurrent tasks to execute (default: `1`) +- **autoExit?**: Automatically exit process when all periodic tasks complete (default: `false`) +- **encryptionKey?**: Custom encryption key for task configs (default: uses `BLAZERJOB_ENCRYPTION_KEY` env var or a default key) ### schedule(taskFn: () => Promise, opts: { ... }): number - **taskFn**: Asynchronous function to execute (your JS/TS code). @@ -258,9 +275,12 @@ COSMOS_RPC_URL=https://mainnet.infura.io/v3/YOUR_INFURA_KEY - `interval?`: (optional) Number of milliseconds between executions (for recurring tasks). - `priority?`: (optional) Higher priority tasks run first. - `retriesLeft?`: (optional) Number of retry attempts if the task fails. - - `type`: Task type (e.g. `'cosmos'`). + - `type`: Task type (e.g. `'http'`). - `config?`: (optional) Additional configuration for the task, see [TaskConfig](#taskconfig-interface) below. - `webhookUrl?`: (optional) If set, BlazerJob will POST a JSON payload to this URL on task success, failure, or retry. + - `maxRuns?`: (optional) Maximum number of executions for periodic tasks. + - `maxDurationMs?`: (optional) Maximum duration in milliseconds for periodic tasks. + - `onEnd?`: (optional) Callback function called when task completes with stats `{ runCount, errorCount }`. Returns the ID of the created task. @@ -270,9 +290,15 @@ Returns the ID of the created task. ### stop(): void - Stops the scheduler loop (does not close the database). +### deleteTask(taskId: number): void +- Deletes a task by ID and cleans up associated memory (task functions, stats, error counts). + +### getTasks(): any[] +- Returns all tasks from the database with decrypted configurations. + --- -## Arrêt automatique du process (option autoExit) +## Automatic Process Exit (autoExit option) For testing or scripting purposes, you can configure BlazeJob to automatically exit the process as soon as all periodic tasks (with `maxRuns` or `maxDurationMs`) are completed: @@ -301,7 +327,7 @@ jobs.onAllTasksEnded(() => { }); ``` -## Bonnes pratiques +## Best Practices - **Enable `autoExit` only for scripts or tests.** - **In production/server, leave `autoExit` as `false` (the default) to prevent unexpected process termination.** @@ -309,20 +335,16 @@ jobs.onAllTasksEnded(() => { ## TaskConfig Interface -BlazerJob supports the following task types and config structures: +BlazerJob supports the following task type and config structure: ```typescript -type TaskType = 'cosmos'; - -interface CosmosTaskConfig { - queryType: 'balance' | 'tx' | 'custom'; - queryParams?: Record; - to?: string; - amount?: string; - denom?: string; - mnemonic?: string; - chainId?: string; - rpcUrl?: string; +type TaskType = 'http'; + +interface HttpTaskConfig { + url: string; + method?: string; + headers?: Record; + body?: any; } ``` @@ -370,53 +392,6 @@ If you set `webhookUrl` when scheduling a task, BlazerJob will POST a JSON paylo --- -## Exemple : requête simple Cosmos (balance ou tx) - -Here’s how to use BlazerJob to execute a simple query on Cosmos (for example, to get the balance of an address or transaction info): - -### 1. Query balance (solde) -```typescript -import { BlazeJob } from 'blazerjob'; - -const jobs = new BlazeJob({ dbPath: './tasks.db' }); - -jobs.schedule(async () => {}, { - runAt: new Date(), - type: 'cosmos', - config: JSON.stringify({ - queryType: 'balance', - queryParams: { address: 'cosmos1...' }, - // rpcUrl peut venir de .env ou être spécifié ici - }) -}); - -jobs.start(); -``` - -### 2. Query transaction (tx) -```typescript -import { BlazeJob } from 'blazerjob'; - -const jobs = new BlazeJob({ dbPath: './tasks.db' }); - -jobs.schedule(async () => {}, { - runAt: new Date(), - type: 'cosmos', - config: JSON.stringify({ - queryType: 'tx', - queryParams: { hash: '0x...' }, - // rpcUrl peut venir de .env ou être spécifié ici - }) -}); - -jobs.start(); -``` - -- Results are logged on the server side (console). -- For a custom query, use `queryType: 'custom'` and adapt `queryParams` as needed. - ---- - ## Example: Scheduled HTTP request (http connector) BlazerJob now lets you schedule an HTTP API request (using fetch): @@ -441,7 +416,7 @@ jobs.schedule(async () => {}, { jobs.start(); ``` -### Exemple : requête GET +### Example: GET Request ```typescript jobs.schedule(async () => {}, { runAt: new Date(), @@ -453,7 +428,7 @@ jobs.schedule(async () => {}, { }); ``` -### Exemple : requête GET toutes les 10 secondes avec log de la réponse +### Example: GET Request Every 10 Seconds with Response Logging ```typescript import { BlazeJob } from 'blazerjob'; @@ -462,7 +437,7 @@ const jobs = new BlazeJob({ dbPath: './tasks.db' }); jobs.schedule(async () => {}, { runAt: new Date(), - interval: 10000, // toutes les 10 secondes + interval: 10000, // every 10 seconds type: 'http', config: JSON.stringify({ url: 'https://api.coindesk.com/v1/bpi/currentprice.json', @@ -473,7 +448,7 @@ jobs.schedule(async () => {}, { jobs.start(); ``` -> Pour logguer la réponse côté serveur, modifie la fonction dans le code source : +> To log the response on the server side, modify the function in the source code: > > ```typescript > taskFn = async () => { @@ -489,100 +464,6 @@ jobs.start(); --- -## Cosmos Module: Centralized Logic - -BlazerJob centralizes all Cosmos blockchain logic in the `src/cosmos/` module. This module exposes helpers for scheduling, querying, and sending tokens on Cosmos chains (CosmJS-compatible). - -### Features -- **Batch scheduling**: Schedule hundreds of Cosmos queries or transactions in one call. -- **Unified helpers**: Query balances, transactions, and send tokens using a simple API. -- **Environment support**: Cosmos mnemonic and RPC URL can be set in `.env` or provided per task. -- **Error handling**: Centralized error helpers for Cosmos-specific issues (rate limits, etc). -- **TypeScript-first**: All helpers are typed for safe use. - -### Example: Batch Cosmos Queries -```typescript -import { BlazeJob } from 'blazerjob'; -import { scheduleManyCosmosQueries } from './src/cosmos'; - -const job = new BlazeJob({ dbPath: './tasks.db' }); - -await scheduleManyCosmosQueries(job, { - addresses: [ - 'cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh', - 'cosmos1c9ye9j3p4e9w8f7j2k7l6k8e8f7g9h5d3j8k7h', - ], - count: 100, - queryType: 'balance', - intervalMs: 100, -}); -job.start(); -``` - -### Example: Query Cosmos Balance or Transaction -```typescript -import { getBalance, getTx } from './src/cosmos'; - -const balances = await getBalance(process.env.COSMOS_RPC_URL, 'cosmos1...'); -const tx = await getTx(process.env.COSMOS_RPC_URL, '0x...'); -``` - -### Example: Send Tokens on Cosmos -```typescript -import { sendTokens } from './src/cosmos'; - -await sendTokens({ - rpcUrl: process.env.COSMOS_RPC_URL, - mnemonic: process.env.COSMOS_MNEMONIC, - to: 'cosmos1destination...', - amount: '100000', - denom: 'uatom', - chainId: 'cosmoshub-4', -}); -``` - -### Environment Variables -- `COSMOS_MNEMONIC` – Cosmos wallet mnemonic -- `COSMOS_RPC_URL` – Cosmos RPC endpoint - -See `.env.example` for details. - ---- - -## Cosmos Helpers (API) - -BlazerJob exposes various Cosmos helpers in `src/cosmos/queries.ts`: - -- `getBalance(rpcUrl, address)`: Gets the balance of an address -- `getTx(rpcUrl, hash)`: Retrieves a transaction by hash -- `sendTokens({rpcUrl, mnemonic, to, amount, denom, ...})`: Sends ATOM or other tokens -- `getLatestBlockHeight(rpcUrl)`: Gets the latest block height -- `getBlockByHeight(rpcUrl, height)`: Gets block details by height -- `getAccountInfo(rpcUrl, address)`: Gets account info (account number, sequence, ...) -- `getAllBalances(rpcUrl, address)`: Gets all balances for an address -- `getChainId(rpcUrl)`: Gets the chain ID -- `getTransactionByHash(rpcUrl, hash)`: Alias for `getTx` -- `searchTxs(rpcUrl, query)`: Searches transactions (by address, event, ...) -- `broadcastTx(rpcUrl, txBytes)`: Broadcasts a signed transaction -- `getDelegation(rpcUrl, delegator, validator)`: Gets specific staking delegation - -> Some advanced queries (validators, supply, node info) require a REST/LCD endpoint (not included in StargateClient, see cosmjs/launchpad/lcd or fetch). - -#### Advanced Usage Example -```typescript -import { - getBalance, getTx, sendTokens, getLatestBlockHeight, getBlockByHeight, - getAccountInfo, getAllBalances, getChainId, getTransactionByHash, searchTxs, - broadcastTx, getDelegation -} from './src/cosmos'; - -const balances = await getAllBalances(process.env.COSMOS_RPC_URL, 'cosmos1...'); -const block = await getBlockByHeight(process.env.COSMOS_RPC_URL, 1234567); -const delegation = await getDelegation(process.env.COSMOS_RPC_URL, 'cosmos1delegator...', 'cosmosvaloper1validator...'); -``` - ---- - ## License GNU diff --git a/package-lock.json b/package-lock.json index c134c4b..2159536 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,188 +1,31 @@ { "name": "blazerjob", - "version": "1.3.1", + "version": "1.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "blazerjob", - "version": "1.3.1", + "version": "1.4.0", "license": "ISC", "dependencies": { - "@cosmjs/proto-signing": "^0.33.1", - "@cosmjs/stargate": "^0.33.1", "@fastify/formbody": "^8.0.2", "better-sqlite3": "^11.9.1", "dotenv": "^16.5.0", "fastify": "^5.3.2", - "node-fetch": "^2.7.0", - "protobufjs": "^7.5.0" + "node-fetch": "^2.7.0" }, "bin": { "blazerjob": "dist/bin/cli.js" }, "devDependencies": { "@types/better-sqlite3": "^7.6.13", - "@types/bs58": "^4.0.4", "@types/node": "^22.15.3", "@types/node-fetch": "^2.6.12", "ts-node": "^10.9.2", "typescript": "^5.8.3" } }, - "node_modules/@cosmjs/amino": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/amino/-/amino-0.33.1.tgz", - "integrity": "sha512-WfWiBf2EbIWpwKG9AOcsIIkR717SY+JdlXM/SL/bI66BdrhniAF+/ZNis9Vo9HF6lP2UU5XrSmFA4snAvEgdrg==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/crypto": "^0.33.1", - "@cosmjs/encoding": "^0.33.1", - "@cosmjs/math": "^0.33.1", - "@cosmjs/utils": "^0.33.1" - } - }, - "node_modules/@cosmjs/crypto": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/crypto/-/crypto-0.33.1.tgz", - "integrity": "sha512-U4kGIj/SNBzlb2FGgA0sMR0MapVgJUg8N+oIAiN5+vl4GZ3aefmoL1RDyTrFS/7HrB+M+MtHsxC0tvEu4ic/zA==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/encoding": "^0.33.1", - "@cosmjs/math": "^0.33.1", - "@cosmjs/utils": "^0.33.1", - "@noble/hashes": "^1", - "bn.js": "^5.2.0", - "elliptic": "^6.6.1", - "libsodium-wrappers-sumo": "^0.7.11" - } - }, - "node_modules/@cosmjs/encoding": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/encoding/-/encoding-0.33.1.tgz", - "integrity": "sha512-nuNxf29fUcQE14+1p//VVQDwd1iau5lhaW/7uMz7V2AH3GJbFJoJVaKvVyZvdFk+Cnu+s3wCqgq4gJkhRCJfKw==", - "license": "Apache-2.0", - "dependencies": { - "base64-js": "^1.3.0", - "bech32": "^1.1.4", - "readonly-date": "^1.0.0" - } - }, - "node_modules/@cosmjs/json-rpc": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/json-rpc/-/json-rpc-0.33.1.tgz", - "integrity": "sha512-T6VtWzecpmuTuMRGZWuBYHsMF/aznWCYUt/cGMWNSz7DBPipVd0w774PKpxXzpEbyt5sr61NiuLXc+Az15S/Cw==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/stream": "^0.33.1", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/math": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/math/-/math-0.33.1.tgz", - "integrity": "sha512-ytGkWdKFCPiiBU5eqjHNd59djPpIsOjbr2CkNjlnI1Zmdj+HDkSoD9MUGpz9/RJvRir5IvsXqdE05x8EtoQkJA==", - "license": "Apache-2.0", - "dependencies": { - "bn.js": "^5.2.0" - } - }, - "node_modules/@cosmjs/proto-signing": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/proto-signing/-/proto-signing-0.33.1.tgz", - "integrity": "sha512-Sv4W+MxX+0LVnd+2rU4Fw1HRsmMwSVSYULj7pRkij3wnPwUlTVoJjmKFgKz13ooIlfzPrz/dnNjGp/xnmXChFQ==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/amino": "^0.33.1", - "@cosmjs/crypto": "^0.33.1", - "@cosmjs/encoding": "^0.33.1", - "@cosmjs/math": "^0.33.1", - "@cosmjs/utils": "^0.33.1", - "cosmjs-types": "^0.9.0" - } - }, - "node_modules/@cosmjs/socket": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/socket/-/socket-0.33.1.tgz", - "integrity": "sha512-KzAeorten6Vn20sMiM6NNWfgc7jbyVo4Zmxev1FXa5EaoLCZy48cmT3hJxUJQvJP/lAy8wPGEjZ/u4rmF11x9A==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/stream": "^0.33.1", - "isomorphic-ws": "^4.0.1", - "ws": "^7", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/socket/node_modules/ws": { - "version": "7.5.10", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", - "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", - "license": "MIT", - "engines": { - "node": ">=8.3.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@cosmjs/stargate": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/stargate/-/stargate-0.33.1.tgz", - "integrity": "sha512-CnJ1zpSiaZgkvhk+9aTp5IPmgWn2uo+cNEBN8VuD9sD6BA0V4DMjqe251cNFLiMhkGtiE5I/WXFERbLPww3k8g==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/amino": "^0.33.1", - "@cosmjs/encoding": "^0.33.1", - "@cosmjs/math": "^0.33.1", - "@cosmjs/proto-signing": "^0.33.1", - "@cosmjs/stream": "^0.33.1", - "@cosmjs/tendermint-rpc": "^0.33.1", - "@cosmjs/utils": "^0.33.1", - "cosmjs-types": "^0.9.0" - } - }, - "node_modules/@cosmjs/stream": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/stream/-/stream-0.33.1.tgz", - "integrity": "sha512-bMUvEENjeQPSTx+YRzVsWT1uFIdHRcf4brsc14SOoRQ/j5rOJM/aHfsf/BmdSAnYbdOQ3CMKj/8nGAQ7xUdn7w==", - "license": "Apache-2.0", - "dependencies": { - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/tendermint-rpc": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/tendermint-rpc/-/tendermint-rpc-0.33.1.tgz", - "integrity": "sha512-22klDFq2MWnf//C8+rZ5/dYatr6jeGT+BmVbutXYfAK9fmODbtFcumyvB6uWaEORWfNukl8YK1OLuaWezoQvxA==", - "license": "Apache-2.0", - "dependencies": { - "@cosmjs/crypto": "^0.33.1", - "@cosmjs/encoding": "^0.33.1", - "@cosmjs/json-rpc": "^0.33.1", - "@cosmjs/math": "^0.33.1", - "@cosmjs/socket": "^0.33.1", - "@cosmjs/stream": "^0.33.1", - "@cosmjs/utils": "^0.33.1", - "axios": "^1.6.0", - "readonly-date": "^1.0.0", - "xstream": "^11.14.0" - } - }, - "node_modules/@cosmjs/utils": { - "version": "0.33.1", - "resolved": "https://registry.npmjs.org/@cosmjs/utils/-/utils-0.33.1.tgz", - "integrity": "sha512-UnLHDY6KMmC+UXf3Ufyh+onE19xzEXjT4VZ504Acmk4PXxqyvG4cCPprlKUFnGUX7f0z8Or9MAOHXBx41uHBcg==", - "license": "Apache-2.0" - }, "node_modules/@cspotcode/source-map-support": { "version": "0.8.1", "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", @@ -335,82 +178,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@noble/hashes": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", - "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -449,21 +216,11 @@ "@types/node": "*" } }, - "node_modules/@types/bs58": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/bs58/-/bs58-4.0.4.tgz", - "integrity": "sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*", - "base-x": "^3.0.6" - } - }, "node_modules/@types/node": { "version": "22.15.5", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.15.5.tgz", "integrity": "sha512-e3r3tiKxBr9e/+5uNRkF+K/2gnhR2V/EOY/gxNXviodSa3DYSqkYUR2Xp05l2uS/A7j864m8IQvdf+itWNIg1Q==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -556,6 +313,7 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "dev": true, "license": "MIT" }, "node_modules/atomic-sleep": { @@ -577,27 +335,6 @@ "fastq": "^1.17.1" } }, - "node_modules/axios": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", - "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.4", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/base-x": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/base-x/-/base-x-3.0.11.tgz", - "integrity": "sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/base64-js": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", @@ -618,12 +355,6 @@ ], "license": "MIT" }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, "node_modules/better-sqlite3": { "version": "11.9.1", "resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.9.1.tgz", @@ -655,18 +386,6 @@ "readable-stream": "^3.4.0" } }, - "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", - "license": "MIT" - }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "license": "MIT" - }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -695,6 +414,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -714,6 +434,7 @@ "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" @@ -731,12 +452,6 @@ "node": ">=18" } }, - "node_modules/cosmjs-types": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/cosmjs-types/-/cosmjs-types-0.9.0.tgz", - "integrity": "sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==", - "license": "Apache-2.0" - }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -768,44 +483,11 @@ "node": ">=4.0.0" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "license": "MIT", - "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "dev": true, "license": "MIT", "engines": { "node": ">=0.4.0" @@ -855,6 +537,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.1", @@ -865,27 +548,6 @@ "node": ">= 0.4" } }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "license": "MIT" - }, "node_modules/end-of-stream": { "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", @@ -899,6 +561,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -908,6 +571,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -917,6 +581,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0" @@ -929,6 +594,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, "license": "MIT", "dependencies": { "es-errors": "^1.3.0", @@ -1087,30 +753,11 @@ "node": ">=20" } }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/form-data": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "dev": true, "license": "MIT", "dependencies": { "asynckit": "^0.4.0", @@ -1133,6 +780,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1142,6 +790,7 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind-apply-helpers": "^1.0.2", @@ -1166,6 +815,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, "license": "MIT", "dependencies": { "dunder-proto": "^1.0.1", @@ -1181,26 +831,11 @@ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", "license": "MIT" }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "license": "MIT", - "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gopd": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1209,22 +844,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1237,6 +861,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, "license": "MIT", "dependencies": { "has-symbols": "^1.0.3" @@ -1248,20 +873,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" @@ -1270,17 +886,6 @@ "node": ">= 0.4" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/ieee754": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", @@ -1322,15 +927,6 @@ "node": ">= 10" } }, - "node_modules/isomorphic-ws": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", - "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==", - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, "node_modules/json-schema-ref-resolver": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/json-schema-ref-resolver/-/json-schema-ref-resolver-2.0.1.tgz", @@ -1356,21 +952,6 @@ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "license": "MIT" }, - "node_modules/libsodium-sumo": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium-sumo/-/libsodium-sumo-0.7.15.tgz", - "integrity": "sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==", - "license": "ISC" - }, - "node_modules/libsodium-wrappers-sumo": { - "version": "0.7.15", - "resolved": "https://registry.npmjs.org/libsodium-wrappers-sumo/-/libsodium-wrappers-sumo-0.7.15.tgz", - "integrity": "sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==", - "license": "ISC", - "dependencies": { - "libsodium-sumo": "^0.7.15" - } - }, "node_modules/light-my-request": { "version": "6.6.0", "resolved": "https://registry.npmjs.org/light-my-request/-/light-my-request-6.6.0.tgz", @@ -1408,12 +989,6 @@ ], "license": "MIT" }, - "node_modules/long": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", - "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", - "license": "Apache-2.0" - }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -1425,6 +1000,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" @@ -1434,6 +1010,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" @@ -1443,6 +1020,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" @@ -1463,18 +1041,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "license": "MIT" - }, "node_modules/minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -1528,15 +1094,6 @@ } } }, - "node_modules/object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, "node_modules/on-exit-leak-free": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/on-exit-leak-free/-/on-exit-leak-free-2.1.2.tgz", @@ -1650,36 +1207,6 @@ ], "license": "MIT" }, - "node_modules/protobufjs": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.5.0.tgz", - "integrity": "sha512-Z2E/kOY1QjoMlCytmexzYfDm/w5fKAiRwpSzGtdnXW1zC88Z2yXazHHrOtwCzn+7wSxyE8PYM4rvVcMphF9sOA==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.2", - "@protobufjs/base64": "^1.1.2", - "@protobufjs/codegen": "^2.0.4", - "@protobufjs/eventemitter": "^1.1.0", - "@protobufjs/fetch": "^1.1.0", - "@protobufjs/float": "^1.0.2", - "@protobufjs/inquire": "^1.1.0", - "@protobufjs/path": "^1.1.2", - "@protobufjs/pool": "^1.1.0", - "@protobufjs/utf8": "^1.1.0", - "@types/node": ">=13.7.0", - "long": "^5.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -1725,12 +1252,6 @@ "node": ">= 6" } }, - "node_modules/readonly-date": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/readonly-date/-/readonly-date-1.0.0.tgz", - "integrity": "sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==", - "license": "Apache-2.0" - }, "node_modules/real-require": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/real-require/-/real-require-0.2.0.tgz", @@ -1937,15 +1458,6 @@ "node": ">=0.10.0" } }, - "node_modules/symbol-observable": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-2.0.3.tgz", - "integrity": "sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==", - "license": "MIT", - "engines": { - "node": ">=0.10" - } - }, "node_modules/tar-fs": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz", @@ -2072,6 +1584,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/util-deprecate": { @@ -2109,38 +1622,6 @@ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "license": "ISC" }, - "node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/xstream": { - "version": "11.14.0", - "resolved": "https://registry.npmjs.org/xstream/-/xstream-11.14.0.tgz", - "integrity": "sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==", - "license": "MIT", - "dependencies": { - "globalthis": "^1.0.1", - "symbol-observable": "^2.0.3" - } - }, "node_modules/yn": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", diff --git a/package.json b/package.json index 04951f1..42b621c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "blazerjob", - "version": "1.4.0", - "description": "TypeScript library for scheduling, executing, and managing asynchronous tasks (custom, HTTP, Cosmos) with a SQLite backend.", + "version": "2.0.1", + "description": "TypeScript library for scheduling, executing, and managing asynchronous tasks (custom, HTTP) with a SQLite backend.", "main": "dist/index.js", "types": "dist/index.d.ts", "bin": { @@ -22,7 +22,6 @@ "typescript", "GNU", "sqlite", - "blockchain", "http", "automation", "cli", @@ -45,20 +44,16 @@ "homepage": "https://github.com/QuenumGerald/BlazerJob#readme", "devDependencies": { "@types/better-sqlite3": "^7.6.13", - "@types/bs58": "^4.0.4", "@types/node": "^22.15.3", "@types/node-fetch": "^2.6.12", "ts-node": "^10.9.2", "typescript": "^5.8.3" }, "dependencies": { - "@cosmjs/proto-signing": "^0.33.1", - "@cosmjs/stargate": "^0.33.1", "@fastify/formbody": "^8.0.2", "better-sqlite3": "^11.9.1", "dotenv": "^16.5.0", "fastify": "^5.3.2", - "node-fetch": "^2.7.0", - "protobufjs": "^7.5.0" + "node-fetch": "^2.7.0" } } diff --git a/src/bin/cli.ts b/src/bin/cli.ts index 0997277..f7dcbaf 100644 --- a/src/bin/cli.ts +++ b/src/bin/cli.ts @@ -75,7 +75,7 @@ async function main() { console.error('Please provide the task id to delete.'); return process.exit(1); } - jobs['db'].prepare('DELETE FROM tasks WHERE id = ?').run(id); + jobs.deleteTask(Number(id)); console.log(`Task ${id} deleted.`); break; } diff --git a/src/cosmos/batch.ts b/src/cosmos/batch.ts deleted file mode 100644 index d8cac57..0000000 --- a/src/cosmos/batch.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { BlazeJob } from '../index'; -import { CosmosBatchOptions } from './types'; - -/** - * Programme facilement un grand nombre de requêtes Cosmos sur une liste d'adresses. - * Les adresses sont utilisées en round-robin. - */ -export async function scheduleManyCosmosQueries(job: BlazeJob, opts: CosmosBatchOptions) { - const { - addresses, - count, - queryType, - intervalMs = 100, - configOverrides = {}, - retriesLeft = 0, - priority = 0, - runAt, - webhookUrl - } = opts; - if (!addresses || addresses.length === 0) throw new Error('addresses must be a non-empty array'); - for (let i = 0; i < count; i++) { - const address = addresses[i % addresses.length]; - const scheduledAt = runAt - ? (runAt instanceof Date ? new Date(runAt.getTime() + i * intervalMs) : new Date(new Date(runAt).getTime() + i * intervalMs)) - : new Date(Date.now() + i * intervalMs); - job.schedule(undefined, { - type: 'cosmos', - runAt: scheduledAt, - priority, - retriesLeft, - webhookUrl, - config: { - queryType, - queryParams: { address }, - ...configOverrides - } - }); - } -} diff --git a/src/cosmos/client.ts b/src/cosmos/client.ts deleted file mode 100644 index 9347080..0000000 --- a/src/cosmos/client.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { SigningStargateClient } from '@cosmjs/stargate'; -import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; - -export async function getStargateClient(rpcUrl: string) { - return SigningStargateClient.connect(rpcUrl); -} - -export async function getSigningClientAndWallet(rpcUrl: string, mnemonic: string, prefix = 'cosmos') { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix }); - const client = await SigningStargateClient.connectWithSigner(rpcUrl, wallet); - return { client, wallet }; -} diff --git a/src/cosmos/config.ts b/src/cosmos/config.ts deleted file mode 100644 index c603a21..0000000 --- a/src/cosmos/config.ts +++ /dev/null @@ -1,6 +0,0 @@ -export function getCosmosConfig(cfg: any = {}): { rpcUrl: string; mnemonic?: string } { - const rpcUrl = cfg.rpcUrl || process.env.COSMOS_RPC_URL; - const mnemonic = cfg.mnemonic || process.env.COSMOS_MNEMONIC; - if (!rpcUrl) throw new Error('No Cosmos rpcUrl (set in config or .env)'); - return { rpcUrl, mnemonic }; -} diff --git a/src/cosmos/errors.ts b/src/cosmos/errors.ts deleted file mode 100644 index 9b173b9..0000000 --- a/src/cosmos/errors.ts +++ /dev/null @@ -1,10 +0,0 @@ -export function handleCosmosError(e: any) { - if (e && typeof e.message === 'string') { - if (e.message.includes('rate limit')) { - console.error('[Cosmos][RateLimit]', e.message); - // Ici, tu pourrais ajouter une logique de retry/backoff - } - // Ajoute ici d'autres gestions d'erreur spécifiques Cosmos - } - throw e; -} diff --git a/src/cosmos/index.ts b/src/cosmos/index.ts deleted file mode 100644 index 2595257..0000000 --- a/src/cosmos/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './client'; -export * from './queries'; -export * from './batch'; -export * from './types'; -export * from './config'; -export * from './errors'; -// Ici on pourra ajouter d'autres exports (helpers, etc) diff --git a/src/cosmos/queries.ts b/src/cosmos/queries.ts deleted file mode 100644 index ee47e93..0000000 --- a/src/cosmos/queries.ts +++ /dev/null @@ -1,131 +0,0 @@ -import { getStargateClient, getSigningClientAndWallet } from './client'; - -/** - * Fabrique une fonction de tâche Cosmos pour BlazeJob (queryType, queryParams...) - */ -export function makeCosmosTaskFn(cfg: any) { - return async () => { - const { queryType, queryParams } = cfg; - console.log('[Cosmos] queryType:', queryType, 'queryParams:', queryParams); - if (!queryType || !queryParams || !queryParams.address) throw new Error('Invalid Cosmos config: missing address'); - const rpcEndpoint = process.env.COSMOS_RPC_URL; - if (!rpcEndpoint) { - throw new Error('COSMOS_RPC_URL is not set in environment variables'); - } - const client = await getStargateClient(rpcEndpoint); - if (queryType === 'balance') { - const balance = await client.getAllBalances(queryParams.address); - console.log('[Cosmos][balance]', balance); - } else if (queryType === 'txs') { - const txs = await client.searchTx(queryParams); - console.log('[Cosmos][txs]', txs); - } else { - throw new Error('Unknown Cosmos query type: ' + queryType); - } - }; -} - -export async function getBalance(rpcUrl: string, address: string) { - const client = await getStargateClient(rpcUrl); - return client.getAllBalances(address); -} - -export async function getTx(rpcUrl: string, hash: string) { - const client = await getStargateClient(rpcUrl); - return client.getTx(hash); -} - -export async function sendTokens({ rpcUrl, mnemonic, to, amount, denom, gas = '200000', memo = '', chainId }: { - rpcUrl: string; - mnemonic: string; - to: string; - amount: string; - denom: string; - gas?: string; - memo?: string; - chainId: string; -}) { - const { client, wallet } = await getSigningClientAndWallet(rpcUrl, mnemonic); - const [account] = await wallet.getAccounts(); - const fee = { - amount: [{ amount: gas, denom }], - gas, - }; - return client.sendTokens(account.address, to, [{ amount, denom }], fee, memo); -} - -/** - * Query the current block height - */ -export async function getLatestBlockHeight(rpcUrl: string) { - const client = await getStargateClient(rpcUrl); - const status = await client.getHeight(); - return status; -} - -/** - * Query a block by height - */ -export async function getBlockByHeight(rpcUrl: string, height: number) { - const client = await getStargateClient(rpcUrl); - return client.getBlock(height); -} - -/** - * Query account info (number, sequence, etc) - */ -export async function getAccountInfo(rpcUrl: string, address: string) { - const client = await getStargateClient(rpcUrl); - return client.getAccount(address); -} - -/** - * Query all balances for an address - */ -export async function getAllBalances(rpcUrl: string, address: string) { - const client = await getStargateClient(rpcUrl); - return client.getAllBalances(address); -} - -/** - * Query chain ID - */ -export async function getChainId(rpcUrl: string) { - const client = await getStargateClient(rpcUrl); - return client.getChainId(); -} - -/** - * Query a transaction by hash (alias for getTx) - */ -export async function getTransactionByHash(rpcUrl: string, hash: string) { - const client = await getStargateClient(rpcUrl); - return client.getTx(hash); -} - -/** - * Query all transactions for an address (using searchTx) - */ -export async function searchTxs(rpcUrl: string, query: any) { - const client = await getStargateClient(rpcUrl); - return client.searchTx(query); -} - -/** - * Broadcast a signed transaction (raw tx) - */ -export async function broadcastTx(rpcUrl: string, txBytes: Uint8Array) { - const client = await getStargateClient(rpcUrl); - return client.broadcastTx(txBytes); -} - -/** - * Query staking delegation for (delegator, validator) - */ -export async function getDelegation(rpcUrl: string, delegatorAddress: string, validatorAddress: string) { - const client = await getStargateClient(rpcUrl); - return client.getDelegation(delegatorAddress, validatorAddress); -} - -// Note: Some advanced queries (validators, supply, node info) require REST endpoints or LCD clients, not StargateClient. -// For those, you can use fetch or cosmjs/launchpad/lcd for more advanced needs. diff --git a/src/cosmos/types.ts b/src/cosmos/types.ts deleted file mode 100644 index af2d5f3..0000000 --- a/src/cosmos/types.ts +++ /dev/null @@ -1,11 +0,0 @@ -export interface CosmosBatchOptions { - addresses: string[]; - count: number; - queryType: string; - intervalMs?: number; - configOverrides?: Record; - retriesLeft?: number; - priority?: number; - runAt?: Date | string; - webhookUrl?: string; -} diff --git a/src/index.ts b/src/index.ts index 0512681..0f88f26 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,15 +6,8 @@ import Fastify, { FastifyInstance, FastifyReply, FastifyRequest } from 'fastify' const Database = require('better-sqlite3'); import fetch from 'node-fetch'; // si node <18 import * as crypto from 'crypto'; -import { TaskType, TaskConfig, CosmosTaskConfig, HttpTaskConfig, ShellTaskConfig } from './types'; -import { SigningStargateClient, StargateClient, coins } from '@cosmjs/stargate'; -import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing'; -import { makeCosmosTaskFn } from './cosmos/queries'; +import { TaskType, TaskConfig, HttpTaskConfig } from './types'; import { makeHttpTaskFn } from './http/queries'; -import { exec } from 'child_process'; -import { promisify } from 'util'; - -const execAsync = promisify(exec); export interface ScheduleExtra { maxRuns?: number; @@ -27,7 +20,8 @@ export type OnTaskEnd = (taskId: number, stats: { runCount: number, errorCount: export type OnAllTasksEnded = () => void; export interface BlazeJobOptions { - dbPath: string; + dbPath?: string; + storage?: 'sqlite' | 'memory'; autoExit?: boolean; concurrency?: number; encryptionKey?: string; @@ -86,8 +80,12 @@ export class BlazeJob { constructor(options: BlazeJobOptions) { this.encryptionKey = getEncryptionKey(options.encryptionKey); - this.db = new Database(options.dbPath); - this.db.pragma('journal_mode = WAL'); + const useMemoryStorage = options.storage !== 'sqlite'; + const dbPath = useMemoryStorage ? ':memory:' : (options.dbPath || 'blazerjob.db'); + this.db = new Database(dbPath); + if (!useMemoryStorage) { + this.db.pragma('journal_mode = WAL'); + } this.autoExit = !!options.autoExit; this.concurrency = options.concurrency || 1; this.db.prepare(` @@ -169,40 +167,25 @@ export class BlazeJob { let taskFn: () => Promise = async () => { }; // Decrypt config before execution if needed const decryptedConfig = decryptConfig(task.config, this.encryptionKey); - // Si la tâche a une fonction JS custom (stockée en mémoire), on l'utilise + // If the task has a custom JS function (stored in memory), use it if (this.taskFns.has(task.id)) { taskFn = this.taskFns.get(task.id)!; - } else if (task.type === 'cosmos') { - const config = typeof decryptedConfig === 'string' ? JSON.parse(decryptedConfig) : decryptedConfig; - let configCopy = JSON.parse(JSON.stringify(config)); // clonage profond - if (typeof configCopy === 'string') { - configCopy = JSON.parse(configCopy); - } - taskFn = makeCosmosTaskFn(configCopy); } else if (task.type === 'http' && decryptedConfig) { let config: any = decryptedConfig; - // Correction : parser plusieurs fois si besoin + // Parse multiple times if needed for (let i = 0; i < 2; i++) { if (typeof config === 'string') { try { config = JSON.parse(config); } catch (e) { - console.error('[BlazeJob][HTTP] Erreur de parsing config:', e, config); + console.error('[BlazeJob][HTTP] Config parsing error:', e, config); break; } } } taskFn = makeHttpTaskFn(config); - } else if (task.type === 'shell' && decryptedConfig) { - const config = JSON.parse(decryptedConfig) as ShellTaskConfig; - taskFn = async () => { - console.log('[DEBUG][Shell] Commande exécutée:', config.cmd); - const { stdout, stderr } = await execAsync(config.cmd); - if (stdout) console.log('[Shell][stdout]', stdout); - if (stderr) console.error('[Shell][stderr]', stderr); - }; } else { - // NE PAS réassigner taskFn ici pour laisser la fonction custom s'exécuter + // Do not reassign taskFn here to let custom function execute } await taskFn(); // Après exécution de la tâche (succès ou erreur) @@ -273,57 +256,6 @@ export class BlazeJob { } } - /** - * Programme nativement plusieurs requêtes Cosmos d'un coup. - * @param opts - * - count: nombre de requêtes à programmer - * - address: adresse Cosmos cible - * - queryType: type de requête ('balance', 'tx', ...) - * - intervalMs: intervalle entre chaque tâche (ms, défaut 100) - * - configOverrides: options avancées (optionnel) - * - retriesLeft, priority, runAt, webhookUrl (optionnel) - */ - public async scheduleManyCosmosQueries(opts: { - count: number; - address: string; - queryType: string; - intervalMs?: number; - configOverrides?: Record; - retriesLeft?: number; - priority?: number; - runAt?: Date | string; - webhookUrl?: string; - }) { - const { - count, - address, - queryType, - intervalMs = 100, - configOverrides = {}, - retriesLeft = 0, - priority = 0, - runAt, - webhookUrl - } = opts; - for (let i = 0; i < count; i++) { - const scheduledAt = runAt - ? (runAt instanceof Date ? new Date(runAt.getTime() + i * intervalMs) : new Date(new Date(runAt).getTime() + i * intervalMs)) - : new Date(Date.now() + i * intervalMs); - this.schedule(undefined, { - type: 'cosmos', - runAt: scheduledAt, - priority, - retriesLeft, - webhookUrl, - config: { - queryType, - queryParams: { address }, - ...configOverrides - } - }); - } - } - public getTasks(): any[] { const tasks = this.db.prepare('SELECT * FROM tasks').all(); return tasks.map((task: any) => { @@ -334,6 +266,14 @@ export class BlazeJob { }); } + public deleteTask(taskId: number): void { + this.db.prepare('DELETE FROM tasks WHERE id = ?').run(taskId); + // Clean up memory maps + this.taskFns.delete(taskId); + this.taskRunStats.delete(taskId); + this.taskErrorCount.delete(taskId); + } + /** * Schedule a new task and store its function in the taskMap. * @param taskFn The function to execute for this task @@ -402,9 +342,9 @@ export async function startServer(port: number = 9000) { // eslint-disable-next-line @typescript-eslint/no-var-requires app.register(require('@fastify/formbody')); - // Initialize SQLite database - db = new Database('blazerjob.db'); - jobs = new BlazeJob({ dbPath: 'blazerjob.db' }); + // Initialize scheduler (RAM storage by default) + jobs = new BlazeJob({ storage: 'memory' }); + db = jobs['db']; // GET /tasks: return all scheduled tasks app.get('/tasks', async (request: FastifyRequest, reply: FastifyReply) => { @@ -416,50 +356,11 @@ export async function startServer(port: number = 9000) { app.post('/task', async (request: FastifyRequest, reply: FastifyReply) => { const { runAt, interval, priority, retriesLeft, type, config, webhookUrl, maxRuns, maxDurationMs, onEnd } = (request.body as any) ?? {}; let taskFn: () => Promise = async () => { }; - if (type === 'cosmos' && config) { - const cfg = JSON.parse(config) as CosmosTaskConfig; - const rpcUrl = cfg.rpcUrl || process.env.COSMOS_RPC_URL; - const mnemonic = cfg.mnemonic || process.env.COSMOS_MNEMONIC; - if (!rpcUrl) throw new Error('No Cosmos rpcUrl (set in config or .env)'); - if (cfg.to && cfg.amount && cfg.denom && mnemonic && cfg.chainId) { - // Send tokens - taskFn = async () => { - const wallet = await DirectSecp256k1HdWallet.fromMnemonic(mnemonic, { prefix: 'cosmos' }); - const [account] = await wallet.getAccounts(); - const client = await SigningStargateClient.connectWithSigner(rpcUrl, wallet); - const fee = { - amount: coins(cfg.gas || '5000', cfg.denom), - gas: cfg.gas || '200000', - }; - const result = await client.sendTokens(account.address, cfg.to, coins(cfg.amount, cfg.denom), fee, cfg.memo || ''); - if (result.code !== 0) throw new Error(result.rawLog); - return; - }; - } else if (cfg.queryType) { - // Query - taskFn = async () => { - const client = await StargateClient.connect(rpcUrl); - let _res; - if (cfg.queryType === 'balance') { - _res = await client.getAllBalances(cfg.queryParams?.address); - console.log('[Cosmos][balance]', cfg.queryParams?.address, _res); - } else if (cfg.queryType === 'tx') { - _res = await client.getTx(cfg.queryParams?.hash); - console.log('[Cosmos][tx]', cfg.queryParams?.hash, _res); - } else { - throw new Error('Unknown Cosmos queryType'); - } - console.log('[Cosmos][query result]', _res); - return; - }; - } else { - throw new Error('Invalid Cosmos config: must provide tx params or queryType'); - } - } else if (type === 'http' && config) { + if (type === 'http' && config) { const cfg = JSON.parse(config) as HttpTaskConfig; taskFn = makeHttpTaskFn(cfg); } else { - // Par défaut, tâche factice + // Default: dummy task taskFn = async () => { console.log('Task executed:', { type, config }); }; @@ -471,7 +372,11 @@ export async function startServer(port: number = 9000) { // DELETE /task/:id: delete a task by id app.delete('/task/:id', async (request: FastifyRequest, reply: FastifyReply) => { const { id } = request.params as { id: string }; + const taskId = parseInt(id, 10); db.prepare('DELETE FROM tasks WHERE id = ?').run(id); + // Clean up memory maps + jobs!['taskFns'].delete(taskId); + jobs!['taskRunStats'].delete(taskId); reply.code(204).send(); }); diff --git a/src/tests/test_cosmos_query.ts b/src/tests/test_cosmos_query.ts deleted file mode 100644 index c19625f..0000000 --- a/src/tests/test_cosmos_query.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { BlazeJob } from '../index'; -import { scheduleManyCosmosQueries } from '../cosmos'; - -const job = new BlazeJob({ dbPath: './tasks_cosmos_query.db' }); - -(async () => { - console.log('Test Cosmos multi-query démarré'); - await scheduleManyCosmosQueries(job, { - addresses: [ - 'cosmos1fl48vsnmsdzcv85q5d2q4z5ajdha8yu34mf0eh', - 'cosmos1c9ye9j3p4e9w8f7j2k7l6k8e8f7g9h5d3j8k7h', - // Ajoute ici d'autres adresses si besoin - ], - count: 100, - queryType: 'balance', - intervalMs: 100, - // Autres options possibles: retriesLeft, priority, configOverrides, runAt, webhookUrl - }); - job.start(); -})(); diff --git a/src/tests/test_cosmos_tx.ts b/src/tests/test_cosmos_tx.ts deleted file mode 100644 index cc61c20..0000000 --- a/src/tests/test_cosmos_tx.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { BlazeJob } from '../index'; - -const jobs = new BlazeJob({ dbPath: './tasks_cosmos_tx.db' }); -jobs.schedule(undefined, { - runAt: new Date(Date.now() + 1000), - type: 'cosmos', - config: JSON.stringify({ - to: 'cosmos1destination...', - amount: '100000', - denom: 'uatom', - chainId: 'cosmoshub-4' - }) -}); -jobs.start(); diff --git a/src/types.ts b/src/types.ts index 78c9e89..9482ae1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,9 +1,5 @@ // TaskConfig interface for all supported types -export type TaskType = 'fintech' | 'onchain' | 'solana' | 'cosmos' | 'shell' | 'http' | 'email'; - -export interface ShellTaskConfig { - cmd: string; -} +export type TaskType = 'http'; export interface HttpTaskConfig { url: string; @@ -12,62 +8,4 @@ export interface HttpTaskConfig { body?: any; } -export interface OnchainTaskConfig { - rpcUrl?: string; - privateKey?: string; - to: string; - value: string; // in ETH or wei - data?: string; - gasLimit?: number; -} - -export interface SolanaTaskConfig { - rpcUrl?: string; - secretKey?: string; // base58 or Uint8Array as string - to: string; - lamports: number; // amount in lamports - memo?: string; -} - -export interface EmailTaskConfig { - to: string; - subject: string; - text?: string; - html?: string; - from?: string; - smtpHost?: string; - smtpPort?: number; - smtpUser?: string; - smtpPass?: string; -} - -export interface FintechTaskConfig { - provider: string; - amount: number; - currency: string; - recipient: string; - [key: string]: any; -} - -export interface CosmosTaskConfig { - rpcUrl?: string; - mnemonic?: string; - to: string; - amount: string; // en uatom, uosmo, etc. - denom: string; - chainId: string; - gas?: string; - memo?: string; - // Pour query : queryType et params - queryType?: 'balance' | 'tx' | 'custom'; - queryParams?: Record; -} - -export type TaskConfig = - | ShellTaskConfig - | HttpTaskConfig - | OnchainTaskConfig - | SolanaTaskConfig - | EmailTaskConfig - | CosmosTaskConfig - | FintechTaskConfig; +export type TaskConfig = HttpTaskConfig;