Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/ChainSafe.Gaming/RPC/Bytes/Bytes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,27 @@

namespace ChainSafe.Gaming.Evm.Bytes
{
/// <summary>
/// Provides utility functions for manipulating and validating byte arrays and hexadecimal strings.
/// </summary>
public class Bytes
{
/// <summary>
/// Converts a byte array into its hexadecimal representation with a "0x" prefix.
/// </summary>
/// <param name="value">Byte array to be converted.</param>
/// <returns>Hexadecimal representation of the byte array with "0x" prefix.</returns>
public static string Hexlify(byte[] value)
{
return "0x" + BitConverter.ToString(value).Replace("-", string.Empty);
}

/// <summary>
/// Converts a string into its hexadecimal representation with a "0x" prefix.
/// If the string is already in hex format, it is returned as is.
/// </summary>
/// <param name="value">String to be converted.</param>
/// <returns>Hexadecimal representation of the string with "0x" prefix, or the original string if it's already in hex format.</returns>
public static string Hexlify(string value)
{
if (IsHexString(value))
Expand All @@ -20,6 +34,13 @@ public static string Hexlify(string value)
return "0x" + value;
}

/// <summary>
/// Pads the provided hexadecimal string with zeros to meet the desired length.
/// </summary>
/// <param name="value">Hexadecimal string to be padded.</param>
/// <param name="lenght">Desired length for the hexadecimal string representation excluding the "0x" prefix.</param>
/// <returns>Hexadecimal string padded with zeros to the specified length.</returns>
/// <exception cref="Exception">Thrown when the provided value is not a valid hex string or if the value's length exceeds the desired length.</exception>
public static string HexZeroPad(string value, int lenght)
{
if (!IsHexString(value))
Expand All @@ -34,25 +55,35 @@ public static string HexZeroPad(string value, int lenght)

while (value.Length < (2 * lenght) + 2)
{
value = string.Format("0x0{0}", value.Substring(2));
value = $"0x0{value.Substring(2)}";
}

return value;
}

/// <summary>
/// Pads the provided byte array with zeros to meet the desired length in its hexadecimal representation.
/// </summary>
/// <param name="value">Byte array to be padded.</param>
/// <param name="lenght">Desired length for the hexadecimal representation excluding the "0x" prefix.</param>
/// <returns>Hexadecimal representation of the byte array, padded with zeros to the specified length.</returns>
public static string HexZeroPad(byte[] value, int lenght)
{
return HexZeroPad(Hexlify(value), lenght);
}

/// <summary>
/// Validates if the provided string is a valid hexadecimal string with a "0x" prefix.
/// </summary>
/// <param name="value">String to be validated.</param>
/// <returns>True if the string is a valid hexadecimal string, otherwise false.</returns>
public static bool IsHexString(string value)
{
if (!new Regex("^0x[0-9a-fA-F]*$").IsMatch(value))
{
return false;
}

// if (length && value.length !== 2 + 2 * length) { return false; }
return true;
}
}
Expand Down
36 changes: 36 additions & 0 deletions src/ChainSafe.Gaming/RPC/Contracts/Builders/ABITypedRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@

namespace ChainSafe.Gaming.Evm.Contracts.Builders
{
/// <summary>
/// A static class for managing and accessing ABI (Application Binary Interface) types for smart contracts.
/// </summary>
public static class ABITypedRegistry
{
private static readonly ConcurrentDictionary<Type, FunctionABI> FunctionAbiRegistry = new();
Expand All @@ -13,11 +16,22 @@ public static class ABITypedRegistry

private static readonly AttributesToABIExtractor AbiExtractor = new();

/// <summary>
/// Gets the FunctionABI of type TFunctionMessage.
/// </summary>
/// <typeparam name="TFunctionMessage">The type of the function message.</typeparam>
/// <returns>An object of type FunctionABI.</returns>
public static FunctionABI GetFunctionABI<TFunctionMessage>()
{
return GetFunctionABI(typeof(TFunctionMessage));
}

/// <summary>
/// Gets the FunctionABI for the given type.
/// </summary>
/// <param name="functionABIType">The type to get the FunctionABI for.</param>
/// <returns>An object of type FunctionABI.</returns>
/// <exception cref="ArgumentException">Thrown when the given type is not a valid FunctionABI type.</exception>
public static FunctionABI GetFunctionABI(Type functionABIType)
{
if (!FunctionAbiRegistry.ContainsKey(functionABIType))
Expand All @@ -30,11 +44,22 @@ public static FunctionABI GetFunctionABI(Type functionABIType)
return FunctionAbiRegistry[functionABIType];
}

/// <summary>
/// Gets the EventABI of type TEvent.
/// </summary>
/// <typeparam name="TEvent">The type of the event.</typeparam>
/// <returns>An object of type EventABI.</returns>
public static EventABI GetEvent<TEvent>()
{
return GetEvent(typeof(TEvent));
}

/// <summary>
/// Gets the EventABI for the given type.
/// </summary>
/// <param name="type">The type to get the EventABI for.</param>
/// <returns>An object of type EventABI.</returns>
/// <exception cref="ArgumentException">Thrown when the given type is not a valid EventABI type.</exception>
public static EventABI GetEvent(Type type)
{
if (!EventAbiRegistry.ContainsKey(type))
Expand All @@ -47,11 +72,22 @@ public static EventABI GetEvent(Type type)
return EventAbiRegistry[type];
}

/// <summary>
/// Gets the ErrorABI of type TError.
/// </summary>
/// <typeparam name="TError">The type of the error.</typeparam>
/// <returns>An object of type ErrorABI.</returns>
public static ErrorABI GetError<TError>()
{
return GetError(typeof(TError));
}

/// <summary>
/// Gets the ErrorABI for the given type.
/// </summary>
/// <param name="type">The type to get the ErrorABI for.</param>
/// <returns>An object of type ErrorABI.</returns>
/// <exception cref="ArgumentException">Thrown when the given type is not a valid ErrorABI type.</exception>
public static ErrorABI GetError(Type type)
{
if (!ErrorAbiRegistry.ContainsKey(type))
Expand Down
76 changes: 76 additions & 0 deletions src/ChainSafe.Gaming/RPC/Contracts/Builders/ContractBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,54 +8,106 @@

namespace ChainSafe.Gaming.Evm.Contracts.Builders
{
/// <summary>
/// Represents a builder pattern class used to build a contract.
/// </summary>
public class ContractBuilder
{
/// <summary>
/// Initializes a new instance of the <see cref="ContractBuilder"/> class using ABI string and contract address.
/// </summary>
/// <param name="abi">ABI string of the contract.</param>
/// <param name="contractAddress">Ethereum address of the contract.</param>
public ContractBuilder(string abi, string contractAddress)
{
ContractABI = ABIDeserialiserFactory.DeserialiseContractABI(abi);
Address = contractAddress;
}

/// <summary>
/// Initializes a new instance of the <see cref="ContractBuilder"/> class using a contract message type and contract address.
/// </summary>
/// <param name="contractMessageType">Type containing attributes representing the contract ABI.</param>
/// <param name="contractAddress">Ethereum address of the contract.</param>
public ContractBuilder(Type contractMessageType, string contractAddress)
{
var abiExtractor = new AttributesToABIExtractor();
ContractABI = abiExtractor.ExtractContractABI(contractMessageType);
Address = contractAddress;
}

/// <summary>
/// Initializes a new instance of the <see cref="ContractBuilder"/> class using multiple contract message types and contract address.
/// </summary>
/// <param name="contractMessagesTypes">Array of Types containing attributes representing the contract ABI.</param>
/// <param name="contractAddress">Ethereum address of the contract.</param>
public ContractBuilder(Type[] contractMessagesTypes, string contractAddress)
{
var abiExtractor = new AttributesToABIExtractor();
ContractABI = abiExtractor.ExtractContractABI(contractMessagesTypes);
Address = contractAddress;
}

/// <summary>
/// Gets or sets the ABI of the contract.
/// </summary>
public ContractABI ContractABI { get; set; }

/// <summary>
/// Gets or sets the Ethereum address of the contract.
/// </summary>
public string Address { get; set; }

/// <summary>
/// Retrieves the default filter input for the contract.
/// </summary>
/// <param name="fromBlock">Starting block for the filter. Optional.</param>
/// <param name="toBlock">Ending block for the filter. Optional.</param>
/// <returns>The default filter input for the contract.</returns>
public NewFilterInput GetDefaultFilterInput(BlockParameter fromBlock = null, BlockParameter toBlock = null)
{
return FilterInputBuilder.GetDefaultFilterInput(Address, fromBlock, toBlock);
}

/// <summary>
/// Retrieves the function builder for a specific function using its type.
/// </summary>
/// <typeparam name="TFunction">Type of the function.</typeparam>
/// <returns>The function builder for the specified function type.</returns>
/// <exception cref="Exception">Thrown when the specified type lacks a required Function Attribute.</exception>
public FunctionBuilder<TFunction> GetFunctionBuilder<TFunction>()
{
var function = FunctionAttribute.GetAttribute<TFunction>() ??
throw new Exception("Invalid TFunction required a Function Attribute");
return new FunctionBuilder<TFunction>(Address, GetFunctionAbi(function.Name));
}

/// <summary>
/// Retrieves the function builder for a specific function using its name.
/// </summary>
/// <param name="name">Name of the function.</param>
/// <returns>The function builder for the specified function name.</returns>
public FunctionBuilder GetFunctionBuilder(string name)
{
return new FunctionBuilder(Address, GetFunctionAbi(name));
}

/// <summary>
/// Retrieves the function builder for a specific function using its signature.
/// </summary>
/// <param name="signature">Signature of the function.</param>
/// <returns>The function builder for the specified function signature.</returns>
public FunctionBuilder GetFunctionBuilderBySignature(string signature)
{
return new FunctionBuilder(Address, GetFunctionAbiBySignature(signature));
}

/// <summary>
/// Retrieves the error ABI for a specific error using its name.
/// </summary>
/// <param name="name">Name of the error.</param>
/// <returns>The error ABI for the specified name.</returns>
/// <exception cref="Exception">Thrown when the Contract ABI is not initialized or the error is not found.</exception>
public ErrorABI GetErrorAbi(string name)
{
if (ContractABI == null)
Expand All @@ -68,6 +120,12 @@ public ErrorABI GetErrorAbi(string name)
return errorAbi;
}

/// <summary>
/// Retrieves the event ABI for a specific event using its name.
/// </summary>
/// <param name="name">Name of the event.</param>
/// <returns>The event ABI for the specified name.</returns>
/// <exception cref="Exception">Thrown when the Contract ABI is not initialized or the event is not found.</exception>
public EventABI GetEventAbi(string name)
{
if (ContractABI == null)
Expand All @@ -80,6 +138,12 @@ public EventABI GetEventAbi(string name)
return eventAbi;
}

/// <summary>
/// Retrieves the event ABI for a specific event using its signature.
/// </summary>
/// <param name="signature">Signature of the event.</param>
/// <returns>The event ABI for the specified signature.</returns>
/// <exception cref="Exception">Thrown when the Contract ABI is not initialized or the event signature is not found.</exception>
public EventABI GetEventAbiBySignature(string signature)
{
if (ContractABI == null)
Expand All @@ -96,6 +160,12 @@ public EventABI GetEventAbiBySignature(string signature)
return eventAbi;
}

/// <summary>
/// Retrieves the function ABI for a specific function using its name.
/// </summary>
/// <param name="name">Name of the function.</param>
/// <returns>The function ABI for the specified name.</returns>
/// <exception cref="Exception">Thrown when the Contract ABI is not initialized or the function is not found.</exception>
public FunctionABI GetFunctionAbi(string name)
{
if (ContractABI == null)
Expand All @@ -108,6 +178,12 @@ public FunctionABI GetFunctionAbi(string name)
return functionAbi;
}

/// <summary>
/// Retrieves the function ABI for a specific function using its signature.
/// </summary>
/// <param name="signature">Signature of the function.</param>
/// <returns>The function ABI for the specified signature.</returns>
/// <exception cref="Exception">Thrown when the Contract ABI is not initialized or the function signature is not found.</exception>
public FunctionABI GetFunctionAbiBySignature(string signature)
{
if (ContractABI == null)
Expand Down
Loading