public DeployContract(IClient client) { this.client = client; this.ethSendTransaction = new EthSendTransaction(client); this.constructorCallEncoder = new ConstructorCallEncoder(); this.abiDeserialiser = new ABIDeserialiser(); }
/// <summary> ///同步 发送交易,返回交易回执 /// </summary> /// <param name="abi">合约abi</param> /// <param name="contractAddress">合约地址</param> /// <param name="functionName">合约请求调用方法名称</param> /// <param name="inputsParameters">方法对应的 参数</param> /// <param name="value">请求参数值</param> /// <returns>交易回执</returns> public ReceiptResultDto SendTranscationWithReceipt(string abi, string contractAddress, string functionName, Parameter[] inputsParameters, params object[] value) { ReceiptResultDto receiptResult = new ReceiptResultDto(); var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); var function = contract.Functions.FirstOrDefault(x => x.Name == functionName); var sha3Signature = function.Sha3Signature;// "0x53ba0944"; var functionCallEncoder = new FunctionCallEncoder(); var result = functionCallEncoder.EncodeRequest(sha3Signature, inputsParameters, value); var blockNumber = GetBlockNumber(); var transDto = BuildTransactionParams(result, blockNumber, contractAddress); var tx = BuildRLPTranscation(transDto); tx.Sign(new EthECKey(this._privateKey.HexToByteArray(), true)); var txHash = SendRequest <object>(tx.Data, tx.Signature); if (txHash != null) { receiptResult = GetTranscationReceipt(txHash.ToString()); } return(receiptResult); }
/// <summary> /// 异步 Call 调用 适用于链上调用但不需要共识(通常用constant,view等修饰的合约方法) /// </summary> /// <param name="contractAddress">合约地址</param> /// <param name="abi">合约abi</param> /// <param name="callFunctionName">调用方法名称</param> /// <returns>返回交易回执</returns> public async Task <ReceiptResultDto> CallRequestAsync(string contractAddress, string abi, string callFunctionName, Parameter[] inputsParameters = null, params object[] value) { CallInput callDto = new CallInput(); callDto.From = new Account(this._privateKey).Address.ToLower();//address ; var contractAbi = new ABIDeserialiser().DeserialiseContract(abi); callDto.To = contractAddress; callDto.Value = new HexBigInteger(0); var function = contractAbi.Functions.FirstOrDefault(x => x.Name == callFunctionName); var sha3Signature = function.Sha3Signature;// "0x53ba0944"; if (inputsParameters == null) { callDto.Data = "0x" + sha3Signature; } else { var functionCallEncoder = new FunctionCallEncoder(); var funcData = functionCallEncoder.EncodeRequest(sha3Signature, inputsParameters, value); callDto.Data = funcData; } var getRequest = new RpcRequest(this._requestId, JsonRPCAPIConfig.Call, new object[] { this._requestObjectId, callDto }); var result = await this._rpcClient.SendRequestAsync <ReceiptResultDto>(getRequest); //var getRequest = new RpcRequestMessage(this.RequestId, JsonRPCAPIConfig.Call, new object[] { this.RequestObjectId, callDto }); //var result = HttpUtils.RpcPost<ReceiptResultDto>(BaseConfig.DefaultUrl, getRequest); //同步方法 return(result); }
/// <summary> ///异步 发送交易,返回交易回执 /// </summary> /// <param name="abi">合约abi</param> /// <param name="contractAddress">合约地址</param> /// <param name="functionName">合约请求调用方法名称</param> /// <param name="inputsParameters">方法对应的 参数</param> /// <param name="value">请求参数值</param> /// <returns>交易回执</returns> public async Task <ReceiptResultDto> SendTranscationWithReceiptAsync(string abi, string contractAddress, string functionName, Parameter[] inputsParameters, params object[] value) { ReceiptResultDto receiptResult = new ReceiptResultDto(); var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); var function = contract.Functions.FirstOrDefault(x => x.Name == functionName); var sha3Signature = function.Sha3Signature;// "0x53ba0944"; var functionCallEncoder = new FunctionCallEncoder(); var result = functionCallEncoder.EncodeRequest(sha3Signature, inputsParameters, value); var blockNumber = await GetBlockNumberAsync(); var transDto = BuildTransactionParams(result, blockNumber, contractAddress); var tx = BuildRLPTranscation(transDto); tx.Sign(new EthECKey(this._privateKey.HexToByteArray(), true)); var txHash = await SendRequestAysnc <string>(tx.Data, tx.Signature); if (txHash != null) { receiptResult = await GetTranscationReceiptAsync(txHash); if (receiptResult == null) { throw new Exception("txHash != null 的时候报错了:" + receiptResult.ToJson()); } } return(receiptResult); }
public Contract(IClient client, string abi, string contractAddress) { ContractABI = new ABIDeserialiser().DeserialiseContract(abi); Client = client; Address = contractAddress; ethNewFilter = new EthNewFilter(client); }
/// <summary> /// 同步 通用合约部署,只返回交易Hash /// </summary> /// <param name="binCode">合约内容</param> /// <returns>交易Hash</returns> public string DeployContract(string binCode, string abi = null, params object[] values) { var blockNumber = GetBlockNumber(); var resultData = ""; ConstructorCallEncoder _constructorCallEncoder = new ConstructorCallEncoder(); var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); if (contract.Constructor != null) { if (values != null) { resultData = _constructorCallEncoder.EncodeRequest(binCode, contract.Constructor.InputParameters, values); } else { resultData = _constructorCallEncoder.EncodeRequest(binCode, ""); } } else { resultData = binCode; } var transParams = BuildTransactionParams(resultData, blockNumber, ""); var tx = BuildRLPTranscation(transParams); tx.Sign(new EthECKey(this._privateKey.HexToByteArray(), true)); var result = SendRequest <object>(tx.Data, tx.Signature); return(Convert.ToString(result)); }
/// <summary> /// 异步 通用合约部署,只返回交易Hash /// </summary> /// <param name="binCode">合约内容</param> /// <returns>交易Hash</returns> public async Task <string> DeployContractAsync(string binCode, string abi = null, params object[] values) { var blockNumber = await GetBlockNumberAsync(); var resultData = ""; ConstructorCallEncoder _constructorCallEncoder = new ConstructorCallEncoder(); if (values == null || values.Length == 0) { resultData = _constructorCallEncoder.EncodeRequest(binCode, ""); } var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); if (contract.Constructor == null) { throw new Exception( "Parameters supplied for a constructor but ABI does not contain a constructor definition"); } resultData = _constructorCallEncoder.EncodeRequest(binCode, contract.Constructor.InputParameters, values); var transParams = BuildTransactionParams(resultData, blockNumber, ""); var tx = BuildRLPTranscation(transParams); tx.Sign(new EthECKey(this._privateKey.HexToByteArray(), true)); var result = await SendRequestAysnc <string>(tx.Data, tx.Signature); return(result); }
public DeployContract(IClient client) { this.client = client; ethSendTransaction = new EthSendTransaction(client); personalSignAndSendTransaction = new PersonalSignAndSendTransaction(client); constructorCallEncoder = new ConstructorCallEncoder(); abiDeserialiser = new ABIDeserialiser(); }
public void ShouldDeserialisedAndEncodeSignatureEventsWithTuples() { var abi = "[{\"constant\":false,\"inputs\":[],\"name\":\"txRaiseEvent\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"x\",\"type\":\"bytes32\"},{\"name\":\"truncateToLength\",\"type\":\"uint256\"}],\"name\":\"bytes32ToString\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"source\",\"type\":\"string\"}],\"name\":\"stringToBytes32\",\"outputs\":[{\"name\":\"result\",\"type\":\"bytes32\"}],\"payable\":false,\"stateMutability\":\"pure\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"buyerSysId\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"buyerPurchaseOrderNumber\",\"type\":\"bytes32\"},{\"indexed\":true,\"name\":\"buyerProductId\",\"type\":\"bytes32\"},{\"components\":[{\"name\":\"ethPurchaseOrderNumber\",\"type\":\"uint64\"},{\"name\":\"buyerSysId\",\"type\":\"bytes32\"},{\"name\":\"buyerPurchaseOrderNumber\",\"type\":\"bytes32\"},{\"name\":\"sellerSysId\",\"type\":\"bytes32\"},{\"name\":\"sellerSalesOrderNumber\",\"type\":\"bytes32\"},{\"name\":\"buyerProductId\",\"type\":\"bytes32\"},{\"name\":\"sellerProductId\",\"type\":\"bytes32\"},{\"name\":\"currency\",\"type\":\"bytes32\"},{\"name\":\"currencyAddress\",\"type\":\"address\"},{\"name\":\"totalQuantity\",\"type\":\"uint32\"},{\"name\":\"totalValue\",\"type\":\"uint32\"},{\"name\":\"openInvoiceQuantity\",\"type\":\"uint32\"},{\"name\":\"openInvoiceValue\",\"type\":\"uint32\"},{\"name\":\"poStatus\",\"type\":\"uint8\"}],\"indexed\":false,\"name\":\"purchaseOrder\",\"type\":\"tuple\"}],\"name\":\"PurchaseRaisedLog\",\"type\":\"event\"}]"; var contractAbi = new ABIDeserialiser().DeserialiseContract(abi); var eventAbi = contractAbi.Events.FirstOrDefault(e => e.Name == "PurchaseRaisedLog"); Assert.Equal("8004ab55fa321fe77c5bde5420bc7af7d33f755d3d71ee4d59bf0c0af7b9c055", eventAbi.Sha3Signature); }
public ABIService( IABIRepository abiRepository, ILogFactory logFactory) { _abiDeserializer = new ABIDeserialiser(); _abiRepository = abiRepository; _log = logFactory.CreateLog(this); }
public void ShouldDeserialiseJArrayStyleABI() { var abi = "[{\"constant\":false,\"inputs\":[{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"productId\",\"type\":\"uint256\"},{\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"lineItem\",\"type\":\"tuple[]\"},{\"name\":\"customerId\",\"type\":\"uint256\"}],\"name\":\"purchaseOrder\",\"type\":\"tuple\"}],\"name\":\"SetPurchaseOrder\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[],\"name\":\"GetPurchaseOrder2\",\"outputs\":[{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"productId\",\"type\":\"uint256\"},{\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"lineItem\",\"type\":\"tuple[]\"},{\"name\":\"customerId\",\"type\":\"uint256\"}],\"name\":\"purchaseOrder\",\"type\":\"tuple\"}],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"GetPurchaseOrder\",\"outputs\":[{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"productId\",\"type\":\"uint256\"},{\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"lineItem\",\"type\":\"tuple[]\"},{\"name\":\"customerId\",\"type\":\"uint256\"}],\"name\":\"purchaseOrder\",\"type\":\"tuple\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"name\":\"sender\",\"type\":\"address\"},{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"components\":[{\"name\":\"id\",\"type\":\"uint256\"},{\"name\":\"productId\",\"type\":\"uint256\"},{\"name\":\"quantity\",\"type\":\"uint256\"}],\"name\":\"lineItem\",\"type\":\"tuple[]\"},{\"name\":\"customerId\",\"type\":\"uint256\"}],\"indexed\":false,\"name\":\"purchaseOrder\",\"type\":\"tuple\"}],\"name\":\"PurchaseOrderChanged\",\"type\":\"event\"}]"; var contractAbi = new ABIDeserialiser().DeserialiseContract(JArray.Parse(abi)); var functionABI = contractAbi.Functions.FirstOrDefault(e => e.Name == "SetPurchaseOrder"); var sig = functionABI.Sha3Signature; Assert.Equal("0cc400bd", functionABI.Sha3Signature); }
public string ContractGen(string abi, string contractName, string nameSpace) { contractName = MakeFirstCharUpper(contractName); var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); var operations = EventsGen(contract) + FunctionsGen(contract); var genContract = string.Format(ContractTemplate, abi.Replace("\"", "\"\""), contractName, operations); return(string.Format(NameSpaceTemplate, nameSpace, genContract)); }
public async Task VerifyFunctionCall <T>(string abi, string contractAddress, string functionName, T expectedResult, params object[] values) { var contractABI = new ABIDeserialiser().DeserialiseContract(abi); var functionABI = contractABI.Functions.FirstOrDefault(x => x.Name == functionName && x.InputParameters.Length == values.Length); var contract = web3.Eth.GetContract(abi, contractAddress); T result = await contract.GetFunctionBySignature(functionABI.Sha3Signature).CallAsync <T>(values); result.Should().BeEquivalentTo(expectedResult, $"The result of function call {functionName} is not expected"); }
public ServiceModel(string abi, string byteCode, string contractName = DEFAULT_CONTRACTNAME, string namespaceName = DEFAULT_NAMESPACE) { ContractName = CapitaliseFirstChar(contractName); Namespace = CapitaliseFirstChar(namespaceName); Abi = abi; ByteCode = byteCode; var des = new ABIDeserialiser(); Contract = des.DeserialiseContract(abi); }
public CommonModel(string abi, string byteCode, string namespaceName = DEFAULT_NAMESPACE) { utils = new Utils(); GlobalNames = new GlobalNames(); Namespace = Utils.CapitaliseFirstChar(namespaceName); Abi = abi; ByteCode = byteCode; var des = new ABIDeserialiser(); Contract = des.DeserialiseContract(abi); }
/// <summary> /// 同步 Call 调用 适用于链上调用但不需要共识(通常用constant,view等修饰的合约方法) /// </summary> /// <param name="contractAddress">合约地址</param> /// <param name="abi">合约abi</param> /// <param name="callFunctionName">调用方法名称</param> /// <returns>返回交易回执</returns> public ReceiptResultDto CallRequest(string contractAddress, string abi, string callFunctionName) { CallInput callDto = new CallInput(); callDto.From = new Account(this._privateKey).Address.ToLower();//address ; callDto.To = contractAddress; var contractAbi = new ABIDeserialiser().DeserialiseContract(abi); var function = contractAbi.Functions.FirstOrDefault(x => x.Name == callFunctionName); callDto.Value = new HexBigInteger(0); callDto.Data = "0x" + function.Sha3Signature; var request = new RpcRequestMessage(this._requestId, JsonRPCAPIConfig.Call, new object[] { this._requestObjectId, callDto }); var result = HttpUtils.RpcPost <ReceiptResultDto>(this._url, request);; return(result); }
public virtual void ShouldDeserializeContract() { string abi = @"[{""constant"":false,""inputs"":[{""name"":""a"",""type"":""uint256""}],""name"":""multiply"",""outputs"":[{""name"":""d"",""type"":""uint256""}],""type"":""function""},{""constant"":false,""inputs"":[{""name"":""a"",""type"":""uint256""},{""name"":""to"",""type"":""address""}],""name"":""other"",""outputs"":[{""name"":""d"",""type"":""uint256""}],""type"":""function""}]"; var des = new ABIDeserialiser(); var contract = des.DeserialiseContract(abi); var function = contract.Functions.FirstOrDefault(x => x.Name == "multiply"); Assert.NotNull(function); Assert.False(function.Constant); var param = function.InputParameters.FirstOrDefault(x => x.Name == "a"); Assert.NotNull(param); Assert.Equal(param.Type, "uint256"); Assert.Equal("c6888fa1", function.Sha3Signature); Assert.Equal("ea6ace3d", contract.Functions[1].Sha3Signature); }
public async Task QueueAllEventsForMakerDAOContract() { // Load config // - this will contain the secrets and connection strings we don't want to hard code var config = TestConfiguration.LoadConfig(); string azureStorageConnectionString = config["AzureStorageConnectionString"]; // Create a proxy for the blockchain var web3 = new Web3.Web3(TestConfiguration.BlockchainUrls.Infura.Mainnet); // Create Queue Factory // - In this sample we're targetting Azure // - The factory communicates with Azure to create and get different queues var queueFactory = new AzureSubscriberQueueFactory(azureStorageConnectionString); // Create a Queue // - This is where we're going to put the matching event logs var queue = await queueFactory.GetOrCreateQueueAsync("makerdaoevents"); // Get the maker DAO contract abi // - from this we're able to match and decode the events in the contract var contractAbi = new ABIDeserialiser().DeserialiseContract(MAKER_DAO_ABI); // Create an event subscription for these events // - Passing in the maker dao address to ensure only logs with a matching address are processed // - There is an option to pass an implementation of IEventHandlerHistoryRepository in to the constructor // - This would record history for each event handler and is used to prevent duplication var eventSubscription = new EventSubscription(contractAbi.Events, new[] { MAKER_CONTRACT_ADDRESS }); // Assign the queue to the event subscription // - Matching events will be written to this queue // - By default a generic message is written to the queue // - The message contains the raw log (aka FilterLog), decoded event parameter values and event metadata // - Therefore the message schema is consistent across all messages sent to any queues // - However - should you require your own queue message schema the method below accepts a custom message mapper // - Ultimately the message is converted to json eventSubscription.AddQueueHandler(queue); // Azure storage setup // - this example reads and writes block progress to an Azure storage table // - to avoid collision with other samples we provide a prefix var storageCloudSetup = new CloudTableSetup(azureStorageConnectionString, prefix: $"makerdao"); // Create a progress repository // - It stores and retrieves the most recent block processed var blockProgressRepo = storageCloudSetup.CreateBlockProgressRepository(); // Create a progress service // - This uses the progress repo to dictate what blocks to process next // - The MIN_BLOCK_NUMBER dictates the starting point if the progress repo is empty or has fallen too far behind var progressService = new BlockProgressService(web3, MIN_BLOCK_NUMBER, blockProgressRepo); // Create a filter // - This is essentially the query that is sent to the chain when retrieving logs // - It is OPTIONAL - without it, all logs in the block range are requested // - The filter is invoked before any event subscriptions evaluate the logs // - The subscriptions are free to implement their own matching logic // - In this sample we're only interested in MakerDAO logs // - Therefore it makes sense to restrict the number of logs to retrieve from the chain var makerAddressFilter = new NewFilterInput() { Address = new[] { MAKER_CONTRACT_ADDRESS } }; // Create a log processor // - This uses the blockchainProxy to get the logs // - It sends each log to the event subscriptions to indicate if the logs matches the subscription criteria // - It then allocates matching logs to separate batches per event subscription var logProcessor = new BlockRangeLogsProcessor(web3, new[] { eventSubscription }, makerAddressFilter); // Create a batch log processor service // - It uses the progress service to calculates the block range to progress // - It then invokes the log processor - passing in the range to process // - It updates progress via the progress service var batchProcessorService = new LogsProcessor(logProcessor, progressService, MAX_BLOCKS_PER_BATCH); // execute try { // Optional cancellation token // - Useful for cancelling long running processing operations var ctx = new System.Threading.CancellationTokenSource(); // instruct the service to get and process the next range of blocks // when the rangeProcessed is null - it means there was nothing to process var rangeProcessed = await batchProcessorService.ProcessOnceAsync(ctx.Token); // ensure we have processed the expected number of events // the event subscription has state which can record running totals across many processing batches Assert.Equal(16, eventSubscription.State.GetInt("EventsHandled")); // get the message count from the queue Assert.Equal(16, await queue.GetApproxMessageCountAsync()); } finally { // delete any data from Azure await ClearDown(queue, storageCloudSetup, queueFactory); } }
public DeployContract(ITransactionManager transactionManager) { TransactionManager = transactionManager; _constructorCallEncoder = new ConstructorCallEncoder(); _abiDeserialiser = new ABIDeserialiser(); }
public ContractBuilder(string abi, string contractAddress) { ContractABI = new ABIDeserialiser().DeserialiseContract(abi); Address = contractAddress; }
public async Task WriteAllEventsForMakerDAOToAzureStorage() { // Load config // - this will contain the secrets and connection strings we don't want to hard code var config = TestConfiguration.LoadConfig(); string azureStorageConnectionString = config["AzureStorageConnectionString"]; // Create a proxy for the blockchain // - It will get the logs from the chain // - It provides a log processing friendly abstraction // - Under the hood it wraps the Nethereum.Web3.Web3 object // - In this sample we're hardcoded to target mainnet var web3 = new Web3.Web3(TestConfiguration.BlockchainUrls.Infura.Mainnet); // Get the maker DAO contract abi // - from this we're able to match and decode the events in the contract var contractAbi = new ABIDeserialiser().DeserialiseContract(MAKER_DAO_ABI); // Create an event subscription for these events // - Passing in the maker dao address to ensure only logs with a matching address are processed // - There is an option to pass an implementation of IEventHandlerHistoryRepository in to the constructor // - This would record history for each event handler and is used to prevent duplication var eventSubscription = new EventSubscription(contractAbi.Events, new[] { MAKER_CONTRACT_ADDRESS }); // Create an Azure Table Storage Factory // - The factory communicates with Azure to create and get different tables var tableStorageFactory = new AzureTablesSubscriberRepositoryFactory(azureStorageConnectionString); // Create a Handler for a Table // - It wraps a table repository (routing ILogHandler calls to ITransactionLogRepository) // - This is where we're going to put the matching event logs // - we're supplying a table prefix // - the actual table name would be "<prefix>TransactionLogs" // - this allows us to have different tables for different groups of event logs // - the handler implements ILogHandler // - ILogHandler is a really simple interface to implement if you wish to customise the storage var storageHandlerForLogs = await tableStorageFactory.GetLogRepositoryHandlerAsync(tablePrefix : "makerdaoalleventstorage"); // Assign the storage handler to the event subscription // - Matching events will be passed to the handler // - internally the handler passes the events to the repository layer which writes them to Azure eventSubscription.AddStorageHandler(storageHandlerForLogs); // Azure storage setup (for storing Block Progress) // - this example reads and writes block progress to an Azure storage table // - to avoid collision with other samples we provide a prefix var storageCloudSetup = new CloudTableSetup(azureStorageConnectionString, prefix: $"makerdaoalleventstorage"); // Create a progress repository // - It stores and retrieves the most recent block processed var blockProgressRepo = storageCloudSetup.CreateBlockProgressRepository(); // Create a progress service // - This uses the progress repo to dictate what blocks to process next // - The MIN_BLOCK_NUMBER dictates the starting point if the progress repo is empty or has fallen too far behind var progressService = new BlockProgressService(web3, MIN_BLOCK_NUMBER, blockProgressRepo); // Create a filter // - This is essentially the query that is sent to the chain when retrieving logs // - It is OPTIONAL - without it, all logs in the block range are requested // - The filter is invoked before any event subscriptions evaluate the logs // - The subscriptions are free to implement their own matching logic // - In this sample we're only interested in MakerDAO logs // - Therefore it makes sense to restrict the number of logs to retrieve from the chain var makerAddressFilter = new NewFilterInput() { Address = new[] { MAKER_CONTRACT_ADDRESS } }; // Create a log processor // - This uses the blockchainProxy to get the logs // - It sends each log to the event subscriptions to indicate if the logs matches the subscription criteria // - It then allocates matching logs to separate batches per event subscription var logProcessor = new BlockRangeLogsProcessor(web3, new[] { eventSubscription }, makerAddressFilter); // Create a batch log processor service // - It uses the progress service to calculates the block range to progress // - It then invokes the log processor - passing in the range to process // - It updates progress via the progress service var batchProcessorService = new LogsProcessor(logProcessor, progressService, MAX_BLOCKS_PER_BATCH); // execute try { // Optional cancellation token // - Useful for cancelling long running processing operations var ctx = new System.Threading.CancellationTokenSource(); // instruct the service to get and process the next range of blocks // when the rangeProcessed is null - it means there was nothing to process var rangeProcessed = await batchProcessorService.ProcessOnceAsync(ctx.Token); // ensure we have processed the expected number of events // the event subscription has state which can record running totals across many processing batches Assert.Equal(16, eventSubscription.State.GetInt("EventsHandled")); // get the row count from azure storage // querying azure table storage is limited/basic // the TransactionHash is the partitionkey and the rowkey is the LogIndex // this allows us to query by tx hash var logRepositoryHandler = storageHandlerForLogs as TransactionLogRepositoryHandler; var repository = logRepositoryHandler.TransactionLogRepository as TransactionLogRepository; var expectedTransactionHashes = new[] { "0x19db52e6f823b39aa1763321514a3f4a07c66140b90d99bc28b7f4bc318e0c9c", "0x8d58abc578f5e321f2e6b7c0637ccc60fbf62b39b120691cbf19ff201f5069b0", "0x2a7da4088595861792bcd6c4201bcacc8e93e4b931a9254da82594cd42ca9993", "0x0bee561ac6bafb59bcc4c48fc4c1225aaedbab3e8089acea420140aafa47f3e5", "0x6fc82b076fa7088581a80869cb9c7a08d7f8e897670a9f67e39139b39246da7e", "0xdc2ee28db35ed5dbbc9e18a7d6bdbacb6e6633a9fce1ecda99ea7e1cf4bc8c72", "0xcd2fea48c84468f70c9a44c4ffd7b26064a2add8b72937edf593634d2501c1f6", "0x3acf887420887148222aab1d25d4d4893794e505ef276cc4cb6a48fffc6cb381", "0x96129f905589b2a95c26276aa7e8708a12381ddec50485d6684c4abf9a5a1d00" }; List <TransactionLog> logsFromRepo = new List <TransactionLog>(); foreach (var txHash in expectedTransactionHashes) { logsFromRepo.AddRange(await repository.GetManyAsync(txHash)); } Assert.Equal(16, logsFromRepo.Count); } finally { // delete any data from Azure await storageCloudSetup.GetCountersTable().DeleteIfExistsAsync(); await tableStorageFactory.DeleteTablesAsync(); } }
public Contract(EthApiService eth, string abi, string contractAddress) { Eth = eth; ContractABI = new ABIDeserialiser().DeserialiseContract(abi); Address = contractAddress; }
public DecodingService() { _abiDeserializer = new ABIDeserialiser(); _eventTopicDecoder = new EventTopicDecoder(); _functionCallDecoder = new FunctionCallDecoder(); }
public DeployContractTransactionBuilder() { _constructorCallEncoder = new ConstructorCallEncoder(); _abiDeserialiser = new ABIDeserialiser(); }