public async Task <ActionResult> GetBlockByHash(string hash, int noTxList = 1)
        {
            if (!Validations.IsValidHash(hash))
            {
                return(BadRequest(hash + " is not a valid block hash"));
            }

            Utils.CheckIfChainIsFresh(chain_, config_.AcceptStaleRequests);

            string key = "block" + noTxList + hash;

            if (memoryCache_.TryGetValue(key, out JsonResult cachedBlockJson))
            {
                return(cachedBlockJson);
            }
            ;

            var binaryHash = Binary.HexStringToByteArray(hash);

            using (DisposableApiCallResult <GetBlockHeaderByHashTxSizeResult> getBlockResult = await chain_.FetchBlockHeaderByHashTxSizesAsync(binaryHash))
            {
                Utils.CheckBitprimApiErrorCode(getBlockResult.ErrorCode, "FetchBlockHeaderByHashTxSizesAsync(" + hash + ") failed, check error log");

                var getLastHeightResult = await chain_.FetchLastHeightAsync();

                Utils.CheckBitprimApiErrorCode(getLastHeightResult.ErrorCode, "FetchLastHeightAsync() failed, check error log");

                var blockHeight = getBlockResult.Result.Header.BlockHeight;

                ApiCallResult <GetBlockHashTimestampResult> getNextBlockResult = null;
                if (blockHeight != getLastHeightResult.Result)
                {
                    getNextBlockResult = await chain_.FetchBlockByHeightHashTimestampAsync(blockHeight + 1);

                    Utils.CheckBitprimApiErrorCode(getNextBlockResult.ErrorCode, "FetchBlockByHeightHashTimestampAsync(" + blockHeight + 1 + ") failed, check error log");
                }

                decimal  blockReward;
                PoolInfo poolInfo;
                using (DisposableApiCallResult <GetTxDataResult> coinbase = await chain_.FetchTransactionAsync(getBlockResult.Result.TransactionHashes[0], true))
                {
                    Utils.CheckBitprimApiErrorCode(coinbase.ErrorCode, "FetchTransactionAsync(" + getBlockResult.Result.TransactionHashes[0] + ") failed, check error log");
                    blockReward = Utils.SatoshisToCoinUnits(coinbase.Result.Tx.TotalOutputValue);
                    poolInfo    = poolsInfo_.GetPoolInfo(coinbase.Result.Tx);
                }

                JsonResult blockJson = Json(BlockToJSON
                                            (
                                                getBlockResult.Result.Header.BlockData, blockHeight, getBlockResult.Result.TransactionHashes,
                                                blockReward, getLastHeightResult.Result, getNextBlockResult?.Result.BlockHash,
                                                getBlockResult.Result.SerializedBlockSize, poolInfo, noTxList == 0)
                                            );

                memoryCache_.Set(key, blockJson, new MemoryCacheEntryOptions {
                    Size = Constants.Cache.BLOCK_CACHE_ENTRY_SIZE
                });
                return(blockJson);
            }
        }
        private async Task <TransactionSummary> TxToJSON(ITransaction tx, UInt64 blockHeight, bool confirmed,
                                                         bool returnLegacyAddresses, bool noAsm, bool noScriptSig,
                                                         bool noSpend)
        {
            UInt32 blockTimestamp = 0;
            string blockHash      = "";

            if (confirmed)
            {
                using (var getBlockHeaderResult = await chain_.FetchBlockHeaderByHeightAsync(blockHeight))
                {
                    Utils.CheckBitprimApiErrorCode(getBlockHeaderResult.ErrorCode, "FetchBlockHeaderByHeightAsync(" + blockHeight + ") failed, check error log");
                    IHeader blockHeader = getBlockHeaderResult.Result.BlockData;
                    blockTimestamp = blockHeader.Timestamp;
                    blockHash      = Binary.ByteArrayToHexString(blockHeader.Hash);
                }
            }
            ApiCallResult <UInt64> getLastHeightResult = await chain_.FetchLastHeightAsync();

            Utils.CheckBitprimApiErrorCode(getLastHeightResult.ErrorCode, "FetchLastHeightAsync failed, check error log");

            var txJson = new TransactionSummary();

            txJson.txid     = Binary.ByteArrayToHexString(tx.Hash);
            txJson.version  = tx.Version;
            txJson.locktime = tx.Locktime;
            txJson.vin      = await TxInputsToJSON(tx, returnLegacyAddresses, noAsm, noScriptSig);

            txJson.vout = await TxOutputsToJSON(tx, returnLegacyAddresses, noAsm, noSpend);

            txJson.confirmations = confirmed? getLastHeightResult.Result - blockHeight + 1 : 0;
            txJson.isCoinBase    = tx.IsCoinbase;
            txJson.valueOut      = Utils.SatoshisToCoinUnits(tx.TotalOutputValue);
            txJson.size          = tx.GetSerializedSize();
            UInt64 inputsTotal = await ManuallyCalculateInputsTotal(tx); //TODO Solve at native layer

            txJson.valueIn = Utils.SatoshisToCoinUnits(inputsTotal);
            if (confirmed)
            {
                txJson.blockhash   = blockHash;
                txJson.time        = blockTimestamp;
                txJson.blocktime   = blockTimestamp;
                txJson.blockheight = (Int64)blockHeight;
            }
            else
            {
                txJson.blockheight = -1;
                txJson.time        = (UInt32)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            }
            if (!tx.IsCoinbase)
            {
                txJson.fees = Utils.SatoshisToCoinUnits(inputsTotal - tx.TotalOutputValue); //TODO Solve at native layer
            }
            return(txJson);
        }
예제 #3
0
        private async Task <GetLastBlock> GetLastBlock()
        {
            if (!memoryCache_.TryGetValue(Constants.Cache.LAST_BLOCK_HEIGHT_CACHE_KEY, out ulong currentHeight))
            {
                var getLastHeightResult = await chain_.FetchLastHeightAsync();

                Utils.CheckBitprimApiErrorCode(getLastHeightResult.ErrorCode, "FetchLastHeightAsync() failed");
                currentHeight = getLastHeightResult.Result;

                memoryCache_.Set(Constants.Cache.LAST_BLOCK_HEIGHT_CACHE_KEY, currentHeight,
                                 new MemoryCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = Constants.Cache.LAST_BLOCK_HEIGHT_MAX_AGE,
                    Size = Constants.Cache.LAST_BLOCK_HEIGHT_ENTRY_SIZE
                });
            }

            if (!memoryCache_.TryGetValue(Constants.Cache.LAST_BLOCK_CACHE_KEY, out GetLastBlock ret))
            {
                using (var getBlockDataResult = await chain_.FetchBlockHeaderByHeightAsync(currentHeight))
                {
                    Utils.CheckBitprimApiErrorCode(getBlockDataResult.ErrorCode, "FetchBlockHeaderByHeightAsync(" + currentHeight + ") failed");

                    ret = new GetLastBlock
                    {
                        BlockHeight = getBlockDataResult.Result.BlockHeight
                        , Bits      = getBlockDataResult.Result.BlockData.Bits
                        , Hash      = getBlockDataResult.Result.BlockData.Hash
                    };

                    memoryCache_.Set(Constants.Cache.LAST_BLOCK_CACHE_KEY, ret,
                                     new MemoryCacheEntryOptions
                    {
                        AbsoluteExpirationRelativeToNow = Constants.Cache.LAST_BLOCK_MAX_AGE,
                        Size = Constants.Cache.LAST_BLOCK_ENTRY_SIZE
                    });
                }
            }

            return(ret);
        }
예제 #4
0
        private async Task <List <Utxo> > GetUtxo(string paymentAddress, bool returnLegacyAddresses)
        {
            Utils.CheckIfChainIsFresh(chain_, config_.AcceptStaleRequests);

            using (var address = new PaymentAddress(paymentAddress))
                using (var getAddressHistoryResult = await chain_.FetchHistoryAsync(address, UInt64.MaxValue, 0))
                {
                    Utils.CheckBitprimApiErrorCode(getAddressHistoryResult.ErrorCode, "FetchHistoryAsync(" + paymentAddress + ") failed, check error log.");

                    var history = getAddressHistoryResult.Result;

                    var utxo = new List <Utxo>();

                    var getLastHeightResult = await chain_.FetchLastHeightAsync();

                    Utils.CheckBitprimApiErrorCode(getLastHeightResult.ErrorCode, "FetchLastHeightAsync failed, check error log");

                    var topHeight = getLastHeightResult.Result;

                    foreach (IHistoryCompact compact in history)
                    {
                        if (compact.PointKind == PointKind.Output)
                        {
                            using (var outPoint = new OutputPoint(compact.Point.Hash, compact.Point.Index))
                            {
                                var getSpendResult = await chain_.FetchSpendAsync(outPoint);

                                if (getSpendResult.ErrorCode == ErrorCode.NotFound) //Unspent = it's an utxo
                                {
                                    //Get the tx to get the script
                                    using (var getTxResult = await chain_.FetchTransactionAsync(compact.Point.Hash, true))
                                    {
                                        Utils.CheckBitprimApiErrorCode(getTxResult.ErrorCode, "FetchTransactionAsync (" + Binary.ByteArrayToHexString(outPoint.Hash) + ") failed, check error log");
                                        utxo.Add(new Utxo(address, compact.Point, getTxResult.ErrorCode, getTxResult.Result.Tx, compact, topHeight, returnLegacyAddresses));
                                    }
                                }
                            }
                        }
                    }
                    utxo.AddRange(GetUnconfirmedUtxo(address));
                    return(utxo);
                }
        }
예제 #5
0
 public UInt64 GetCurrentBlockchainHeight()
 {
     return(chain_.FetchLastHeightAsync().Result.Result);
 }