deploy static method

Future<SignalingContract> deploy({
  1. required Web3Client client,
  2. required EthPrivateKey credentials,
  3. List constructorParams = const [],
  4. int? chainId,
})

Deploy new contract instance

Pass a pre-configured Web3Client to avoid creating multiple clients and to maintain connection pooling efficiency.

Example:

final client = Web3Client('http://localhost:7545', http.Client());
final credentials = EthPrivateKey.fromHex('0x...');

final contract = await SignalingContract.deploy(
  client: client,
  credentials: credentials,
  chainId: 1337,  // Ganache
);

print('Deployed at: ${contract.contract.address.eip55With0x}');

Implementation

static Future<SignalingContract> deploy({
  required Web3Client client,
  required EthPrivateKey credentials,
  List<dynamic> constructorParams = const [],
  int? chainId,
}) async {
  // Prepare bytecode - remove 0x prefix if present
  final bytecodeData = hexToBytes(contractBytecode.startsWith('0x')
      ? contractBytecode.substring(2)
      : contractBytecode);

  // Use EIP-1559 transaction format for better compatibility with Ganache
  // Default gas price: 2 gwei (typical for Ganache)
  final gasPrice = EtherAmount.fromInt(EtherUnit.gwei, 2);

  final transaction = Transaction(
    from: credentials.address,
    data: bytecodeData,
    maxGas: 8000000, // Allow sufficient gas for contract deployment
    maxFeePerGas: gasPrice,
    maxPriorityFeePerGas: gasPrice,
  );

  // Send transaction with explicit chainId to avoid signature issues
  // Ganache default chainId is 1337, but can be overridden
  final txHash = await client.sendTransaction(
    credentials,
    transaction,
    chainId: chainId ?? 1337,
  );

  // Wait for transaction receipt and get contract address
  TransactionReceipt? receipt;
  int attempts = 0;
  while (receipt == null && attempts < 60) {
    await Future.delayed(Duration(seconds: 1));
    receipt = await client.getTransactionReceipt(txHash);
    attempts++;
  }

  if (receipt == null) {
    throw Exception('Contract deployment failed: transaction receipt not found after 60 seconds');
  }

  if (receipt.contractAddress == null) {
    throw Exception('Contract deployment failed: no contract address in receipt');
  }

  // Return connected instance
  return connect(
    client: client,
    contractAddress: receipt.contractAddress!,
    credentials: credentials,
  );
}