public static async Task CreateMissingIdentities( MySqlConnection connection, Web3 cl, int blockchainId, BlockchainType blockchain, BlockchainNetwork network) { var eth = new EthApiService(cl.Client); var allIdentitiesCreated = connection .Query <OTContract_Profile_IdentityCreated>(@"select * from OTContract_Profile_IdentityCreated IC WHERE IC.NewIdentity not in (SELECT OTIdentity.Identity FROM OTIdentity WHERE BlockchainID = @BlockchainID) AND IC.BlockchainID = @blockchainID", new { blockchainId = blockchainId }) .ToArray(); foreach (var identity in allIdentitiesCreated) { var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity.NewIdentity); var otVersionFunction = ercContract.GetFunction("otVersion"); var value = await otVersionFunction.CallAsync <BigInteger>(); await OTIdentity.Insert(connection, new OTIdentity { TransactionHash = identity.TransactionHash, Identity = identity.NewIdentity, Version = (int)value, BlockchainID = blockchainId }); } //This only happens due to missing blockchain events (only happened in December 2018) var profilesCreatedWithoutIdentities = connection.Query( @"select TransactionHash, Profile from otcontract_profile_profilecreated WHERE Profile not in (select otidentity.Identity from otidentity WHERE BlockchainID = @blockchainID) AND BlockchainID = @blockchainID", new { blockchainId = blockchainId }).ToArray(); foreach (var profilesCreatedWithoutIdentity in profilesCreatedWithoutIdentities) { string hash = profilesCreatedWithoutIdentity.TransactionHash; string identity = profilesCreatedWithoutIdentity.Profile; var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity); var otVersionFunction = ercContract.GetFunction("otVersion"); var value = await otVersionFunction.CallAsync <BigInteger>(); await OTIdentity.Insert(connection, new OTIdentity { TransactionHash = hash, Identity = identity, Version = (int)value, BlockchainID = blockchainId }); } }
public EthereumTransactionDao() { string url = System.Configuration.ConfigurationManager.AppSettings["ethUrl"]; _webNode = url == null ? new Web3() : new Web3(url); _webNode.TransactionManager.DefaultGasPrice = new BigInteger(0); Contract = _webNode.Eth.GetContract(AbiHelper.GetEcobitBlockchainAbi(), System.Configuration.ConfigurationManager.AppSettings["transactionManagerAddress"]); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); var cl = await GetWeb3(connection, blockchainID, blockchain); var eth = new EthApiService(cl.Client); foreach (var contract in await OTContract.GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.Litigation, blockchainID)) { if (contract.IsArchived && contract.LastSyncedTimestamp.HasValue && (DateTime.Now - contract.LastSyncedTimestamp.Value).TotalDays <= 5) { #if DEBUG Logger.WriteLine(source, " Skipping contract: " + contract.Address); #endif continue; } Logger.WriteLine(source, " Using contract: " + contract.Address); var holdingContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Litigation, blockchain, network), contract.Address); var litigationInitiatedEvent = holdingContract.GetEvent("LitigationInitiated"); var litigationAnsweredEvent = holdingContract.GetEvent("LitigationAnswered"); var litigationTimedOutEvent = holdingContract.GetEvent("LitigationTimedOut"); var litigationCompletedEvent = holdingContract.GetEvent("LitigationCompleted"); var replacementStartedEvent = holdingContract.GetEvent("ReplacementStarted"); ulong size = (ulong)10000; BlockBatcher batcher = BlockBatcher.Start(contract.SyncBlockNumber, (ulong)LatestBlockNumber.Value, size, async delegate(ulong start, ulong end) { await Sync(connection, litigationInitiatedEvent, litigationAnsweredEvent, litigationTimedOutEvent, litigationCompletedEvent, replacementStartedEvent, contract, source, start, end, blockchainID, cl); }); await batcher.Execute(); } } return(true); }
public EthereumTransactionDao(ILogger logger) { _logger = logger; var webNode = new Web3(System.Configuration.ConfigurationManager.AppSettings["ethUrl"]) { TransactionManager = { DefaultGasPrice = 0 } }; Contract = Duck.Cast <IContract>(webNode.Eth.GetContract(AbiHelper.GetTransactionManagerAbi(), System.Configuration.ConfigurationManager.AppSettings["contractAddress"])); }
private T CallTransactionFunction <T>(string address, string functionName) { dynamic transactionContract; if (TransactionContract == null) { transactionContract = _webNode.Eth.GetContract(AbiHelper.GetTransactionAbi(), address); } else { transactionContract = TransactionContract; } return(CallTransactionFunction <T>(functionName, transactionContract)); }
public async Task <string> GetLatestABIForContract([FromQuery] int blockchainID, [FromQuery] int contractType) { await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { var blockchainRow = await connection.QueryFirstAsync("SELECT * FROM blockchains where id = @id", new { id = blockchainID }); string blockchainName = blockchainRow.BlockchainName; string networkName = blockchainRow.NetworkName; BlockchainType blockchainEnum = Enum.Parse <BlockchainType>(blockchainName); BlockchainNetwork networkNameEnum = Enum.Parse <BlockchainNetwork>(networkName); return(AbiHelper.GetContractAbi((ContractTypeEnum)contractType, blockchainEnum, networkNameEnum)); } }
public void GetContractAbi(ContractTypeEnum type) { string abi = AbiHelper.GetContractAbi(type, BlockchainType.Ethereum, BlockchainNetwork.Mainnet); Assert.NotNull(abi); Assert.NotEmpty(abi); abi = AbiHelper.GetContractAbi(type, BlockchainType.Ethereum, BlockchainNetwork.Rinkeby); Assert.NotNull(abi); Assert.NotEmpty(abi); abi = AbiHelper.GetContractAbi(type, BlockchainType.xDai, BlockchainNetwork.Mainnet); Assert.NotNull(abi); Assert.NotEmpty(abi); }
private async Task ProcessJob(MySqlConnection connection, int blockchainID, OTIdentity[] identities, string address, BlockchainType blockchain, BlockchainNetwork network, Source source, uint id) { string abi = AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network); string nodeUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM blockchains WHERE id = @id", new { id = blockchainID }); var cl = new Web3(nodeUrl); var eth = new EthApiService(cl.Client); Int32 percentage = 0; int counter = 0; foreach (OTIdentity identity in identities) { counter++; try { int loopPercentage = (int)Math.Round((decimal)counter * 100 / identities.Count(), MidpointRounding.AwayFromZero); if (loopPercentage != percentage) { percentage = loopPercentage; await connection.ExecuteAsync(@"UPDATE findnodesbywalletjob SET Progress = @percentage WHERE ID = @id", new { id = id, percentage }); } var ercContract = new Contract(eth, abi, identity.Identity); Function keyHasPurposeFunction = ercContract.GetFunction("keyHasPurpose"); var abiEncode = new ABIEncode(); byte[] data = abiEncode.GetABIEncodedPacked(address.HexToByteArray()); byte[] bytes = CalculateHash(data); await TimeConstraint; bool hasPermission = await keyHasPurposeFunction.CallAsync <bool>(bytes, 1); if (hasPermission) { await connection.ExecuteAsync(@"INSERT INTO findnodesbywalletresult(JobID, Identity) VALUES(@jobID, @identity)", new { jobID = id, identity = identity.Identity }); } } catch (Exception ex) { throw; } } await connection.ExecuteAsync(@"UPDATE findnodesbywalletjob SET Progress = 100, EndDate = @endDate WHERE ID = @id", new { id = id, endDate = DateTime.UtcNow }); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); var cl = await GetWeb3(connection, blockchainID, blockchain); var profileStorageContractAddress = (await OTContract .GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.ProfileStorage, blockchainID)).SingleOrDefault(a => a.IsLatest); if (profileStorageContractAddress == null) { return(false); } var profileStorageContract = new Contract(new EthApiService(cl.Client), AbiHelper.GetContractAbi(ContractTypeEnum.ProfileStorage, blockchain, network), profileStorageContractAddress.Address); var profileFunction = profileStorageContract.GetFunction("profile"); var currentIdentities = await OTIdentity.GetAll(connection, blockchainID); Dictionary <string, decimal> paidOutBalances = (await connection .QueryAsync <PayoutGroupHolder>( @"SELECT Holder, SUM(Amount) Amount FROM OTContract_Holding_Paidout WHERE BlockchainID = @blockchainID GROUP BY Holder", new { blockchainID = blockchainID })) .ToDictionary(k => k.Holder, k => k.Amount); Dictionary <string, OfferGroupHolder> offerTotals = (await connection.QueryAsync <OfferGroupHolder>( @"select i.Identity, COUNT(o.OfferID) as OffersTotal, (SELECT count(so.OfferID) FROM otoffer_holders sh join otoffer so on so.OfferID = sh.OfferID AND so.BlockchainID = sh.BlockchainID WHERE sh.blockchainid = @blockchainID and sh.Holder = i.Identity AND so.CreatedTimestamp >= Date_Add(NOW(), INTERVAL -7 DAY)) as OffersLast7Days from otidentity i join otoffer_holders h on h.Holder = i.Identity AND h.BlockchainID = i.BlockchainID join otoffer o on o.OfferID = h.OfferID AND o.BlockchainID = h.BlockchainID WHERE i.blockchainid = @blockchainID GROUP BY i.Identity", new { blockchainID })).ToDictionary(k => k.Identity, k => k); // NodeManagementWallet[] managementWallets = (await connection.QueryAsync<NodeManagementWallet>( // @"SELECT I.Identity, PC.ManagementWallet as CreateWallet, IT.ManagementWallet TransferWallet FROM OTIdentity I //LEFT JOIN OTContract_Profile_ProfileCreated PC ON PC.Profile = I.Identity AND PC.BlockchainID = I.BlockchainID //LEFT JOIN OTContract_Profile_IdentityTransferred IT ON IT.NewIdentity = I.Identity AND IT.BlockchainID = I.BlockchainID //WHERE I.Version > 0 AND I.BlockchainID = @blockchainID", new // { // blockchainID // })).ToArray(); foreach (OTIdentity currentIdentity in currentIdentities) { bool updateProfile = true; DateTime?lastActivityDate = null; if (currentIdentity.Version != Constants.CurrentERCVersion) { if (currentIdentity.LastSyncedTimestamp.HasValue) { DateTime adjustedNowTime = DateTime.Now; if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalDays <= 14) { updateProfile = false; } } } else if (currentIdentity.LastSyncedTimestamp.HasValue) { var dates = (await connection.QueryAsync <DateTime?>(@" select MAX(Timestamp) from otcontract_profile_identitycreated r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.NewIdentity = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_identitytransferred r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.NewIdentity = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_profilecreated r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.Profile = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_tokensdeposited r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.Profile = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_tokensreleased r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.Profile = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_tokensreserved r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.Profile = @identity AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_tokenstransferred r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE (r.Sender = @identity OR r.Receiver = @identity) AND r.blockchainID = @blockchainID union select MAX(Timestamp) from otcontract_profile_tokenswithdrawn r join ethblock b on r.BlockNumber = b.BlockNumber AND r.BlockchainID = b.BlockchainID WHERE r.Profile = @identity AND r.blockchainID = @blockchainID union select MAX(b.Timestamp) from otoffer_holders h join otoffer o on o.offerid = h.offerid and o.BlockchainID = h.BlockchainID join ethblock b on b.blocknumber = o.finalizedblocknumber AND h.BlockchainID = b.BlockchainID where h.Holder = @identity AND h.blockchainID = @blockchainID union SELECT MAX(Timestamp) FROM otcontract_litigation_litigationcompleted lc WHERE lc.HolderIdentity = @identity AND lc.DHWasPenalized = 1 AND lc.blockchainID = @blockchainID union select MAX(b.Timestamp) from otcontract_holding_paidout p join ethblock b on b.blocknumber = p.blocknumber and b.BlockchainID = p.BlockchainID where p.holder = @identity AND p.blockchainID = @blockchainID union select MAX(b.Timestamp) from otcontract_holding_offerfinalized of join otcontract_holding_offercreated oc on oc.OfferId = of.OfferId and oc.BlockchainID = of.BlockchainID join OTIdentity i on i.NodeId = oc.DCNodeId and i.BlockchainID = oc.BlockchainID join ethblock b on of.BlockNumber = b.BlockNumber and b.BlockchainID = of.BlockchainID where i.Identity = @identity AND of.blockchainID = @blockchainID", new { identity = currentIdentity.Identity, blockchainID })).ToArray().Where(d => d.HasValue).Select(d => d.Value).ToArray(); var adjustedNowTime = DateTime.Now; if (dates.Any()) { lastActivityDate = dates.Max(); if (lastActivityDate.Value <= currentIdentity.LastSyncedTimestamp) { if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalHours <= 16) { updateProfile = false; } } } else { if ((adjustedNowTime - currentIdentity.LastSyncedTimestamp.Value).TotalHours <= 24) { updateProfile = false; } } } if (updateProfile || (currentIdentity.NodeId ?? "").Length > 40) { var output = await profileFunction.CallDeserializingToObjectAsync <ProfileFunctionOutput>( currentIdentity.Identity); var stake = Web3.Convert.FromWei(output.stake); var stakeReserved = Web3.Convert.FromWei(output.stakeReserved); var nodeId = HexHelper.ByteArrayToString(output.nodeId, false).Substring(0, 40); var withdrawalAmount = Web3.Convert.FromWei(output.withdrawalAmount); var withdrawalTimestamp = (UInt64)output.withdrawalTimestamp; var reputation = (UInt64)output.reputation; if (currentIdentity.Stake != stake || currentIdentity.StakeReserved != stakeReserved || currentIdentity.NodeId != nodeId || currentIdentity.WithdrawalAmount != withdrawalAmount || currentIdentity.WithdrawalPending != output.withdrawalPending || currentIdentity.WithdrawalTimestamp != withdrawalTimestamp || currentIdentity.Reputation != reputation) { currentIdentity.Stake = stake; currentIdentity.StakeReserved = stakeReserved; currentIdentity.NodeId = nodeId; currentIdentity.WithdrawalAmount = withdrawalAmount; currentIdentity.WithdrawalPending = output.withdrawalPending; currentIdentity.WithdrawalTimestamp = withdrawalTimestamp; currentIdentity.Reputation = reputation; currentIdentity.LastSyncedTimestamp = DateTime.Now; await OTIdentity.UpdateFromProfileFunction(connection, currentIdentity); } else { currentIdentity.LastSyncedTimestamp = DateTime.Now; await OTIdentity.UpdateLastSyncedTimestamp(connection, currentIdentity); } } if (!paidOutBalances.TryGetValue(currentIdentity.Identity, out var paidRow)) { paidRow = 0; } offerTotals.TryGetValue(currentIdentity.Identity, out var offerRow); if (currentIdentity.Paidout != paidRow || currentIdentity.TotalOffers != (offerRow?.OffersTotal ?? 0) || currentIdentity.OffersLast7Days != (offerRow?.OffersLast7Days ?? 0) || currentIdentity.ActiveOffers != 0 || (currentIdentity.LastActivityTimestamp != lastActivityDate && lastActivityDate.HasValue)) { currentIdentity.Paidout = paidRow; currentIdentity.TotalOffers = offerRow?.OffersTotal ?? 0; currentIdentity.OffersLast7Days = offerRow?.OffersLast7Days ?? 0; currentIdentity.ActiveOffers = 0; currentIdentity.LastActivityTimestamp = lastActivityDate; await OTIdentity.UpdateFromPaidoutAndApprovedCalculation(connection, currentIdentity); } } } return(true); }
public static async Task <BeforePayoutResult> CanTryPayout(string nodeID, string offerId, string holdingAddress, string holdingStorageAddress, string litigationStorageAddress, string identity, int?blockchainID, string selectedAddress) { if (nodeID == null || offerId == null || holdingAddress == null || holdingStorageAddress == null || litigationStorageAddress == null || identity == null || blockchainID == null || selectedAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "Missing data in request." }); } await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { var holdingStorageAddressModel = await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingStorageAddressByAddress, new { holdingStorageAddress = holdingStorageAddress, blockchainID }); holdingStorageAddress = holdingStorageAddressModel?.Address; if (holdingStorageAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this holding storage smart contract address for this blockchain id " + blockchainID }); } var blockchainRow = await connection.QueryFirstAsync("SELECT * FROM blockchains where id = @id", new { id = blockchainID }); string blockchainName = blockchainRow.BlockchainName; string networkName = blockchainRow.NetworkName; string explorerTransactionUrl = blockchainRow.TransactionUrl; BlockchainType blockchainEnum = Enum.Parse <BlockchainType>(blockchainName); BlockchainNetwork networkNameEnum = Enum.Parse <BlockchainNetwork>(networkName); string nodeUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM blockchains WHERE id = @id", new { id = blockchainID }); var cl = new Web3(nodeUrl); var eth = new EthApiService(cl.Client); var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchainEnum, networkNameEnum), identity); Function keyHasPurposeFunction = ercContract.GetFunction("keyHasPurpose"); var abiEncode = new ABIEncode(); byte[] test = abiEncode.GetABIEncodedPacked(selectedAddress.HexToByteArray()); byte[] bytes = CalculateHash(test); bool hasPermission = await keyHasPurposeFunction.CallAsync <bool>(bytes, 1) || await keyHasPurposeFunction.CallAsync <bool>(bytes, 2); if (!hasPermission) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The address you have selected in MetaMask (" + selectedAddress + ") does not have permission to payout on the identity " + identity + ". You need to pick either your management wallet or operational wallet." }); } var holdingStorageAbi = AbiHelper.GetContractAbi(ContractTypeEnum.HoldingStorage, blockchainEnum, networkNameEnum); holdingAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(ContractsSql.GetHoldingAddressByAddress, new { holdingAddress = holdingAddress, blockchainID }))?.Address; if (holdingAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this holding smart contract address for this blockchain id " + blockchainID }); } var offerIdArray = offerId.HexToByteArray(); var holdingStorageContract = new Contract(new EthApiService(cl.Client), holdingStorageAbi, holdingStorageAddress); var getHolderStakedAmountFunction = holdingStorageContract.GetFunction("getHolderStakedAmount"); var holderStakedAmount = await getHolderStakedAmountFunction.CallAsync <BigInteger>(offerIdArray, identity); var getHolderPaymentTimestampFunction = holdingStorageContract.GetFunction("getHolderPaymentTimestamp"); var holderPaymentTimestamp = await getHolderPaymentTimestampFunction.CallAsync <BigInteger>(offerIdArray, identity); var getOfferHoldingTimeInMinutesFunction = holdingStorageContract.GetFunction("getOfferHoldingTimeInMinutes"); var offerHoldingTimeInMinutes = await getOfferHoldingTimeInMinutesFunction.CallAsync <BigInteger>(offerIdArray); var getHolderPaidAmountFunction = holdingStorageContract.GetFunction("getHolderPaidAmount"); var holderPaidAmount = await getHolderPaidAmountFunction.CallAsync <BigInteger>(offerIdArray, identity); if (holderStakedAmount <= 0) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says this identity did not hold data for this job. The transaction will likely fail if you try to send this manually." }); } //long holdingTime = await connection.ExecuteScalarAsync<long>( // @"select HoldingTimeInMinutes from otoffer where OfferID = @offerID and blockchainID = @blockchainID", // new // { // offerId, // blockchainID // }); var latestBlockParam = BlockParameter.CreateLatest(); var block = await cl.Eth.Blocks.GetBlockWithTransactionsByNumber.SendRequestAsync(latestBlockParam); DateTime blockDate = TimestampHelper.UnixTimeStampToDateTime((double)block.Timestamp.Value); DateTime jobStartDate = await connection.ExecuteScalarAsync <DateTime>(@"SELECT Timestamp FROM otcontract_holding_offerfinalized where OfferID = @offerID and BlockchainID = @blockchainID", new { offerID = offerId, blockchainID }); DateTime jobEndDate = jobStartDate.AddMinutes((int)offerHoldingTimeInMinutes); if (blockDate > jobEndDate) { blockDate = jobEndDate; } BigInteger blockTimestamp = new BigInteger(TimestampHelper.DateTimeToUnixTimeStamp(blockDate)); var amountToTransfer = holderStakedAmount; amountToTransfer = amountToTransfer * (blockTimestamp - holderPaymentTimestamp); amountToTransfer = amountToTransfer / (offerHoldingTimeInMinutes * 60); decimal friendlyEstimatedPayout = Web3.Convert.FromWei(amountToTransfer); if (holderPaidAmount == holderStakedAmount) { var friendlyAmount = Web3.Convert.FromWei(holderPaidAmount); return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says you have been paid " + friendlyAmount + " TRAC for this job. The transaction will likely fail if you try to send this manually." }); } if (!String.IsNullOrWhiteSpace(litigationStorageAddress)) { litigationStorageAddress = (await connection.QueryFirstOrDefaultAsync <ContractAddress>(@"select Address from otcontract where Type = 9 AND Address = @litigationStorageAddress AND blockchainID = @blockchainID", new { litigationStorageAddress = litigationStorageAddress, blockchainID }))?.Address; if (litigationStorageAddress == null) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "OT Hub is not familiar with this litigation storage smart contract address for this blockchain id " + blockchainID }); } Contract storageContract = new Contract((EthApiService)cl.Eth, AbiHelper.GetContractAbi(ContractTypeEnum.LitigationStorage, blockchainEnum, networkNameEnum), litigationStorageAddress); Function getLitigationStatusFunction = storageContract.GetFunction("getLitigationStatus"); Function getLitigationTimestampFunction = storageContract.GetFunction("getLitigationTimestamp"); BigInteger litigationTimestampInt = await getLitigationTimestampFunction.CallAsync <BigInteger>(latestBlockParam, offerIdArray, identity); Function getOfferLitigationIntervalInMinutesFunction = holdingStorageContract.GetFunction("getOfferLitigationIntervalInMinutes"); BigInteger litgationInterval = await getOfferLitigationIntervalInMinutesFunction.CallAsync <BigInteger>(latestBlockParam, offerIdArray) * 60; var status = await getLitigationStatusFunction.CallAsync <UInt16>(latestBlockParam, offerIdArray, identity); if (status == 1) //initiated { if (litigationTimestampInt + (litgationInterval * 2) >= block.Timestamp.Value) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually." }); } } else if (status == 2) //answered { if (litigationTimestampInt + (litgationInterval) >= block.Timestamp.Value) { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Unanswered litigation in progress, cannot pay out'. The transaction will likely fail if you try to send this manually." }); } } else if (status == 0) //completed { //Do nothing as this is fine } else { return(new BeforePayoutResult { CanTryPayout = false, Header = "Stop!", Message = "The smart contract says 'Data holder is replaced or being replaced, cannot payout!'. The transaction will likely fail if you try to send this manually." }); } } return(new BeforePayoutResult { CanTryPayout = true, BlockchainExplorerUrlFormat = explorerTransactionUrl, EstimatedPayout = friendlyEstimatedPayout }); } }
private static async Task ProcessHoldingSmartContractEvent(int blockchainID, BlockchainType blockchainType, BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl) { var contract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Holding, blockchainType, blockchainNetwork), filterLog.Address); var offerCreatedEvent = contract.GetEvent("OfferCreated"); var offerFinalizedEvent = contract.GetEvent("OfferFinalized"); var offerTaskEvent = contract.GetEvent("OfferTask"); var paidOutEvent = contract.GetEvent("PaidOut"); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { try { if (offerCreatedEvent.IsLogForEvent(transaction)) { var events = offerCreatedEvent.DecodeAllEventsForEvent <Models.Program.OfferCreated>( new[] { filterLog }); foreach (EventLog <Models.Program.OfferCreated> eventLog in events) { await SyncHoldingContractTask.ProcessOfferCreated(connection, blockchainID, cl, filterLog.Address, eventLog); } await ProcessJobsTask.Execute(connection, blockchainID, blockchainType, blockchainNetwork); } if (offerFinalizedEvent.IsLogForEvent(transaction)) { var events = offerFinalizedEvent.DecodeAllEventsDefaultForEvent(new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncHoldingContractTask.ProcessOfferFinalised(connection, blockchainID, cl, filterLog.Address, eventLog); } await ProcessJobsTask.Execute(connection, blockchainID, blockchainType, blockchainNetwork); } if (paidOutEvent.IsLogForEvent(transaction)) { var events = paidOutEvent.DecodeAllEventsDefaultForEvent(new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncHoldingContractTask.ProcessPayout(connection, blockchainID, cl, filterLog.Address, eventLog); } } } catch (Exception ex) { Logger.WriteLine(Source.BlockchainSync, ex.ToString()); } } }
private static async Task ProcessProfileSmartContractEvent(int blockchainID, BlockchainType blockchainType, BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl) { var contract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Profile, blockchainType, blockchainNetwork), filterLog.Address); var identityCreatedEvent = contract.GetEvent("IdentityCreated"); var profileCreatedEvent = contract.GetEvent("ProfileCreated"); var tokensDepositedEvent = contract.GetEvent("TokensDeposited"); var tokensReleasedEvent = contract.GetEvent("TokensReleased"); var tokensWithdrawnEvent = contract.GetEvent("TokensWithdrawn"); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { try { if (identityCreatedEvent.IsLogForEvent(transaction)) { var events = identityCreatedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncProfileContractTask.ProcessIdentityCreated(connection, filterLog.Address, blockchainID, cl, eventLog, eth); } await SyncProfileContractTask.CreateMissingIdentities(connection, cl, blockchainID, blockchainType, blockchainNetwork); } if (profileCreatedEvent.IsLogForEvent(transaction)) { Function createProfileFunction = contract.GetFunction("createProfile"); var events = profileCreatedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncProfileContractTask.ProcessProfileCreated(connection, filterLog.Address, createProfileFunction, blockchainID, cl, eventLog, eth); } await SyncProfileContractTask.CreateMissingIdentities(connection, cl, blockchainID, blockchainType, blockchainNetwork); } if (tokensDepositedEvent.IsLogForEvent(transaction)) { var events = tokensDepositedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash)) { await SyncProfileContractTask.ProcessTokensDeposited(connection, filterLog.Address, blockchainID, cl, eventLog, eth); } } if (tokensReleasedEvent.IsLogForEvent(transaction)) { var events = tokensReleasedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash)) { await SyncProfileContractTask.ProcessTokensReleased(connection, filterLog.Address, blockchainID, cl, eventLog, eth); } } if (tokensWithdrawnEvent.IsLogForEvent(transaction)) { var events = tokensWithdrawnEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (var eventLog in events.GroupBy(t => t.Log.TransactionHash)) { await SyncProfileContractTask.ProcessTokensWithdrawn(connection, filterLog.Address, blockchainID, cl, eventLog, eth); } } } catch (Exception ex) { Logger.WriteLine(Source.BlockchainSync, ex.ToString()); } } }
private static async Task ProcessLitigationSmartContractEvent(int blockchainID, BlockchainType blockchainType, BlockchainNetwork blockchainNetwork, EthApiService eth, FilterLog filterLog, FilterLog transaction, Web3 cl) { var contract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Litigation, blockchainType, blockchainNetwork), filterLog.Address); var litigationInitiatedEvent = contract.GetEvent("LitigationInitiated"); var litigationAnsweredEvent = contract.GetEvent("LitigationAnswered"); var litigationTimedOutEvent = contract.GetEvent("LitigationTimedOut"); var litigationCompletedEvent = contract.GetEvent("LitigationCompleted"); var replacementStartedEvent = contract.GetEvent("ReplacementStarted"); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { try { if (litigationInitiatedEvent.IsLogForEvent(transaction)) { var events = litigationInitiatedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncLitigationContractTask.ProcessLitigationInitiated(connection, blockchainID, cl, eventLog, eth); } } if (litigationAnsweredEvent.IsLogForEvent(transaction)) { var events = litigationAnsweredEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncLitigationContractTask.ProcessLitigationAnswered(connection, blockchainID, cl, eventLog, eth); } } if (litigationTimedOutEvent.IsLogForEvent(transaction)) { var events = litigationTimedOutEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncLitigationContractTask.ProcessLitigationTimedOut(connection, blockchainID, cl, eventLog, eth); } } if (litigationCompletedEvent.IsLogForEvent(transaction)) { var events = litigationCompletedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncLitigationContractTask.ProcessLitigationCompleted(connection, blockchainID, cl, eventLog, eth); } } if (replacementStartedEvent.IsLogForEvent(transaction)) { var events = replacementStartedEvent.DecodeAllEventsDefaultForEvent( new[] { filterLog }); foreach (EventLog <List <ParameterOutput> > eventLog in events) { await SyncLitigationContractTask.ProcessLitigationCompleted(connection, blockchainID, cl, eventLog, eth); } } } catch (Exception ex) { Logger.WriteLine(Source.BlockchainSync, ex.ToString()); } } }
private async Task PopulateSmartContracts(MySqlConnection connection, string hubAddress, bool isLatest, int blockchainID, BlockchainType blockchain, BlockchainNetwork network) { var web3 = await GetWeb3(connection, blockchainID, blockchain); EthApiService eth = new EthApiService(web3.Client); var hubContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Hub, blockchain, network), hubAddress); HubAddress hubAddressModel = await GetHubAddressModel(connection, hubAddress, blockchainID, isLatest); if (blockchain == BlockchainType.Ethereum && network == BlockchainNetwork.Mainnet) { await PopulateOriginalETHContracts(connection, blockchainID, hubAddressModel.FromBlockNumber); } Event contractsChangedEvent = hubContract.GetEvent("ContractsChanged"); ulong diff = (ulong)LatestBlockNumber.Value - hubAddressModel.SyncBlockNumber; ulong size = (ulong)10000; beforeSync: if (diff > size) { ulong currentStart = hubAddressModel.SyncBlockNumber; ulong currentEnd = currentStart + size; if (currentEnd > LatestBlockNumber.Value) { currentEnd = (ulong)LatestBlockNumber.Value; } bool canRetry = true; while (currentStart == 0 || currentStart < LatestBlockNumber.Value) { start: try { await SyncContractsChanged(contractsChangedEvent, currentStart, currentEnd, hubContract, web3, connection, blockchainID); } catch (RpcResponseException ex) when(ex.Message.Contains("query returned more than")) { size = size / 2; Logger.WriteLine(Source.BlockchainSync, "Swapping to block sync size of " + size); goto beforeSync; } catch (RpcClientUnknownException ex) when(canRetry && ex.GetBaseException().Message.Contains("Gateway")) { canRetry = false; goto start; } currentStart = currentEnd; currentEnd = currentStart + size; if (currentEnd > LatestBlockNumber.Value) { currentEnd = (ulong)LatestBlockNumber.Value; } } } else { await SyncContractsChanged(contractsChangedEvent, hubAddressModel.SyncBlockNumber, (ulong)LatestBlockNumber.Value, hubContract, web3, connection, blockchainID); } await SyncLatestContractsOnHub(hubAddressModel.FromBlockNumber, hubContract, connection, blockchainID, isLatest); }
public void ThatTransactionManagerAbiIsParsedCorrectly() { string abi = AbiHelper.GetTransactionManagerAbi(); Assert.AreEqual(@"[]", abi); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); var cl = await GetWeb3(connection, blockchainID, blockchain); var eth = new EthApiService(cl.Client); foreach (var contract in await OTContract.GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.Profile, blockchainID)) { if (contract.IsArchived && contract.LastSyncedTimestamp.HasValue && (DateTime.Now - contract.LastSyncedTimestamp.Value).TotalDays <= 5) { #if DEBUG Logger.WriteLine(source, " Skipping contract: " + contract.Address); #endif continue; } Logger.WriteLine(source, " Using contract: " + contract.Address); string abi = AbiHelper.GetContractAbi(ContractTypeEnum.Profile, blockchain, network); var profileContract = new Contract(eth, abi, contract.Address); var profileCreatedEvent = profileContract.GetEvent("ProfileCreated"); var identityCreatedEvent = profileContract.GetEvent("IdentityCreated"); var identityTransferredEvent = profileContract.GetEvent("IdentityTransferred"); var tokensDepositedEvent = profileContract.GetEvent("TokensDeposited"); var tokensReleasedEvent = profileContract.GetEvent("TokensReleased"); var tokensWithdrawnEvent = profileContract.GetEvent("TokensWithdrawn"); var tokensTransferredEvent = profileContract.GetEvent("TokensTransferred"); var tokensReservedEvent = profileContract.GetEvent("TokensReserved"); Function createProfileFunction = profileContract.GetFunction("createProfile"); Function transferProfileFunction = profileContract.GetFunction("transferProfile"); ulong size = (ulong)10000; BlockBatcher batcher = BlockBatcher.Start(contract.SyncBlockNumber, (ulong)LatestBlockNumber.Value, size, async delegate(ulong start, ulong end) { await Sync(connection, profileCreatedEvent, identityCreatedEvent, identityTransferredEvent, tokensDepositedEvent, tokensReleasedEvent, tokensWithdrawnEvent, tokensTransferredEvent, tokensReservedEvent, contract, source, createProfileFunction, transferProfileFunction, start, end, blockchainID, cl); }); await batcher.Execute(); } await CreateMissingIdentities(connection, cl, blockchainID, blockchain, network); } return(true); }