Exemple #1
0
        public static async Task <EthBlock> GetBlock(MySqlConnection connection, string blockHash, HexBigInteger blockNumber, Web3 cl, int blockchainID)
        {
            var block = await EthBlock.GetByNumber(connection, (UInt64)blockNumber.Value, blockchainID);

            if (block == null)
            {
                await _semaphore.WaitAsync();

                try
                {
                    block = await EthBlock.GetByNumber(connection, (UInt64)blockNumber.Value, blockchainID);

                    if (block == null)
                    {
                        var apiBlock = await cl.Eth.Blocks.GetBlockWithTransactionsHashesByNumber.SendRequestAsync(blockNumber);

                        block = new EthBlock
                        {
                            BlockHash    = blockHash,
                            BlockNumber  = (UInt64)blockNumber.Value,
                            Timestamp    = TimestampHelper.UnixTimeStampToDateTime((double)apiBlock.Timestamp.Value),
                            BlockchainID = blockchainID
                        };

                        EthBlock.Insert(connection, block);
                    }
                }
                finally
                {
                    _semaphore.Release();
                }
            }

            return(block);
        }
        public void Timestamp_ValidDate()
        {
            DateTime date = TimestampHelper.UnixTimeStampToDateTime(1625319664);

            var expected = new DateTime(2021, 07, 03, 14, 41, 04, DateTimeKind.Local);

            Assert.Equal(expected, date);
        }
        public async Task ExecuteEth(Source source)
        {
            Logger.WriteLine(source, "Syncing TRAC Market (ETH)");

            DateTime now = new DateTime(DateTime.UtcNow.Year, DateTime.UtcNow.Month, DateTime.UtcNow.Day,
                                        DateTime.UtcNow.Hour, 0, 0, DateTimeKind.Utc);
            DateTime latestTimestamp;

            using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
            {
                latestTimestamp =
                    connection.ExecuteScalar <DateTime?>(@"select max(ticker_eth.Timestamp) from ticker_eth") ??
                    connection.ExecuteScalar <DateTime>(@"SELECT Min(b.Timestamp) FROM ethblock b
                    where b.Timestamp >= COALESCE((select max(ticker_eth.Timestamp) from ticker_eth), (SELECT Min(b.Timestamp) FROM ethblock b))");
            }

            var startDate = new DateTime(2019, 12, 26, 17, 0, 0, DateTimeKind.Utc);

            if (latestTimestamp < startDate)
            {
                latestTimestamp = startDate;
            }

            if ((now - latestTimestamp).TotalHours < 1)
            {
                return;
            }

            //CoinpaprikaAPI.Client client = new CoinpaprikaAPI.Client();

            using (var wc = new WebClient())
            {
                await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString))
                {
                    await connection.OpenAsync();

                    for (DateTime date = latestTimestamp.Date; date.Date <= now; date = date.AddDays(1))
                    {
                        if (date > now)
                        {
                            break;
                        }


                        DataTable rawData = new DataTable();
                        rawData.Columns.Add("Timestamp", typeof(DateTime));
                        rawData.Columns.Add("Price", typeof(decimal));

                        RootObject obj = null;

                        for (int i = 0; i < 24; i++)
                        {
                            Int32 unixStartTimestamp =
                                (Int32)(date.AddHours(i).Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
                            Int32 unixEndTimestamp =
                                (Int32)(date.AddHours(i).AddHours(1).Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

                            await TimeConstraint;

                            var data = wc.DownloadString(
                                $"https://api.coingecko.com/api/v3/coins/origintrail/market_chart/range?vs_currency=eth&from={unixStartTimestamp}&to={unixEndTimestamp}");

                            obj = JsonConvert.DeserializeObject <RootObject>(data);


                            if (obj?.prices == null)
                            {
                                continue;
                            }

                            foreach (List <double> ticker in obj.prices)
                            {
                                DateTime tickerTime =
                                    TimestampHelper.UnixTimeStampToDateTime(Convert.ToDouble(ticker[0].ToString().Substring(0, 10)));

                                if (tickerTime <= latestTimestamp)
                                {
                                    continue;
                                }

                                var row = rawData.NewRow();


                                row["Timestamp"] = tickerTime;
                                row["Price"]     = ticker[1];
                                rawData.Rows.Add(row);

                                break;
                            }
                        }

                        if (rawData.Rows.Count == 0)
                        {
                            continue;
                        }


                        await using (MySqlTransaction tran =
                                         await connection.BeginTransactionAsync(global::System.Data.IsolationLevel.Serializable))
                        {
                            await using (MySqlCommand cmd = new MySqlCommand())
                            {
                                cmd.Connection  = connection;
                                cmd.Transaction = tran;
                                cmd.CommandText = "SELECT * FROM ticker_eth";
                                using (MySqlDataAdapter da = new MySqlDataAdapter(cmd))
                                {
                                    //da.UpdateBatchSize = 1000;
                                    using (MySqlCommandBuilder cb = new MySqlCommandBuilder(da))
                                    {
                                        da.Update(rawData);
                                        await tran.CommitAsync();

                                        if (obj != null && obj.prices != null && obj.prices.Any())
                                        {
                                            var max = obj.prices.Max(v =>
                                                                     TimestampHelper.UnixTimeStampToDateTime(
                                                                         Convert.ToDouble(v[0].ToString().Substring(0, 10))));
                                            if (max > latestTimestamp)
                                            {
                                                latestTimestamp = max;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
Exemple #4
0
        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
                });
            }
        }