diff --git a/contracts/deployments/datahaven-logo.jpg b/contracts/deployments/datahaven-logo.jpg new file mode 100644 index 00000000..d1a4e7f8 Binary files /dev/null and b/contracts/deployments/datahaven-logo.jpg differ diff --git a/contracts/deployments/datahaven-logo.png b/contracts/deployments/datahaven-logo.png new file mode 100644 index 00000000..d1a4e7f8 Binary files /dev/null and b/contracts/deployments/datahaven-logo.png differ diff --git a/contracts/deployments/metadata.json b/contracts/deployments/metadata.json new file mode 100644 index 00000000..47b05ec1 --- /dev/null +++ b/contracts/deployments/metadata.json @@ -0,0 +1,7 @@ +{ + "name": "DataHaven", + "website": "https://datahaven.xyz/", + "description": "DataHaven is a decentralized, EigenLayer-secured AVS for distributed storage. By leveraging restaking, it ensures tamper-proof, censorship-resistant, and verifiable data persistence. Designed with AI and Web3 ecosystems in mind, DataHaven integrates seamlessly with smart contracts, offering developers reliable storage infrastructure for models, logs, and digital assets at scale..", + "logo": "https://raw.githubusercontent.com/datahaven-xyz/datahaven-files/refs/heads/main/files/datahaven-logo.png", + "twitter": "https://x.com/datahaven_xyz" +} \ No newline at end of file diff --git a/test/cli/handlers/contracts/.env.example b/test/cli/handlers/contracts/.env.example index 722016ef..0939183e 100644 --- a/test/cli/handlers/contracts/.env.example +++ b/test/cli/handlers/contracts/.env.example @@ -9,5 +9,5 @@ AVS_OWNER_PRIVATE_KEY=0x00000000000000000000000000000000000000000000000000000000 # Etherscan API key for contract verification (optional) # Get your API key from: https://etherscan.io/apis -# This is used for automatic contract verification on Hoodi block explorer -# ETHERSCAN_API_KEY=your_etherscan_api_key_here \ No newline at end of file +# This is used for contract verification on Etherscan +ETHERSCAN_API_KEY=your_etherscan_api_key_here \ No newline at end of file diff --git a/test/cli/handlers/contracts/index.ts b/test/cli/handlers/contracts/index.ts index d26d528a..681b6d8e 100644 --- a/test/cli/handlers/contracts/index.ts +++ b/test/cli/handlers/contracts/index.ts @@ -1,3 +1,4 @@ export * from "./deploy"; export * from "./status"; +export * from "./update-metadata"; export * from "./verify"; diff --git a/test/cli/handlers/contracts/update-metadata.ts b/test/cli/handlers/contracts/update-metadata.ts new file mode 100644 index 00000000..03ae6544 --- /dev/null +++ b/test/cli/handlers/contracts/update-metadata.ts @@ -0,0 +1,75 @@ +import { logger, parseDeploymentsFile, printDivider } from "utils"; +import { createPublicClient, createWalletClient, http } from "viem"; +import { privateKeyToAccount } from "viem/accounts"; +import { getChainDeploymentParams } from "../../../configs/contracts/config"; +import { dataHavenServiceManagerAbi } from "../../../contract-bindings/generated"; + +/** + * Updates the AVS metadata URI for the DataHaven Service Manager + */ +export const updateAVSMetadataURI = async (chain: string, uri: string) => { + try { + // Load environment variables + const avsOwnerPrivateKey = process.env.AVS_OWNER_PRIVATE_KEY; + if (!avsOwnerPrivateKey) { + throw new Error("AVS_OWNER_PRIVATE_KEY environment variable is required"); + } + + // Get chain configuration + const deploymentParams = getChainDeploymentParams(chain); + logger.info(`🫎 Updating AVS metadata URI on ${chain} chain`); + logger.info(`Network: ${deploymentParams.network} (Chain ID: ${deploymentParams.chainId})`); + logger.info(`RPC URL: ${deploymentParams.rpcUrl}`); + logger.info(`New URI: ${uri}`); + + // Create wallet client for the AVS owner + const account = privateKeyToAccount(avsOwnerPrivateKey as `0x${string}`); + const walletClient = createWalletClient({ + account, + transport: http(deploymentParams.rpcUrl) + }); + + // Create public client for reading transaction receipts + const publicClient = createPublicClient({ + transport: http(deploymentParams.rpcUrl) + }); + + logger.info(`Using account: ${account.address}`); + + const deployments = await parseDeploymentsFile(chain); + const serviceManagerAddress = deployments.ServiceManager; + + logger.info(`ServiceManager contract address: ${serviceManagerAddress}`); + + // Call the updateAVSMetadataURI function + logger.info("📝 Calling updateAVSMetadataURI..."); + + const hash = await walletClient.writeContract({ + address: serviceManagerAddress, + abi: dataHavenServiceManagerAbi, + functionName: "updateAVSMetadataURI", + args: [uri], + chain: null + }); + + logger.info("✅ Transaction submitted successfully!"); + logger.info(`Transaction hash: ${hash}`); + + // Wait for transaction confirmation + logger.info("⏳ Waiting for transaction confirmation..."); + const receipt = await publicClient.waitForTransactionReceipt({ hash }); + + if (receipt.status === "success") { + logger.info(`✅ Transaction confirmed in block ${receipt.blockNumber}`); + logger.info(`Gas used: ${receipt.gasUsed}`); + } else { + logger.error("❌ Transaction failed"); + } + + printDivider(); + return hash; + } catch (error) { + logger.error(`❌ Failed to update AVS metadata URI: ${error}`); + throw error; + } +}; diff --git a/test/cli/index.ts b/test/cli/index.ts index 577db57b..68f708c8 100644 --- a/test/cli/index.ts +++ b/test/cli/index.ts @@ -11,7 +11,8 @@ import { launch, launchPreActionHook, stop, - stopPreActionHook + stopPreActionHook, + updateAVSMetadataURI } from "./handlers"; // Function to parse integer @@ -187,6 +188,7 @@ const contractsCommand = program - status: Show deployment plan, configuration, and status (default) - deploy: Deploy contracts to specified chain - verify: Verify deployed contracts on block explorer + - update-metadata: Update the metadata URI of an existing AVS contract Common options: --chain: Target chain (required: hoodi, holesky, mainnet) @@ -229,6 +231,35 @@ contractsCommand .hook("preAction", contractsPreActionHook) .action(contractsVerify); +// Contracts Update Metadata +contractsCommand + .command("update-metadata") + .description("Update AVS metadata URI for the DataHaven Service Manager") + .option("--chain ", "Target chain (hoodi, holesky, mainnet)") + .option("--uri ", "New metadata URI (required)") + .option("--reset", "Use if you want to reset the metadata URI") + .option("--rpc-url ", "Chain RPC URL (optional, defaults based on chain)") + .action(async (options: any, command: any) => { + // Try to get chain from options or command + let chain = options.chain; + if (!chain && command.parent) { + chain = command.parent.getOptionValue("chain"); + } + if (!chain) { + chain = command.getOptionValue("chain"); + } + if (!options.uri && !options.reset) { + throw new Error("--uri parameter is required"); + } + if (options.reset) { + options.uri = ""; + } + if (!chain) { + throw new Error("--chain parameter is required"); + } + await updateAVSMetadataURI(chain, options.uri); + }); + // Default Contracts command (runs check) contractsCommand .description("Show deployment plan, configuration, and status")