@net-protocol/cli 0.1.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/cli/shared.ts","../../src/commands/storage/storage/check.ts","../../src/commands/storage/utils.ts","../../src/commands/storage/transactions/prep.ts","../../src/commands/storage/transactions/filter.ts","../../src/commands/storage/transactions/send.ts","../../src/commands/storage/core/upload.ts","../../src/commands/storage/relay/recheckStorage.ts","../../src/commands/storage/relay/retry.ts","../../src/commands/storage/core/uploadRelay.ts","../../src/commands/storage/core/preview.ts","../../src/commands/storage/index.ts","../../src/cli/index.ts"],"names":["chalk","hexToString","StorageClient","getStorageKeyBytes","retryFailedTransactionsPackage","failedIndexes","backendWalletAddress","readFileSync","detectFileTypeFromBase64","base64ToDataUri","privateKeyToAccount","getPublicClient","getChainRpcUrls","createWalletClient","http","shouldSuggestXmlStorage","stringToHex","program","Command"],"mappings":"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","file":"index.mjs","sourcesContent":["import chalk from \"chalk\";\nimport type { CommonOptions } from \"../shared/types\";\n\n/**\n * Parse and validate common options shared across all commands\n * Extracts private key, chain ID, and RPC URL from command options or environment variables\n */\nexport function parseCommonOptions(options: {\n privateKey?: string;\n chainId?: number;\n rpcUrl?: string;\n}): CommonOptions {\n // Get private key from option or environment variable\n const privateKey =\n options.privateKey ||\n process.env.NET_PRIVATE_KEY ||\n process.env.PRIVATE_KEY;\n\n if (!privateKey) {\n console.error(\n chalk.red(\n \"Error: Private key is required. Provide via --private-key flag or NET_PRIVATE_KEY/PRIVATE_KEY environment variable\"\n )\n );\n process.exit(1);\n }\n\n // Validate private key format\n if (!privateKey.startsWith(\"0x\") || privateKey.length !== 66) {\n console.error(\n chalk.red(\n \"Error: Invalid private key format (must be 0x-prefixed, 66 characters)\"\n )\n );\n process.exit(1);\n }\n\n // Warn about private key security if provided via command line\n if (options.privateKey) {\n console.warn(\n chalk.yellow(\n \"āš ļø Warning: Private key provided via command line. Consider using NET_PRIVATE_KEY environment variable instead.\"\n )\n );\n }\n\n // Get chain ID from option or environment variable\n const chainId =\n options.chainId ||\n (process.env.NET_CHAIN_ID\n ? parseInt(process.env.NET_CHAIN_ID, 10)\n : undefined);\n\n if (!chainId) {\n console.error(\n chalk.red(\n \"Error: Chain ID is required. Provide via --chain-id flag or NET_CHAIN_ID environment variable\"\n )\n );\n process.exit(1);\n }\n\n // Get RPC URL from option or environment variable\n const rpcUrl = options.rpcUrl || process.env.NET_RPC_URL;\n\n return {\n privateKey: privateKey as `0x${string}`,\n chainId,\n rpcUrl,\n };\n}\n\n","import { StorageClient } from \"@net-protocol/storage\";\nimport { hexToString } from \"viem\";\nimport type {\n StorageCheckResult,\n CheckNormalStorageExistsParams,\n CheckChunkedStorageExistsParams,\n CheckXmlChunksExistParams,\n CheckXmlMetadataExistsParams,\n} from \"../types\";\n\n/**\n * Check if normal storage data exists and matches content\n * Pure function - uses StorageClient, no side effects\n * Accepts JSON object as parameter\n */\nexport async function checkNormalStorageExists(\n params: CheckNormalStorageExistsParams\n): Promise<StorageCheckResult> {\n const { storageClient, storageKey, operatorAddress, expectedContent } = params;\n const existing = await storageClient.get({\n key: storageKey,\n operator: operatorAddress,\n });\n\n if (!existing) {\n return { exists: false };\n }\n\n // Compare content\n const storedContent = hexToString(existing.value as `0x${string}`);\n const matches = storedContent === expectedContent;\n\n return { exists: true, matches };\n}\n\n/**\n * Check if ChunkedStorage data exists\n * Pure function - uses StorageClient\n * Accepts JSON object as parameter\n */\nexport async function checkChunkedStorageExists(\n params: CheckChunkedStorageExistsParams\n): Promise<boolean> {\n const { storageClient, chunkedHash, operatorAddress } = params;\n const meta = await storageClient.getChunkedMetadata({\n key: chunkedHash,\n operator: operatorAddress,\n });\n\n return meta !== null && meta.chunkCount > 0;\n}\n\n/**\n * Check which XML chunks already exist in ChunkedStorage\n * Returns Set of chunkedStorage hashes that exist\n * Pure function - uses StorageClient\n * Accepts JSON object as parameter\n */\nexport async function checkXmlChunksExist(\n params: CheckXmlChunksExistParams\n): Promise<Set<string>> {\n const { storageClient, chunkedHashes, operatorAddress } = params;\n const existing = new Set<string>();\n\n // Check each chunk in parallel for efficiency\n await Promise.all(\n chunkedHashes.map(async (hash) => {\n const exists = await checkChunkedStorageExists({\n storageClient,\n chunkedHash: hash,\n operatorAddress,\n });\n if (exists) {\n existing.add(hash);\n }\n })\n );\n\n return existing;\n}\n\n/**\n * Check if XML metadata exists and matches expected metadata\n * Pure function - uses StorageClient\n * Accepts JSON object as parameter\n */\nexport async function checkXmlMetadataExists(\n params: CheckXmlMetadataExistsParams\n): Promise<StorageCheckResult> {\n const { storageClient, storageKey, operatorAddress, expectedMetadata } = params;\n const existing = await storageClient.get({\n key: storageKey,\n operator: operatorAddress,\n });\n\n if (!existing) {\n return { exists: false };\n }\n\n const storedMetadata = hexToString(existing.value as `0x${string}`);\n const matches = storedMetadata === expectedMetadata;\n\n return { exists: true, matches };\n}\n\n","import { StorageClient } from \"@net-protocol/storage\";\nimport { hexToString } from \"viem\";\nimport { encodeStorageKeyForUrl } from \"@net-protocol/storage\";\nimport { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n checkNormalStorageExists,\n checkChunkedStorageExists,\n checkXmlMetadataExists,\n} from \"./storage/check\";\nimport type {\n TransactionWithId,\n StorageTransactionArgs,\n CheckTransactionExistsParams,\n} from \"./types\";\n\n/**\n * Convert typed args to array (for viem compatibility)\n */\nexport function typedArgsToArray(\n args: StorageTransactionArgs\n): readonly unknown[] {\n if (args.type === \"normal\" || args.type === \"metadata\") {\n return [args.args.key, args.args.text, args.args.value];\n } else {\n return [args.args.hash, args.args.text, args.args.chunks];\n }\n}\n\n/**\n * Extract typed args from WriteTransactionConfig\n */\nexport function extractTypedArgsFromTransaction(\n tx: WriteTransactionConfig,\n type: \"normal\" | \"chunked\" | \"metadata\"\n): StorageTransactionArgs {\n if (type === \"normal\" || type === \"metadata\") {\n return {\n type,\n args: {\n key: tx.args[0] as `0x${string}`,\n text: tx.args[1] as string,\n value: tx.args[2] as `0x${string}`,\n },\n };\n } else {\n return {\n type: \"chunked\",\n args: {\n hash: tx.args[0] as `0x${string}`,\n text: tx.args[1] as string,\n chunks: tx.args[2] as `0x${string}`[],\n },\n };\n }\n}\n\n/**\n * Extract content string from transaction typed args\n * Helper to eliminate duplication of hexToString pattern\n */\nexport function extractContentFromTransaction(\n tx: TransactionWithId\n): string {\n if (tx.typedArgs.type === \"normal\" || tx.typedArgs.type === \"metadata\") {\n return hexToString(tx.typedArgs.args.value);\n } else {\n // For chunked transactions, return empty string (no content to extract)\n return \"\";\n }\n}\n\n/**\n * Generate storage URL for displaying to user\n * Centralizes URL generation logic\n */\nexport function generateStorageUrl(\n operatorAddress: string | undefined,\n chainId: number,\n storageKey: string\n): string | undefined {\n if (!operatorAddress) return undefined;\n return `https://storedon.net/net/${chainId}/storage/load/${\n operatorAddress\n }/${encodeStorageKeyForUrl(storageKey)}`;\n}\n\n/**\n * Check if a transaction's data already exists (idempotency check)\n * Consolidates existence check logic used in both filtering and sending\n * Accepts JSON object as parameter\n */\nexport async function checkTransactionExists(\n params: CheckTransactionExistsParams\n): Promise<boolean> {\n const { storageClient, tx, operatorAddress } = params;\n if (tx.type === \"normal\") {\n // Extract expected content from typed args\n if (tx.typedArgs.type === \"normal\") {\n const expectedContent = hexToString(tx.typedArgs.args.value);\n const check = await checkNormalStorageExists({\n storageClient,\n storageKey: tx.id,\n operatorAddress,\n expectedContent,\n });\n return check.exists && check.matches === true;\n }\n } else if (tx.type === \"chunked\") {\n // ChunkedStorage: hash existence = content match (deterministic hash)\n return await checkChunkedStorageExists({\n storageClient,\n chunkedHash: tx.id,\n operatorAddress,\n });\n } else if (tx.type === \"metadata\") {\n // XML metadata: extract and compare content\n if (tx.typedArgs.type === \"metadata\") {\n const expectedMetadata = hexToString(tx.typedArgs.args.value);\n const check = await checkXmlMetadataExists({\n storageClient,\n storageKey: tx.id,\n operatorAddress,\n expectedMetadata,\n });\n return check.exists && check.matches === true;\n }\n }\n return false;\n}\n\n","import { WriteTransactionConfig } from \"@net-protocol/core\";\nimport { StorageClient, getStorageKeyBytes } from \"@net-protocol/storage\";\nimport { hexToString } from \"viem\";\nimport type {\n TransactionWithId,\n NormalStorageArgs,\n PrepareXmlStorageTransactionsParams,\n} from \"../types\";\nimport { extractTypedArgsFromTransaction, typedArgsToArray } from \"../utils\";\n\n/**\n * Prepare normal storage transaction with ID\n * Uses StorageClient.preparePut() from net-public\n * Accepts typed JSON args object instead of individual parameters\n */\nexport function prepareNormalStorageTransaction(\n storageClient: StorageClient,\n args: NormalStorageArgs,\n originalStorageKey: string // Original string key needed for preparePut\n): TransactionWithId {\n // Use StorageClient.preparePut() from net-public\n // preparePut needs the original string key, not bytes32\n const content = hexToString(args.value);\n \n const transaction = storageClient.preparePut({\n key: originalStorageKey,\n text: args.text,\n value: content,\n });\n\n const typedArgs = {\n type: \"normal\" as const,\n args,\n };\n\n return {\n id: args.key,\n type: \"normal\",\n transaction,\n typedArgs,\n };\n}\n\n/**\n * Prepare XML storage transactions with IDs\n * Returns array: [metadata transaction, ...chunk transactions]\n * Uses StorageClient.prepareXmlStorage() from net-public\n * Accepts JSON object as parameter\n */\nexport function prepareXmlStorageTransactions(\n params: PrepareXmlStorageTransactionsParams\n): TransactionWithId[] {\n const { storageClient, storageKey, text, content, operatorAddress } = params;\n const storageKeyBytes = getStorageKeyBytes(storageKey) as `0x${string}`;\n\n // Use StorageClient.prepareXmlStorage() from net-public\n // This handles all the chunking, ChunkedStorage preparation, and metadata generation\n // Pass storageKey as string - prepareXmlStorage will convert it internally\n const result = storageClient.prepareXmlStorage({\n data: content,\n operatorAddress: operatorAddress as `0x${string}`,\n storageKey: storageKey, // Pass as string, not bytes32\n filename: text,\n useChunkedStorageBackend: true, // Use ChunkedStorage backend (default)\n });\n\n // Map WriteTransactionConfig[] to TransactionWithId[]\n // First transaction is metadata, rest are chunk transactions\n const transactions: TransactionWithId[] = result.transactionConfigs.map(\n (tx, index) => {\n if (index === 0) {\n // First transaction is metadata - use our storageKeyBytes for ID\n const typedArgs = extractTypedArgsFromTransaction(tx, \"metadata\");\n return {\n id: storageKeyBytes,\n type: \"metadata\",\n transaction: tx,\n typedArgs,\n };\n } else {\n // Rest are ChunkedStorage transactions\n // Extract typed args and get hash from typed args\n const typedArgs = extractTypedArgsFromTransaction(tx, \"chunked\");\n if (typedArgs.type === \"chunked\") {\n const chunkedHash = typedArgs.args.hash;\n return {\n id: chunkedHash,\n type: \"chunked\",\n transaction: tx,\n typedArgs,\n };\n }\n // This should never happen, but TypeScript needs it\n throw new Error(\"Invalid chunked transaction\");\n }\n }\n );\n\n return transactions;\n}\n\n","import { StorageClient } from \"@net-protocol/storage\";\nimport { hexToString } from \"viem\";\nimport { WriteTransactionConfig } from \"@net-protocol/core\";\nimport {\n STORAGE_CONTRACT,\n CHUNKED_STORAGE_CONTRACT,\n} from \"@net-protocol/storage\";\nimport {\n checkNormalStorageExists,\n checkChunkedStorageExists,\n checkXmlChunksExist,\n checkXmlMetadataExists,\n} from \"../storage/check\";\nimport { extractTypedArgsFromTransaction } from \"../utils\";\nimport type {\n TransactionWithId,\n FilterExistingTransactionsParams,\n FilterXmlStorageTransactionsParams,\n} from \"../types\";\n\n/**\n * Filter transactions to only those that need to be sent\n * Checks existence for each transaction and filters out already-stored ones\n * Pure function - uses StorageClient, no side effects\n * Accepts JSON object as parameter\n */\nexport async function filterExistingTransactions(\n params: FilterExistingTransactionsParams\n): Promise<{\n toSend: TransactionWithId[];\n skipped: TransactionWithId[];\n}> {\n const { storageClient, transactions, operatorAddress, expectedContent } =\n params;\n const toSend: TransactionWithId[] = [];\n const skipped: TransactionWithId[] = [];\n\n for (const tx of transactions) {\n let exists = false;\n\n if (tx.type === \"normal\") {\n // Normal storage: always check if exists AND matches content\n if (expectedContent) {\n const check = await checkNormalStorageExists({\n storageClient,\n storageKey: tx.id,\n operatorAddress,\n expectedContent,\n });\n exists = check.exists && check.matches === true;\n } else {\n // Extract content from typed args if not provided\n if (tx.typedArgs.type === \"normal\") {\n const storedContent = hexToString(tx.typedArgs.args.value);\n const check = await checkNormalStorageExists({\n storageClient,\n storageKey: tx.id,\n operatorAddress,\n expectedContent: storedContent,\n });\n exists = check.exists && check.matches === true;\n }\n }\n } else if (tx.type === \"chunked\") {\n // ChunkedStorage: check if metadata exists\n exists = await checkChunkedStorageExists({\n storageClient,\n chunkedHash: tx.id,\n operatorAddress,\n });\n } else if (tx.type === \"metadata\") {\n // XML metadata: check if exists\n // Extract expected metadata from typed args (it's hex-encoded)\n if (tx.typedArgs.type === \"metadata\") {\n const expectedMetadata = hexToString(tx.typedArgs.args.value);\n const check = await checkXmlMetadataExists({\n storageClient,\n storageKey: tx.id,\n operatorAddress,\n expectedMetadata,\n });\n exists = check.exists && check.matches === true;\n }\n }\n\n if (exists) {\n skipped.push(tx);\n } else {\n toSend.push(tx);\n }\n }\n\n return { toSend, skipped };\n}\n\n/**\n * Filter XML storage transactions more efficiently\n * Checks all chunks in parallel, then filters\n * Accepts WriteTransactionConfig[] directly and derives chunkedHashes internally\n * Accepts JSON object as parameter\n */\nexport async function filterXmlStorageTransactions(\n params: FilterXmlStorageTransactionsParams\n): Promise<{\n toSend: WriteTransactionConfig[];\n skipped: WriteTransactionConfig[];\n}> {\n const { storageClient, transactions, operatorAddress } = params;\n\n // Separate metadata and chunk transactions by contract address\n const metadataTx = transactions.find(\n (tx) => tx.to.toLowerCase() === STORAGE_CONTRACT.address.toLowerCase()\n );\n const chunkTxs = transactions.filter(\n (tx) => tx.to.toLowerCase() === CHUNKED_STORAGE_CONTRACT.address.toLowerCase()\n );\n\n // Derive chunkedHashes internally from WriteTransactionConfig[] args\n const chunkedHashes: string[] = [];\n for (const tx of chunkTxs) {\n const typedArgs = extractTypedArgsFromTransaction(tx, \"chunked\");\n if (typedArgs.type === \"chunked\") {\n chunkedHashes.push(typedArgs.args.hash); // Content-based hash (keccak256(xmlChunk))\n }\n }\n\n const toSend: WriteTransactionConfig[] = [];\n const skipped: WriteTransactionConfig[] = [];\n\n // Check which chunks exist (parallel check)\n const existingChunks = await checkXmlChunksExist({\n storageClient,\n chunkedHashes,\n operatorAddress,\n });\n\n // Filter chunk transactions\n for (const tx of chunkTxs) {\n const typedArgs = extractTypedArgsFromTransaction(tx, \"chunked\");\n if (typedArgs.type === \"chunked\") {\n const hash = typedArgs.args.hash;\n if (existingChunks.has(hash)) {\n skipped.push(tx);\n } else {\n toSend.push(tx);\n }\n }\n }\n\n // Check metadata (if all chunks exist and match, skip metadata too)\n if (metadataTx) {\n const allChunksExist = chunkedHashes.length > 0 && chunkedHashes.every((hash) =>\n existingChunks.has(hash)\n );\n if (allChunksExist) {\n // Verify metadata matches\n try {\n const typedArgs = extractTypedArgsFromTransaction(metadataTx, \"metadata\");\n if (typedArgs.type === \"metadata\") {\n const expectedMetadata = hexToString(typedArgs.args.value);\n const check = await checkXmlMetadataExists({\n storageClient,\n storageKey: typedArgs.args.key,\n operatorAddress,\n expectedMetadata,\n });\n if (check.exists && check.matches) {\n skipped.push(metadataTx);\n } else {\n toSend.unshift(metadataTx); // Metadata first\n }\n }\n } catch {\n // If we can't extract metadata args, include in toSend\n toSend.unshift(metadataTx);\n }\n } else {\n toSend.unshift(metadataTx); // Metadata first\n }\n }\n\n return { toSend, skipped };\n}\n","import { createWalletClient, http, WalletClient, defineChain, PublicClient } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport {\n getPublicClient,\n getChainRpcUrls,\n} from \"@net-protocol/core\";\nimport { StorageClient } from \"@net-protocol/storage\";\nimport { checkTransactionExists, typedArgsToArray } from \"../utils\";\nimport type {\n TransactionWithId,\n UploadResult,\n CreateWalletClientParams,\n SendTransactionsParams,\n} from \"../types\";\n\n/**\n * Create wallet client from private key\n * Accepts JSON object as parameter\n */\nexport function createWalletClientFromPrivateKey(\n params: CreateWalletClientParams\n): {\n walletClient: WalletClient;\n publicClient: PublicClient;\n operatorAddress: `0x${string}`;\n} {\n const { privateKey, chainId, rpcUrl } = params;\n const account = privateKeyToAccount(privateKey);\n const publicClient = getPublicClient({ chainId, rpcUrl });\n\n // Get RPC URLs for the chain\n const rpcUrls = getChainRpcUrls({ chainId, rpcUrl });\n\n // Create wallet client with the same chain configuration\n const chain = publicClient.chain\n ? defineChain({\n id: chainId,\n name: publicClient.chain.name,\n nativeCurrency: publicClient.chain.nativeCurrency,\n rpcUrls: {\n default: { http: rpcUrls },\n public: { http: rpcUrls },\n },\n blockExplorers: publicClient.chain.blockExplorers,\n })\n : defineChain({\n id: chainId,\n name: `Chain ${chainId}`,\n nativeCurrency: { name: \"Ether\", symbol: \"ETH\", decimals: 18 },\n rpcUrls: {\n default: { http: rpcUrls },\n public: { http: rpcUrls },\n },\n });\n\n const walletClient = createWalletClient({\n account,\n chain,\n transport: http(),\n });\n\n return {\n walletClient,\n publicClient,\n operatorAddress: account.address,\n };\n}\n\n/**\n * Send transactions sequentially with idempotency checks\n * Checks existence before each transaction (handles partial retries)\n * Accepts JSON object as parameter\n */\nexport async function sendTransactionsWithIdempotency(\n params: SendTransactionsParams\n): Promise<UploadResult> {\n const { storageClient, walletClient, publicClient, transactions, operatorAddress } = params;\n let sent = 0;\n let skipped = 0;\n let failed = 0;\n let finalHash: string | undefined;\n const errorMessages: string[] = [];\n\n for (let i = 0; i < transactions.length; i++) {\n const tx = transactions[i];\n\n try {\n // Check if this transaction's data already exists (idempotency)\n // Always compare content, not just check existence\n const exists = await checkTransactionExists({\n storageClient,\n tx,\n operatorAddress,\n });\n\n if (exists) {\n console.log(\n `ā­ļø Transaction ${i + 1}/${\n transactions.length\n } skipped (already stored): ${tx.id}`\n );\n skipped++;\n continue;\n }\n\n // Send transaction\n console.log(\n `šŸ“¤ Sending transaction ${i + 1}/${transactions.length}: ${tx.id}`\n );\n // Convert typed args to array for viem compatibility\n const args = typedArgsToArray(tx.typedArgs);\n if (!walletClient.account) {\n throw new Error(\"Wallet client must have an account\");\n }\n const hash = await walletClient.writeContract({\n account: walletClient.account,\n address: tx.transaction.to as `0x${string}`,\n abi: tx.transaction.abi,\n functionName: tx.transaction.functionName as string,\n args,\n value: tx.transaction.value,\n chain: null,\n });\n\n // Wait for confirmation\n const receipt = await publicClient.waitForTransactionReceipt({ hash });\n console.log(\n `āœ“ Transaction ${i + 1} confirmed in block ${\n receipt.blockNumber\n } (hash: ${hash})`\n );\n\n sent++;\n finalHash = hash;\n } catch (error) {\n const errorMsg =\n error instanceof Error ? error.message : String(error);\n console.error(`āœ— Transaction ${i + 1} failed: ${errorMsg}`);\n errorMessages.push(errorMsg);\n failed++;\n // Continue with remaining transactions (don't fail entire upload)\n }\n }\n\n return {\n success: failed === 0,\n skipped: skipped > 0,\n transactionsSent: sent,\n transactionsSkipped: skipped,\n transactionsFailed: failed,\n finalHash,\n error: errorMessages.length > 0 ? errorMessages.join(\"; \") : undefined,\n };\n}\n\n","import { readFileSync } from \"fs\";\nimport {\n shouldSuggestXmlStorage,\n getStorageKeyBytes,\n detectFileTypeFromBase64,\n base64ToDataUri,\n} from \"@net-protocol/storage\";\nimport { StorageClient } from \"@net-protocol/storage\";\nimport { stringToHex } from \"viem\";\nimport {\n prepareNormalStorageTransaction,\n prepareXmlStorageTransactions,\n} from \"../transactions/prep\";\nimport {\n filterExistingTransactions,\n filterXmlStorageTransactions,\n} from \"../transactions/filter\";\nimport {\n createWalletClientFromPrivateKey,\n sendTransactionsWithIdempotency,\n} from \"../transactions/send\";\nimport type {\n UploadOptions,\n UploadResult,\n TransactionWithId,\n NormalStorageArgs,\n} from \"../types\";\n\n/**\n * Main upload function - orchestrates the entire upload process\n */\nexport async function uploadFile(\n options: UploadOptions\n): Promise<UploadResult> {\n // 1. Read file\n // Read file as buffer (binary) first\n const fileBuffer = readFileSync(options.filePath);\n\n // Detect if file is binary\n // Check for null bytes or non-text characters (excluding common whitespace)\n const isBinary = fileBuffer.some(\n (byte) =>\n byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)\n );\n\n // Convert based on file type\n let fileContent: string;\n if (isBinary) {\n // Convert binary file to base64 string (valid UTF-8)\n const base64String = fileBuffer.toString(\"base64\");\n\n // Detect file type and add data URI prefix if detected\n const detectedType = detectFileTypeFromBase64(base64String);\n if (detectedType) {\n // Include data URI prefix for better type preservation\n // Format: \"data:audio/mpeg;base64,SUQz...\"\n fileContent = base64ToDataUri(base64String);\n } else {\n // Fallback to raw base64 if detection fails\n fileContent = base64String;\n }\n } else {\n // Read as UTF-8 for text files\n fileContent = fileBuffer.toString(\"utf-8\");\n }\n\n // 2. Create StorageClient\n const storageClient = new StorageClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // 3. Create wallet client\n const { walletClient, publicClient, operatorAddress } =\n createWalletClientFromPrivateKey({\n privateKey: options.privateKey,\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n\n // 4. Determine storage type\n const useXmlStorage = shouldSuggestXmlStorage(fileContent);\n const storageType: \"normal\" | \"xml\" = useXmlStorage ? \"xml\" : \"normal\";\n\n // 5. Prepare transactions\n let transactions: TransactionWithId[];\n\n if (useXmlStorage) {\n transactions = prepareXmlStorageTransactions({\n storageClient,\n storageKey: options.storageKey,\n text: options.text,\n content: fileContent,\n operatorAddress,\n });\n // No need to extract chunkedHashes - filterXmlStorageTransactions derives them internally\n } else {\n // Build typed args JSON object\n const storageKeyBytes = getStorageKeyBytes(\n options.storageKey\n ) as `0x${string}`;\n const typedArgs: NormalStorageArgs = {\n key: storageKeyBytes,\n text: options.text,\n value: stringToHex(fileContent),\n };\n\n transactions = [\n prepareNormalStorageTransaction(\n storageClient,\n typedArgs,\n options.storageKey // Pass original string key for preparePut\n ),\n ];\n }\n\n // 6. Filter existing transactions (idempotency)\n let transactionsToSend: TransactionWithId[];\n let skippedCount = 0;\n\n if (useXmlStorage) {\n // Extract WriteTransactionConfig[] from TransactionWithId[]\n // First transaction is metadata, rest are chunk transactions\n const chunkTransactions = transactions\n .filter((tx) => tx.type === \"chunked\")\n .map((tx) => tx.transaction);\n\n // Create a map from WriteTransactionConfig to TransactionWithId for easy lookup\n const txConfigToTxWithId = new Map(\n transactions\n .filter((tx) => tx.type === \"chunked\")\n .map((tx) => [tx.transaction, tx])\n );\n\n const filtered = await filterXmlStorageTransactions({\n storageClient,\n transactions: chunkTransactions, // Only chunk transactions\n operatorAddress,\n });\n\n // Map filtered WriteTransactionConfig[] back to TransactionWithId[]\n const filteredToSend: TransactionWithId[] = filtered.toSend\n .map((txConfig) => txConfigToTxWithId.get(txConfig))\n .filter((tx): tx is TransactionWithId => tx !== undefined);\n\n const filteredSkipped: TransactionWithId[] = filtered.skipped\n .map((txConfig) => txConfigToTxWithId.get(txConfig))\n .filter((tx): tx is TransactionWithId => tx !== undefined);\n\n // Metadata is handled separately - check if it needs to be sent\n const metadataTx = transactions.find((tx) => tx.type === \"metadata\");\n if (metadataTx) {\n // For now, always include metadata in toSend (caller should check separately)\n filteredToSend.unshift(metadataTx);\n }\n\n transactionsToSend = filteredToSend;\n skippedCount = filteredSkipped.length;\n } else {\n const filtered = await filterExistingTransactions({\n storageClient,\n transactions,\n operatorAddress,\n expectedContent: fileContent,\n });\n transactionsToSend = filtered.toSend;\n skippedCount = filtered.skipped.length;\n }\n\n // 7. Check if all transactions were skipped\n if (transactionsToSend.length === 0) {\n return {\n success: true,\n skipped: true,\n transactionsSent: 0,\n transactionsSkipped: skippedCount,\n transactionsFailed: 0,\n operatorAddress,\n storageType,\n };\n }\n\n // 8. Send transactions\n const result = await sendTransactionsWithIdempotency({\n storageClient,\n walletClient,\n publicClient,\n transactions: transactionsToSend,\n operatorAddress,\n });\n\n // Add skipped count from filtering step\n result.transactionsSkipped += skippedCount;\n\n // Add operator address and storage type to result\n result.operatorAddress = operatorAddress;\n result.storageType = storageType;\n\n return result;\n}\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { StorageClient } from \"@net-protocol/storage\";\nimport type { Address } from \"viem\";\nimport { checkXmlChunksExist } from \"../storage/check\";\nimport { extractTypedArgsFromTransaction } from \"../utils\";\n\n/**\n * Storage-specific recheck function for retry logic\n *\n * Re-checks failed transactions on-chain before retry to filter out\n * transactions that have succeeded since the last attempt.\n *\n * This is storage-specific because it uses checkXmlChunksExist and\n * extractTypedArgsFromTransaction which understand storage transaction types.\n *\n * @param failedIndexes - Indexes of failed transactions\n * @param transactions - Original transaction configs\n * @param backendWalletAddress - Backend wallet address (operator for storage checks)\n * @returns Array of transaction indexes that still need to be retried\n */\nexport async function recheckFailedTransactionsStorage(\n failedIndexes: number[],\n transactions: WriteTransactionConfig[],\n storageClient: StorageClient,\n backendWalletAddress: Address\n): Promise<number[]> {\n if (failedIndexes.length === 0) {\n return [];\n }\n\n // Extract chunked hashes from failed transactions\n const failedTransactions = failedIndexes.map((idx) => transactions[idx]);\n const chunkedHashes: string[] = [];\n\n for (const tx of failedTransactions) {\n try {\n const typedArgs = extractTypedArgsFromTransaction(tx, \"chunked\");\n if (typedArgs.type === \"chunked\") {\n chunkedHashes.push(typedArgs.args.hash);\n }\n } catch {\n // Not a chunked transaction, skip\n }\n }\n\n if (chunkedHashes.length === 0) {\n // No chunked transactions to check, return all failed indexes\n return failedIndexes;\n }\n\n // Check which chunks exist on-chain\n const existingChunks = await checkXmlChunksExist({\n storageClient,\n chunkedHashes,\n operatorAddress: backendWalletAddress,\n });\n\n // Filter out indexes where the transaction has succeeded\n const stillFailed: number[] = [];\n\n for (const failedIdx of failedIndexes) {\n const tx = transactions[failedIdx];\n try {\n const typedArgs = extractTypedArgsFromTransaction(tx, \"chunked\");\n if (typedArgs.type === \"chunked\") {\n const hash = typedArgs.args.hash;\n if (!existingChunks.has(hash)) {\n // Transaction still hasn't succeeded\n stillFailed.push(failedIdx);\n }\n // If hash exists, transaction succeeded, skip retry\n } else {\n // Non-chunked transaction, always retry\n stillFailed.push(failedIdx);\n }\n } catch {\n // Can't determine type, retry to be safe\n stillFailed.push(failedIdx);\n }\n }\n\n return stillFailed;\n}\n\n","import type { WriteTransactionConfig } from \"@net-protocol/core\";\nimport type { StorageClient } from \"@net-protocol/storage\";\nimport type { Address } from \"viem\";\nimport type { RetryConfig, RelaySubmitResult } from \"@net-protocol/relay\";\nimport type { RetryFailedTransactionsParams } from \"./types\";\nimport { retryFailedTransactions as retryFailedTransactionsPackage } from \"@net-protocol/relay\";\nimport { recheckFailedTransactionsStorage } from \"./recheckStorage\";\n\n/**\n * Retry failed transactions with exponential backoff\n *\n * This is a wrapper around the package retryFailedTransactions that adds\n * storage-specific recheck logic.\n *\n * @param params - Retry parameters\n * @returns Final success/failure status after retries\n */\nexport async function retryFailedTransactions(\n params: RetryFailedTransactionsParams\n): Promise<RelaySubmitResult> {\n const {\n storageClient,\n backendWalletAddress,\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes,\n originalTransactions,\n config,\n sessionToken,\n } = params;\n\n // Use storage-specific recheck function\n return retryFailedTransactionsPackage({\n apiUrl,\n chainId,\n operatorAddress,\n secretKey,\n failedIndexes,\n originalTransactions,\n backendWalletAddress,\n config,\n sessionToken,\n recheckFunction: async (\n failedIndexes: number[],\n transactions: WriteTransactionConfig[],\n backendWalletAddress: Address\n ) => {\n return recheckFailedTransactionsStorage(\n failedIndexes,\n transactions,\n storageClient,\n backendWalletAddress\n );\n },\n });\n}\n","import { readFileSync } from \"fs\";\nimport {\n getStorageKeyBytes,\n detectFileTypeFromBase64,\n base64ToDataUri,\n} from \"@net-protocol/storage\";\nimport { StorageClient } from \"@net-protocol/storage\";\nimport { hexToString } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\nimport { http, createWalletClient } from \"viem\";\nimport { getPublicClient, getChainRpcUrls } from \"@net-protocol/core\";\nimport type { Address, Hash } from \"viem\";\nimport { filterXmlStorageTransactions } from \"../transactions/filter\";\nimport { checkXmlMetadataExists } from \"../storage/check\";\nimport { extractTypedArgsFromTransaction } from \"../utils\";\nimport {\n createRelayX402Client,\n fundBackendWallet,\n checkBackendWalletBalance,\n submitTransactionsViaRelay,\n waitForConfirmations,\n createRelaySession,\n batchTransactions,\n} from \"@net-protocol/relay\";\nimport { retryFailedTransactions } from \"../relay/retry\";\nimport type {\n UploadWithRelayOptions,\n UploadWithRelayResult,\n} from \"../relay/types\";\nimport type { WriteTransactionConfig } from \"@net-protocol/core\";\n\n/**\n * Main upload function with relay - orchestrates the entire relay upload process\n *\n * Flow:\n * 1. Read file\n * 2. Fund backend wallet (x402 payment)\n * 3. Prepare transactions with backendWalletAddress as operator\n * 4. Split transactions (metadata vs chunks)\n * 5. Filter existing transactions (idempotency)\n * 6. Submit chunks via relay (backend wallet pays gas)\n * 7. Retry failed chunks\n * 8. Submit metadata directly (user pays gas)\n * 9. Wait for confirmations\n * 10. Return result\n */\nexport async function uploadFileWithRelay(\n options: UploadWithRelayOptions\n): Promise<UploadWithRelayResult> {\n const errors: Error[] = [];\n\n // 1. Read file\n const fileBuffer = readFileSync(options.filePath);\n\n // Detect if file is binary\n const isBinary = fileBuffer.some(\n (byte) =>\n byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)\n );\n\n // Convert based on file type\n let fileContent: string;\n if (isBinary) {\n const base64String = fileBuffer.toString(\"base64\");\n const detectedType = detectFileTypeFromBase64(base64String);\n if (detectedType) {\n fileContent = base64ToDataUri(base64String);\n } else {\n fileContent = base64String;\n }\n } else {\n fileContent = fileBuffer.toString(\"utf-8\");\n }\n\n // 2. Create StorageClient\n // Note: Relay upload always uses XML storage format, regardless of file size\n // prepareXmlStorage() handles small files by creating a single chunk with XML metadata\n const storageClient = new StorageClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // 4. Create user wallet client\n const userAccount = privateKeyToAccount(options.privateKey);\n const userAddress = userAccount.address;\n const publicClient = getPublicClient({\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n const rpcUrls = getChainRpcUrls({\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n const userWalletClient = createWalletClient({\n account: userAccount,\n chain: publicClient.chain!,\n transport: http(rpcUrls[0]), // Use first RPC URL\n });\n\n // 5. Setup x402 client\n const { fetchWithPayment, httpClient } = createRelayX402Client(\n userAccount,\n options.chainId\n );\n\n // 5.5. Create relay session token (sign once, reuse for all batches)\n // Session token is required for all submit requests\n const sessionResult = await createRelaySession({\n apiUrl: options.apiUrl,\n chainId: options.chainId,\n operatorAddress: userAddress,\n secretKey: options.secretKey,\n account: userAccount,\n expiresIn: 3600, // 1 hour - should be enough for most uploads\n });\n const sessionToken = sessionResult.sessionToken;\n console.log(\"āœ“ Session token created (valid for 1 hour)\");\n\n // 6. Check backend wallet balance and fund if needed\n // Check balance first to avoid unnecessary payments\n let backendWalletAddress: Address | undefined;\n let shouldFund = true;\n\n try {\n const balanceResult = await checkBackendWalletBalance({\n apiUrl: options.apiUrl,\n chainId: options.chainId,\n operatorAddress: userAddress,\n secretKey: options.secretKey,\n });\n backendWalletAddress = balanceResult.backendWalletAddress;\n\n // Only fund if balance is insufficient\n shouldFund = !balanceResult.sufficientBalance;\n } catch (error) {\n // If balance check fails, fall back to funding (for backwards compatibility)\n // This handles cases where the balance endpoint might not be available\n shouldFund = true;\n }\n\n // Fund backend wallet only if balance is insufficient\n // This ensures backendWalletAddress is always set\n if (shouldFund) {\n const fundResult = await fundBackendWallet({\n apiUrl: options.apiUrl,\n chainId: options.chainId,\n operatorAddress: userAddress,\n secretKey: options.secretKey,\n fetchWithPayment,\n httpClient,\n });\n backendWalletAddress = fundResult.backendWalletAddress;\n }\n\n // TypeScript assertion: backendWalletAddress is guaranteed to be set at this point\n // (either from balance check or fund call)\n if (!backendWalletAddress) {\n throw new Error(\"Failed to determine backend wallet address\");\n }\n\n // backendWalletAddress is now guaranteed to be set (either from balance check or fund call)\n\n // 7. Prepare chunks with backendWalletAddress as operator (chunks submitted via relay)\n // Use StorageClient.prepareXmlStorage() to get chunk transactions\n const chunkPrepareResult = storageClient.prepareXmlStorage({\n data: fileContent,\n operatorAddress: backendWalletAddress,\n storageKey: options.storageKey,\n filename: options.text,\n useChunkedStorageBackend: true,\n });\n\n const chunkTxs = chunkPrepareResult.transactionConfigs.slice(1); // Skip metadata, get chunks\n const topLevelHash = chunkPrepareResult.topLevelHash;\n const chunkMetadata = chunkPrepareResult.metadata; // XML metadata referencing backend wallet chunks\n\n // 8. Prepare metadata transaction separately with userAddress as operator\n // Metadata is submitted directly by user, so it should use userAddress\n // We use the same XML metadata string (which references chunks stored by backend wallet)\n const metadataTx = storageClient.preparePut({\n key: topLevelHash,\n text: options.text,\n value: chunkMetadata, // Use the XML metadata from chunk preparation\n });\n\n // 9. Filter existing chunks (idempotency check with backendWalletAddress)\n const filteredChunks = await filterXmlStorageTransactions({\n storageClient,\n transactions: chunkTxs,\n operatorAddress: backendWalletAddress,\n });\n\n const chunksToSend = filteredChunks.toSend;\n const chunksSkipped = filteredChunks.skipped.length;\n\n // 10. Check if metadata already exists (with userAddress as operator)\n // Extract metadata args from the prepared transaction\n const metadataStorageKey = metadataTx.args[0] as `0x${string}`;\n const expectedMetadata = hexToString(metadataTx.args[2] as `0x${string}`);\n let metadataNeedsSubmission = true;\n\n const metadataCheck = await checkXmlMetadataExists({\n storageClient,\n storageKey: metadataStorageKey,\n operatorAddress: userAddress, // User is operator for metadata\n expectedMetadata,\n });\n if (metadataCheck.exists && metadataCheck.matches) {\n metadataNeedsSubmission = false;\n }\n\n // 11. Batch and submit chunks via relay (if any)\n let chunkTransactionHashes: Hash[] = [];\n let chunksSent = 0;\n\n if (chunksToSend.length > 0) {\n try {\n // Batch chunks to respect server limits (100 transactions, 1MB per request)\n const batches = batchTransactions(chunksToSend);\n const totalBatches = batches.length;\n\n if (totalBatches > 1) {\n console.log(\n `šŸ“¦ Splitting ${chunksToSend.length} chunks into ${totalBatches} batch(es)`\n );\n }\n\n // Submit batches sequentially\n for (let batchIndex = 0; batchIndex < batches.length; batchIndex++) {\n const batch = batches[batchIndex];\n\n if (totalBatches > 1) {\n console.log(\n `šŸ“¤ Sending batch ${batchIndex + 1}/${totalBatches} (${\n batch.length\n } transactions)...`\n );\n }\n\n const submitResult = await submitTransactionsViaRelay({\n apiUrl: options.apiUrl,\n chainId: options.chainId,\n operatorAddress: userAddress,\n secretKey: options.secretKey,\n transactions: batch,\n sessionToken,\n });\n\n chunkTransactionHashes.push(...submitResult.transactionHashes);\n chunksSent += submitResult.successfulIndexes.length;\n\n // Check if ALL transactions in this batch failed\n if (submitResult.failedIndexes.length === batch.length) {\n // All transactions failed - likely due to insufficient funds or network issues\n // Don't retry (would waste app fees) and stop processing subsequent batches\n const errorMessage =\n `Batch ${batchIndex + 1}: All ${\n batch.length\n } transactions failed. ` +\n `Likely due to insufficient backend wallet balance or network issues. ` +\n `Stopping batch processing to avoid wasting app fees.`;\n\n console.error(`āŒ ${errorMessage}`);\n errors.push(new Error(errorMessage));\n\n // Stop processing subsequent batches\n break;\n }\n\n // 12. Retry failed chunks in this batch if any (only if some succeeded - partial failure)\n if (\n submitResult.failedIndexes.length > 0 &&\n submitResult.successfulIndexes.length > 0\n ) {\n // Map failed indexes to actual transactions from this batch\n const failedTxs = submitResult.failedIndexes.map((idx) => batch[idx]);\n\n try {\n const retryResult = await retryFailedTransactions({\n apiUrl: options.apiUrl,\n chainId: options.chainId,\n operatorAddress: userAddress,\n secretKey: options.secretKey,\n failedIndexes: submitResult.failedIndexes,\n originalTransactions: failedTxs,\n storageClient,\n backendWalletAddress,\n sessionToken,\n });\n\n // Merge retry results\n chunkTransactionHashes.push(...retryResult.transactionHashes);\n chunksSent += retryResult.successfulIndexes.length;\n\n if (retryResult.failedIndexes.length > 0) {\n errors.push(\n new Error(\n `Batch ${batchIndex + 1}: ${\n retryResult.failedIndexes.length\n } transactions failed after retries`\n )\n );\n }\n } catch (retryError) {\n errors.push(\n retryError instanceof Error\n ? retryError\n : new Error(\n `Batch ${batchIndex + 1} retry failed: ${String(\n retryError\n )}`\n )\n );\n }\n }\n\n // Optional: Wait for batch confirmations before next batch\n // This ensures we don't overwhelm the network and provides progress feedback\n if (\n batchIndex < batches.length - 1 &&\n chunkTransactionHashes.length > 0\n ) {\n // Get the hashes from this batch\n const batchHashes = chunkTransactionHashes.slice(\n -submitResult.successfulIndexes.length\n );\n if (batchHashes.length > 0) {\n try {\n await waitForConfirmations({\n publicClient,\n transactionHashes: batchHashes,\n confirmations: 1, // Just 1 confirmation between batches\n timeout: 30000, // 30 second timeout per batch\n });\n } catch (confirmationError) {\n // Log but don't fail - we'll wait for all confirmations later\n console.warn(\n `āš ļø Batch ${\n batchIndex + 1\n } confirmation timeout (continuing...)`\n );\n }\n }\n }\n }\n } catch (submitError) {\n errors.push(\n submitError instanceof Error\n ? submitError\n : new Error(`Chunk submission failed: ${String(submitError)}`)\n );\n }\n }\n\n // 13. Wait for chunk transaction confirmations\n if (chunkTransactionHashes.length > 0) {\n try {\n await waitForConfirmations({\n publicClient,\n transactionHashes: chunkTransactionHashes,\n confirmations: 1,\n timeout: 60000,\n });\n } catch (confirmationError) {\n errors.push(\n confirmationError instanceof Error\n ? confirmationError\n : new Error(`Chunk confirmation failed: ${String(confirmationError)}`)\n );\n }\n }\n\n // 14. Submit metadata directly (user pays gas)\n let metadataTransactionHash: Hash | undefined;\n if (metadataNeedsSubmission) {\n try {\n metadataTransactionHash = await userWalletClient.writeContract({\n address: metadataTx.to as Address,\n abi: metadataTx.abi,\n functionName: metadataTx.functionName,\n args: metadataTx.args,\n value:\n metadataTx.value !== undefined && metadataTx.value > BigInt(0)\n ? metadataTx.value\n : undefined,\n });\n\n // Wait for metadata confirmation\n await waitForConfirmations({\n publicClient,\n transactionHashes: [metadataTransactionHash],\n confirmations: 1,\n timeout: 60000,\n });\n } catch (metadataError) {\n errors.push(\n metadataError instanceof Error\n ? metadataError\n : new Error(`Metadata submission failed: ${String(metadataError)}`)\n );\n }\n }\n\n // 15. Return result\n return {\n success: errors.length === 0,\n topLevelHash,\n chunksSent,\n chunksSkipped,\n metadataSubmitted:\n metadataNeedsSubmission && metadataTransactionHash !== undefined,\n chunkTransactionHashes,\n metadataTransactionHash,\n backendWalletAddress,\n errors: errors.length > 0 ? errors : undefined,\n };\n}\n","import { readFileSync } from \"fs\";\nimport {\n shouldSuggestXmlStorage,\n getStorageKeyBytes,\n detectFileTypeFromBase64,\n base64ToDataUri,\n} from \"@net-protocol/storage\";\nimport { StorageClient } from \"@net-protocol/storage\";\nimport { stringToHex } from \"viem\";\nimport {\n prepareNormalStorageTransaction,\n prepareXmlStorageTransactions,\n} from \"../transactions/prep\";\nimport {\n filterExistingTransactions,\n filterXmlStorageTransactions,\n} from \"../transactions/filter\";\nimport { createWalletClientFromPrivateKey } from \"../transactions/send\";\nimport type {\n UploadOptions,\n PreviewResult,\n TransactionWithId,\n NormalStorageArgs,\n} from \"../types\";\n\n/**\n * Preview function - performs all prep steps but doesn't submit transactions\n * Returns statistics about what would be uploaded\n */\nexport async function previewFile(\n options: UploadOptions\n): Promise<PreviewResult> {\n // 1. Read file\n // Read file as buffer (binary) first\n const fileBuffer = readFileSync(options.filePath);\n\n // Detect if file is binary\n // Check for null bytes or non-text characters (excluding common whitespace)\n const isBinary = fileBuffer.some(\n (byte) =>\n byte === 0 || (byte < 32 && byte !== 9 && byte !== 10 && byte !== 13)\n );\n\n // Convert based on file type\n let fileContent: string;\n if (isBinary) {\n // Convert binary file to base64 string (valid UTF-8)\n const base64String = fileBuffer.toString(\"base64\");\n\n // Detect file type and add data URI prefix if detected\n const detectedType = detectFileTypeFromBase64(base64String);\n if (detectedType) {\n // Include data URI prefix for better type preservation\n // Format: \"data:audio/mpeg;base64,SUQz...\"\n fileContent = base64ToDataUri(base64String);\n } else {\n // Fallback to raw base64 if detection fails\n fileContent = base64String;\n }\n } else {\n // Read as UTF-8 for text files\n fileContent = fileBuffer.toString(\"utf-8\");\n }\n\n // 2. Create StorageClient\n const storageClient = new StorageClient({\n chainId: options.chainId,\n overrides: options.rpcUrl ? { rpcUrls: [options.rpcUrl] } : undefined,\n });\n\n // 3. Create wallet client (needed for operator address)\n const { operatorAddress } = createWalletClientFromPrivateKey({\n privateKey: options.privateKey,\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n\n // 4. Determine storage type\n const useXmlStorage = shouldSuggestXmlStorage(fileContent);\n const storageType: \"normal\" | \"xml\" = useXmlStorage ? \"xml\" : \"normal\";\n\n // 5. Prepare transactions\n let transactions: TransactionWithId[];\n\n if (useXmlStorage) {\n transactions = prepareXmlStorageTransactions({\n storageClient,\n storageKey: options.storageKey,\n text: options.text,\n content: fileContent,\n operatorAddress,\n });\n // No need to extract chunkedHashes - filterXmlStorageTransactions derives them internally\n } else {\n // Build typed args JSON object\n const storageKeyBytes = getStorageKeyBytes(\n options.storageKey\n ) as `0x${string}`;\n const typedArgs: NormalStorageArgs = {\n key: storageKeyBytes,\n text: options.text,\n value: stringToHex(fileContent),\n };\n\n transactions = [\n prepareNormalStorageTransaction(\n storageClient,\n typedArgs,\n options.storageKey // Pass original string key for preparePut\n ),\n ];\n }\n\n // 6. Filter existing transactions (idempotency)\n let transactionsToSend: TransactionWithId[];\n let transactionsSkipped: TransactionWithId[];\n\n if (useXmlStorage) {\n // Extract WriteTransactionConfig[] from TransactionWithId[]\n // First transaction is metadata, rest are chunk transactions\n const chunkTransactions = transactions\n .filter((tx) => tx.type === \"chunked\")\n .map((tx) => tx.transaction);\n\n // Create a map from WriteTransactionConfig to TransactionWithId for easy lookup\n const txConfigToTxWithId = new Map(\n transactions\n .filter((tx) => tx.type === \"chunked\")\n .map((tx) => [tx.transaction, tx])\n );\n\n const filtered = await filterXmlStorageTransactions({\n storageClient,\n transactions: chunkTransactions, // Only chunk transactions\n operatorAddress,\n });\n\n // Map filtered WriteTransactionConfig[] back to TransactionWithId[]\n const filteredToSend: TransactionWithId[] = filtered.toSend\n .map((txConfig) => txConfigToTxWithId.get(txConfig))\n .filter((tx): tx is TransactionWithId => tx !== undefined);\n\n const filteredSkipped: TransactionWithId[] = filtered.skipped\n .map((txConfig) => txConfigToTxWithId.get(txConfig))\n .filter((tx): tx is TransactionWithId => tx !== undefined);\n\n // Metadata is handled separately - check if it needs to be sent\n const metadataTx = transactions.find((tx) => tx.type === \"metadata\");\n if (metadataTx) {\n // For now, always include metadata in toSend (caller should check separately)\n filteredToSend.unshift(metadataTx);\n }\n\n transactionsToSend = filteredToSend;\n transactionsSkipped = filteredSkipped;\n } else {\n const filtered = await filterExistingTransactions({\n storageClient,\n transactions,\n operatorAddress,\n expectedContent: fileContent,\n });\n transactionsToSend = filtered.toSend;\n transactionsSkipped = filtered.skipped;\n }\n\n // Calculate statistics\n if (useXmlStorage) {\n // XML storage: separate chunks from metadata\n const chunkTransactions = transactions.filter(\n (tx) => tx.type === \"chunked\"\n );\n const metadataTransaction = transactions.find(\n (tx) => tx.type === \"metadata\"\n );\n\n const totalChunks = chunkTransactions.length;\n const alreadyStoredChunks = transactionsSkipped.filter(\n (tx) => tx.type === \"chunked\"\n ).length;\n const needToStoreChunks = transactionsToSend.filter(\n (tx) => tx.type === \"chunked\"\n ).length;\n const metadataNeedsStorage = metadataTransaction\n ? transactionsToSend.some((tx) => tx.type === \"metadata\")\n : false;\n\n return {\n storageType: \"xml\",\n totalChunks,\n alreadyStoredChunks,\n needToStoreChunks,\n metadataNeedsStorage,\n operatorAddress,\n storageKey: options.storageKey,\n totalTransactions: transactions.length,\n transactionsToSend: transactionsToSend.length,\n transactionsSkipped: transactionsSkipped.length,\n };\n } else {\n // Normal storage: single transaction counts as 1 chunk\n const totalChunks = 1;\n const alreadyStoredChunks = transactionsSkipped.length;\n const needToStoreChunks = transactionsToSend.length;\n\n return {\n storageType: \"normal\",\n totalChunks,\n alreadyStoredChunks,\n needToStoreChunks,\n operatorAddress,\n storageKey: options.storageKey,\n totalTransactions: transactions.length,\n transactionsToSend: transactionsToSend.length,\n transactionsSkipped: transactionsSkipped.length,\n };\n }\n}\n","import { Command } from \"commander\";\nimport chalk from \"chalk\";\nimport { parseCommonOptions } from \"../../cli/shared\";\nimport { uploadFile } from \"./core/upload\";\nimport { uploadFileWithRelay } from \"./core/uploadRelay\";\nimport { previewFile } from \"./core/preview\";\nimport { generateStorageUrl } from \"./utils\";\nimport type { UploadOptions } from \"./types\";\nimport type { UploadWithRelayOptions } from \"./relay/types\";\n\n/**\n * Register the storage command with the commander program\n */\nexport function registerStorageCommand(program: Command): void {\n // Command group - no options, no action\n const storageCommand = program\n .command(\"storage\")\n .description(\"Storage operations\");\n\n // Upload subcommand (current storage functionality)\n const uploadCommand = new Command(\"upload\")\n .description(\"Upload files to Net Storage\")\n .requiredOption(\"--file <path>\", \"Path to file to upload\")\n .requiredOption(\"--key <key>\", \"Storage key (filename/identifier)\")\n .requiredOption(\"--text <text>\", \"Text description/filename\")\n .option(\n \"--private-key <key>\",\n \"Private key (0x-prefixed hex, 66 characters). Can also be set via NET_PRIVATE_KEY env var\"\n )\n .option(\n \"--chain-id <id>\",\n \"Chain ID (8453 for Base, 1 for Ethereum, etc.). Can also be set via NET_CHAIN_ID env var\",\n (value) => parseInt(value, 10)\n )\n .option(\n \"--rpc-url <url>\",\n \"Custom RPC URL (can also be set via NET_RPC_URL env var)\"\n )\n .action(async (options) => {\n // Parse common options (private-key, chain-id, rpc-url)\n const commonOptions = parseCommonOptions({\n privateKey: options.privateKey,\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n\n const uploadOptions: UploadOptions = {\n filePath: options.file,\n storageKey: options.key,\n text: options.text,\n privateKey: commonOptions.privateKey,\n chainId: commonOptions.chainId,\n rpcUrl: commonOptions.rpcUrl,\n };\n\n try {\n console.log(chalk.blue(`šŸ“ Reading file: ${options.file}`));\n const result = await uploadFile(uploadOptions);\n\n // Generate storage URL\n const storageUrl = generateStorageUrl(\n result.operatorAddress,\n commonOptions.chainId,\n options.key\n );\n\n if (result.skipped && result.transactionsSent === 0) {\n console.log(\n chalk.green(\n `āœ“ All data already stored - skipping upload\\n Storage Key: ${\n options.key\n }\\n Skipped: ${result.transactionsSkipped} transaction(s)${\n storageUrl ? `\\n Storage URL: ${chalk.cyan(storageUrl)}` : \"\"\n }`\n )\n );\n process.exit(0);\n }\n\n if (result.success) {\n console.log(\n chalk.green(\n `āœ“ File uploaded successfully!\\n Storage Key: ${\n options.key\n }\\n Storage Type: ${\n result.storageType === \"xml\" ? \"XML\" : \"Normal\"\n }\\n Transactions Sent: ${\n result.transactionsSent\n }\\n Transactions Skipped: ${\n result.transactionsSkipped\n }\\n Final Transaction Hash: ${result.finalHash || \"N/A\"}${\n storageUrl ? `\\n Storage URL: ${chalk.cyan(storageUrl)}` : \"\"\n }`\n )\n );\n process.exit(0);\n } else {\n console.error(\n chalk.red(\n `āœ— Upload completed with errors\\n Transactions Sent: ${\n result.transactionsSent\n }\\n Transactions Skipped: ${\n result.transactionsSkipped\n }\\n Transactions Failed: ${\n result.transactionsFailed\n }\\n Error: ${result.error || \"Unknown error\"}`\n )\n );\n process.exit(1);\n }\n } catch (error) {\n console.error(\n chalk.red(\n `Upload failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n )\n );\n process.exit(1);\n }\n });\n\n // Preview subcommand\n const previewCommand = new Command(\"preview\")\n .description(\"Preview storage upload without submitting transactions\")\n .requiredOption(\"--file <path>\", \"Path to file to preview\")\n .requiredOption(\"--key <key>\", \"Storage key (filename/identifier)\")\n .requiredOption(\"--text <text>\", \"Text description/filename\")\n .option(\n \"--private-key <key>\",\n \"Private key (0x-prefixed hex, 66 characters). Can also be set via NET_PRIVATE_KEY env var\"\n )\n .option(\n \"--chain-id <id>\",\n \"Chain ID (8453 for Base, 1 for Ethereum, etc.). Can also be set via NET_CHAIN_ID env var\",\n (value) => parseInt(value, 10)\n )\n .option(\n \"--rpc-url <url>\",\n \"Custom RPC URL (can also be set via NET_RPC_URL env var)\"\n )\n .action(async (options) => {\n // Parse common options (private-key, chain-id, rpc-url)\n const commonOptions = parseCommonOptions({\n privateKey: options.privateKey,\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n\n const previewOptions: UploadOptions = {\n filePath: options.file,\n storageKey: options.key,\n text: options.text,\n privateKey: commonOptions.privateKey,\n chainId: commonOptions.chainId,\n rpcUrl: commonOptions.rpcUrl,\n };\n\n try {\n console.log(chalk.blue(`šŸ“ Reading file: ${options.file}`));\n const result = await previewFile(previewOptions);\n\n // Generate storage URL\n const storageUrl = generateStorageUrl(\n result.operatorAddress,\n commonOptions.chainId,\n options.key\n );\n\n // Display preview results\n console.log(chalk.cyan(\"\\nšŸ“Š Storage Preview:\"));\n console.log(` Storage Key: ${chalk.white(result.storageKey)}`);\n console.log(\n ` Storage Type: ${chalk.white(\n result.storageType === \"xml\" ? \"XML\" : \"Normal\"\n )}`\n );\n console.log(` Total Chunks: ${chalk.white(result.totalChunks)}`);\n console.log(\n ` Already Stored: ${chalk.green(result.alreadyStoredChunks)}`\n );\n console.log(\n ` Need to Store: ${chalk.yellow(result.needToStoreChunks)}`\n );\n\n if (result.storageType === \"xml\" && result.metadataNeedsStorage) {\n console.log(` Metadata: ${chalk.yellow(\"Needs Storage\")}`);\n } else if (result.storageType === \"xml\") {\n console.log(` Metadata: ${chalk.green(\"Already Stored\")}`);\n }\n\n console.log(\n ` Total Transactions: ${chalk.white(result.totalTransactions)}`\n );\n console.log(\n ` Transactions to Send: ${chalk.yellow(result.transactionsToSend)}`\n );\n console.log(\n ` Transactions Skipped: ${chalk.green(result.transactionsSkipped)}`\n );\n console.log(\n ` Operator Address: ${chalk.gray(result.operatorAddress)}`\n );\n\n if (storageUrl) {\n console.log(` Storage URL: ${chalk.cyan(storageUrl)}`);\n }\n\n if (result.needToStoreChunks === 0 && !result.metadataNeedsStorage) {\n console.log(\n chalk.green(\"\\nāœ“ All data is already stored - no upload needed\")\n );\n } else {\n console.log(\n chalk.yellow(\n `\\n⚠ ${result.transactionsToSend} transaction(s) would be sent`\n )\n );\n }\n\n process.exit(0);\n } catch (error) {\n console.error(\n chalk.red(\n `Preview failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n )\n );\n process.exit(1);\n }\n });\n\n // Upload-relay subcommand (relay upload via x402)\n const uploadRelayCommand = new Command(\"upload-relay\")\n .description(\"Upload files to Net Storage via x402 relay (backend pays gas for chunks)\")\n .requiredOption(\"--file <path>\", \"Path to file to upload\")\n .requiredOption(\"--key <key>\", \"Storage key (filename/identifier)\")\n .requiredOption(\"--text <text>\", \"Text description/filename\")\n .requiredOption(\n \"--api-url <url>\",\n \"Backend API URL (e.g., http://localhost:3000)\"\n )\n .requiredOption(\n \"--secret-key <key>\",\n \"Secret key for backend wallet derivation. Can also be set via X402_SECRET_KEY env var\"\n )\n .option(\n \"--private-key <key>\",\n \"Private key (0x-prefixed hex, 66 characters). Can also be set via NET_PRIVATE_KEY env var\"\n )\n .option(\n \"--chain-id <id>\",\n \"Chain ID (8453 for Base, 1 for Ethereum, etc.). Can also be set via NET_CHAIN_ID env var\",\n (value) => parseInt(value, 10)\n )\n .option(\n \"--rpc-url <url>\",\n \"Custom RPC URL (can also be set via NET_RPC_URL env var)\"\n )\n .action(async (options) => {\n // Parse common options (private-key, chain-id, rpc-url)\n const commonOptions = parseCommonOptions({\n privateKey: options.privateKey,\n chainId: options.chainId,\n rpcUrl: options.rpcUrl,\n });\n\n // Parse secret key from options or env\n const secretKey =\n options.secretKey || process.env.X402_SECRET_KEY;\n if (!secretKey) {\n console.error(\n chalk.red(\n \"Error: --secret-key is required or set X402_SECRET_KEY environment variable\"\n )\n );\n process.exit(1);\n }\n\n const uploadRelayOptions: UploadWithRelayOptions = {\n filePath: options.file,\n storageKey: options.key,\n text: options.text,\n privateKey: commonOptions.privateKey,\n chainId: commonOptions.chainId,\n rpcUrl: commonOptions.rpcUrl,\n apiUrl: options.apiUrl,\n secretKey,\n };\n\n try {\n console.log(chalk.blue(`šŸ“ Reading file: ${options.file}`));\n console.log(chalk.blue(`šŸ”— Using relay API: ${options.apiUrl}`));\n const result = await uploadFileWithRelay(uploadRelayOptions);\n\n // Generate storage URL (using user address, not backend wallet)\n const { privateKeyToAccount } = await import(\"viem/accounts\");\n const userAccount = privateKeyToAccount(commonOptions.privateKey);\n const storageUrl = generateStorageUrl(\n userAccount.address,\n commonOptions.chainId,\n options.key\n );\n\n if (result.success) {\n console.log(\n chalk.green(\n `āœ“ File uploaded successfully via relay!\\n Storage Key: ${\n options.key\n }\\n Top-Level Hash: ${result.topLevelHash}\\n Chunks Sent: ${\n result.chunksSent\n }\\n Chunks Skipped: ${\n result.chunksSkipped\n }\\n Metadata Submitted: ${\n result.metadataSubmitted ? \"Yes\" : \"No (already exists)\"\n }\\n Backend Wallet: ${result.backendWalletAddress}\\n Chunk Transaction Hashes: ${\n result.chunkTransactionHashes.length > 0\n ? result.chunkTransactionHashes.join(\", \")\n : \"None\"\n }${\n result.metadataTransactionHash\n ? `\\n Metadata Transaction Hash: ${result.metadataTransactionHash}`\n : \"\"\n }${\n storageUrl ? `\\n Storage URL: ${chalk.cyan(storageUrl)}` : \"\"\n }`\n )\n );\n process.exit(0);\n } else {\n console.error(\n chalk.red(\n `āœ— Upload completed with errors\\n Chunks Sent: ${\n result.chunksSent\n }\\n Chunks Skipped: ${\n result.chunksSkipped\n }\\n Metadata Submitted: ${\n result.metadataSubmitted ? \"Yes\" : \"No\"\n }\\n Errors: ${\n result.errors\n ? result.errors.map((e) => e.message).join(\", \")\n : \"Unknown error\"\n }`\n )\n );\n process.exit(1);\n }\n } catch (error) {\n console.error(\n chalk.red(\n `Upload via relay failed: ${\n error instanceof Error ? error.message : String(error)\n }`\n )\n );\n process.exit(1);\n }\n });\n\n storageCommand.addCommand(uploadCommand);\n storageCommand.addCommand(previewCommand);\n storageCommand.addCommand(uploadRelayCommand);\n}\n","#!/usr/bin/env node\n\nimport \"dotenv/config\";\nimport { Command } from \"commander\";\nimport { registerStorageCommand } from \"../commands/storage\";\n\nconst program = new Command();\n\nprogram\n .name(\"netp\")\n .description(\"CLI tool for Net Protocol\")\n .version(\"0.1.0\");\n\n// Register commands\nregisterStorageCommand(program);\n\nprogram.parse();\n"]}
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@net-protocol/cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI tool for Net Protocol",
5
+ "type": "module",
6
+ "bin": {
7
+ "netp": "./dist/cli/index.mjs"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md"
12
+ ],
13
+ "scripts": {
14
+ "build": "tsup",
15
+ "build:watch": "tsup --watch",
16
+ "clean": "rm -rf dist",
17
+ "dev": "tsx watch src/cli/index.ts",
18
+ "start": "tsx src/cli/index.ts",
19
+ "typecheck": "tsc --noEmit",
20
+ "prepack": "../../scripts/prepack-modify-deps.sh",
21
+ "prepublishOnly": "yarn build",
22
+ "postpublish": "../../scripts/postpublish-restore-deps.sh",
23
+ "test": "vitest --run",
24
+ "test:watch": "vitest --watch",
25
+ "test:ui": "vitest --ui",
26
+ "test:coverage": "vitest run --coverage"
27
+ },
28
+ "dependencies": {
29
+ "@net-protocol/core": "^0.1.4",
30
+ "@net-protocol/relay": "^0.1.3",
31
+ "@net-protocol/storage": "^0.1.9",
32
+ "@x402/evm": "^2.1.0",
33
+ "@x402/fetch": "^2.1.0",
34
+ "chalk": "^5.3.0",
35
+ "commander": "^12.1.0",
36
+ "dotenv": "^17.2.3",
37
+ "viem": "^2.31.4"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^20.17.6",
41
+ "@vitest/ui": "^1.0.0",
42
+ "tsup": "^8.0.0",
43
+ "tsx": "^4.21.0",
44
+ "typescript": "^5.6.3",
45
+ "vitest": "^1.0.0"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public",
49
+ "registry": "https://registry.npmjs.org/"
50
+ },
51
+ "repository": {
52
+ "type": "git",
53
+ "url": "https://github.com/stuckinaboot/net-public.git",
54
+ "directory": "packages/net-cli"
55
+ },
56
+ "keywords": [
57
+ "net",
58
+ "protocol",
59
+ "blockchain",
60
+ "ethereum",
61
+ "cli",
62
+ "storage"
63
+ ],
64
+ "license": "MIT"
65
+ }