{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "create2",
  "type": "registry:lib",
  "dependencies": [
    "js-sha3"
  ],
  "registryDependencies": [
    "https://ui.ednesdayw.com/r/wallet-address.json"
  ],
  "files": [
    {
      "path": "src/registry/lib/create2.ts",
      "content": "import { createHash } from \"crypto\";\nimport bs58 from \"bs58\";\nimport { keccak256 } from \"js-sha3\";\nimport { isEVMAddress, isTronAddress } from \"./wallet-address\";\n\n// ============ Types ============\ninterface Create2PredictAddressParams {\n  implementation: string;\n  deployer: string;\n  salt: string;\n}\n\n// ============ Constants ============\n// EIP-1167 Minimal Proxy Bytecode\nconst MINIMAL_PROXY = {\n  PREFIX: \"3d602d80600a3d3981f3363d3d373d3d3d363d73\",\n  EVM_SUFFIX: \"5af43d82803e903d91602b57fd5bf3ff\",\n  TRON_SUFFIX: \"5af43d82803e903d91602b57fd5bf341\",\n} as const;\n\n// Bytecode Processing\nconst BYTECODE_CONFIG = {\n  FIRST_PART_END: 110,\n  SECOND_PART_END: 280,\n  ADDRESS_SIZE: 40,\n} as const;\n\n// ============ Main Functions ============\n\n/**\n * Predicts the deterministic address for a contract using CREATE2\n */\nexport function create2(\n  data: Create2PredictAddressParams & { network?: \"evm\" | \"tron\" },\n) {\n  const { implementation, deployer, salt, network = \"evm\" } = data;\n  if (network === \"evm\") {\n    return predictDeterministicEVMAddress({ implementation, deployer, salt });\n  }\n  return predictDeterministicTronAddress({ implementation, deployer, salt });\n}\n\n/**\n * Predicts the deterministic address for an EVM contract using CREATE2\n */\nexport function predictDeterministicEVMAddress({\n  implementation,\n  deployer,\n  salt,\n}: Create2PredictAddressParams): string {\n  // Validate inputs\n  validateEVMAddress(implementation, \"implementation\");\n  validateEVMAddress(deployer, \"deployer\");\n  validateSalt(salt);\n\n  // Prepare parameters\n  const saltHex = stringToHex(salt, 32);\n  const cleanImplementation = removeHexPrefix(implementation);\n  const cleanDeployer = removeHexPrefix(deployer);\n\n  // Build bytecode\n  const bytecode = buildBytecode(\n    cleanImplementation,\n    cleanDeployer,\n    saltHex,\n    MINIMAL_PROXY.EVM_SUFFIX,\n  );\n\n  // Calculate address\n  const addressHex = calculateAddressFromBytecode(bytecode);\n  return toChecksumAddress(`0x${addressHex}`);\n}\n\n/**\n * Predicts the deterministic address for a TRON contract using CREATE2\n */\nexport function predictDeterministicTronAddress({\n  implementation,\n  deployer,\n  salt,\n}: Create2PredictAddressParams): string {\n  // Validate inputs\n  validateTronAddress(implementation, \"implementation\");\n  validateTronAddress(deployer, \"deployer\");\n  validateSalt(salt);\n\n  // Prepare parameters\n  const saltHex = stringToHex(salt, 32);\n  const cleanImplementation = tronAddressToHex(implementation);\n  const cleanDeployer = tronAddressToHex(deployer);\n\n  // Build bytecode\n  const bytecode = buildBytecode(\n    cleanImplementation,\n    cleanDeployer,\n    saltHex,\n    MINIMAL_PROXY.TRON_SUFFIX,\n  );\n\n  // Calculate address\n  const addressHex = calculateAddressFromBytecode(bytecode);\n  return hexToTronAddress(addressHex);\n}\n\n// ============ Validation Functions ============\n\nfunction validateEVMAddress(address: string, name: string): void {\n  if (!isEVMAddress(address)) {\n    throw new Error(`Invalid ${name} address: ${address}`);\n  }\n}\n\nfunction validateTronAddress(address: string, name: string): void {\n  if (!isTronAddress(address)) {\n    throw new Error(`Invalid ${name} address: ${address}`);\n  }\n}\n\nfunction validateSalt(salt: string): void {\n  if (salt.length > 32) {\n    throw new Error(`Salt must be less than 32 characters: ${salt}`);\n  }\n}\n\n// ============ Helper Functions ============\n\n/**\n * Builds the complete bytecode for CREATE2 address calculation\n */\nfunction buildBytecode(\n  implementation: string,\n  deployer: string,\n  saltHex: string,\n  suffix: string,\n): string {\n  let bytecode = `${MINIMAL_PROXY.PREFIX}${implementation}${suffix}${deployer}${saltHex}`;\n\n  // Add first hash\n  const firstPart = bytecode.slice(0, BYTECODE_CONFIG.FIRST_PART_END);\n  const firstHash = keccak256(Buffer.from(firstPart, \"hex\"));\n  bytecode += firstHash;\n\n  return bytecode;\n}\n\n/**\n * Calculates the final address from bytecode\n */\nfunction calculateAddressFromBytecode(bytecode: string): string {\n  const secondPart = bytecode.slice(\n    BYTECODE_CONFIG.FIRST_PART_END,\n    BYTECODE_CONFIG.SECOND_PART_END,\n  );\n  const secondHash = keccak256(Buffer.from(secondPart, \"hex\"));\n  return secondHash.slice(-BYTECODE_CONFIG.ADDRESS_SIZE);\n}\n\n/**\n * Converts a string to padded hex representation\n */\nfunction stringToHex(str: string, size: number): string {\n  const bytes = Buffer.from(str, \"utf8\");\n  if (bytes.length > size) {\n    throw new Error(`String is too long for size ${size}`);\n  }\n\n  const padded = Buffer.alloc(size);\n  bytes.copy(padded);\n  return padded.toString(\"hex\");\n}\n\n/**\n * Removes hex prefix and converts to lowercase\n */\nfunction removeHexPrefix(address: string): string {\n  return address.slice(2).toLowerCase();\n}\n\n// ============ Crypto Functions ============\n\n/**\n * SHA256 hash function\n */\nfunction sha256(data: Uint8Array): string {\n  return createHash(\"sha256\").update(data).digest(\"hex\");\n}\n\n/**\n * Converts hex string to Uint8Array\n */\nfunction hexToBytes(hex: string): Uint8Array {\n  const bytes = new Uint8Array(hex.length / 2);\n  for (let i = 0; i < hex.length; i += 2) {\n    bytes[i / 2] = Number.parseInt(hex.slice(i, i + 2), 16);\n  }\n  return bytes;\n}\n\n// ============ Address Conversion Functions ============\n\n/**\n * Converts TRON address to hex format\n */\nfunction tronAddressToHex(base58: string): string {\n  const bytes = bs58.decode(base58);\n  return Buffer.from(bytes.slice(1, 21)).toString(\"hex\").toLowerCase();\n}\n\n/**\n * Converts hex to TRON address format\n */\nfunction hexToTronAddress(hex: string): string {\n  const addr = `41${hex}`;\n  const addrBytes = hexToBytes(addr);\n  const checksum = calculateTronChecksum(addrBytes);\n  return bs58.encode(Buffer.concat([addrBytes, checksum]));\n}\n\n/**\n * Calculates TRON address checksum\n */\nfunction calculateTronChecksum(addressBytes: Uint8Array): Buffer {\n  const hash1 = sha256(addressBytes);\n  const hash2 = sha256(hexToBytes(hash1));\n  return Buffer.from(hash2.substring(0, 8), \"hex\");\n}\n\n/**\n * Converts address to EIP-55 checksum format\n */\nfunction toChecksumAddress(address: string): string {\n  const addr = address.toLowerCase().replace(\"0x\", \"\");\n  const hash = keccak256(Buffer.from(addr, \"utf8\"));\n\n  let checksumAddress = \"0x\";\n  for (let i = 0; i < addr.length; i++) {\n    const char = addr[i];\n    const hashChar = hash[i];\n\n    if (!char || !hashChar) continue;\n\n    const hashValue = Number.parseInt(hashChar, 16);\n    checksumAddress +=\n      Number.parseInt(char, 16) >= 10 && hashValue >= 8\n        ? char.toUpperCase()\n        : char;\n  }\n\n  return checksumAddress;\n}\n",
      "type": "registry:lib",
      "target": "lib/create2.ts"
    }
  ]
}