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); }
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); }
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); } }
public UInt64 GetCurrentBlockchainHeight() { return(chain_.FetchLastHeightAsync().Result.Result); }