コード例 #1
0
        /// <summary>
        /// https://github.com/bitcoin-sv-specs/brfc-misc/tree/master/feespec
        /// </summary>
        /// <returns></returns>
        public async Task <FeeQuote> GetFeeQuote()
        {
            var feeQuote = _lastFeeQuote;

            if (feeQuote?.ExpiryTime > DateTime.UtcNow)
            {
                return(feeQuote);
            }

            var url = $"{_baseUrl}/mapi/feeQuote";

            var json = await _httpClient.GetStringAsync(url);

            var e = JsonConvert.DeserializeObject <Envelope>(json);

            var verified = e.VerifySignature(ref _pubKey);

            feeQuote = JsonConvert.DeserializeObject <FeeQuote>(e.Payload);

            if (!verified && feeQuote.MinerId != null)
            {
                throw new InvalidOperationException("Miner did not verify.");
            }

            _lastFeeQuote = feeQuote;

            return(feeQuote);
        }
コード例 #2
0
        public async Task <ActionResult <PolicyQuoteViewModelGet> > GetPolicyQuote()
        {
            if (!IdentityProviderStore.GetUserAndIssuer(User, Request.Headers, out var identity))
            {
                return(Unauthorized("Incorrectly formatted token"));
            }

            logger.LogInformation($"Get PolicyQuote for user { ((identity == null) ? "/" : identity.ToString())} ...");
            FeeQuote feeQuote = feeQuoteRepository.GetCurrentFeeQuoteByIdentity(identity);


            if (feeQuote == null)
            {
                logger.LogInformation($"There are no active policyQuotes.");

                return(NotFound());
            }

            var policyQuoteViewModelGet = new PolicyQuoteViewModelGet(feeQuote, callbackIPAddressesArray)
            {
                Timestamp = clock.UtcNow(),
            };

            return(await FillFeeQuoteViewModelWithInfo(policyQuoteViewModelGet));
        }
コード例 #3
0
        public FeeQuoteViewModelGet(FeeQuote feeQuote)
        {
            ApiVersion = Const.MERCHANT_API_VERSION;
            Fees       = (from fee in feeQuote.Fees
                          select new FeeViewModelGet(fee)).ToArray();

            // Other fields are initialized from BlockCHainInfo and MinerId
        }
コード例 #4
0
 public FeeQuoteViewModelCreate(FeeQuote feeQuote)
 {
     Id               = feeQuote.Id;
     CreatedAt        = feeQuote.CreatedAt;
     ValidFrom        = feeQuote.ValidFrom;
     Identity         = feeQuote.Identity;
     IdentityProvider = feeQuote.IdentityProvider;
     Fees             = (from fee in feeQuote.Fees
                         select new FeeViewModelCreate(fee)).ToArray();
 }
コード例 #5
0
 public FeeQuoteConfigViewModelGet(FeeQuote feeQuote)
 {
     Id               = feeQuote.Id;
     CreatedAt        = feeQuote.CreatedAt;
     Identity         = feeQuote.Identity;
     IdentityProvider = feeQuote.IdentityProvider;
     ValidFrom        = feeQuote.ValidFrom;
     Policies         = feeQuote.PoliciesDict;
     Fees             = (from fee in feeQuote.Fees
                         select new FeeViewModelGet(fee)).ToArray();
 }
コード例 #6
0
 public FeeQuoteViewModelGet(FeeQuote feeQuote, string[] urls)
 {
     ApiVersion = Const.MERCHANT_API_VERSION;
     Fees       = (from fee in feeQuote.Fees
                   select new FeeViewModelGet(fee)).ToArray();
     if (urls != null)
     {
         Callbacks = (from url in urls
                      select new CallbackViewModelGet(url)).ToArray();
     }
     // Other fields are initialized from BlockChainInfo and MinerId
 }
コード例 #7
0
        public ActionResult <FeeQuoteConfigViewModelGet> GetFeeQuoteById(long id)
        {
            logger.LogInformation($"Get FeeQuote {id}");

            FeeQuote feeQuote = feeQuoteRepository.GetFeeQuoteById(id);

            if (feeQuote == null)
            {
                return(NotFound());
            }

            var feeQuoteViewModelGet = new FeeQuoteConfigViewModelGet(feeQuote);

            return(Ok(feeQuoteViewModelGet));
        }
コード例 #8
0
 protected void InsertFeeQuote(UserAndIssuer userAndIssuer = null)
 {
     using (MockedClock.NowIs(DateTime.UtcNow.AddMinutes(-1)))
     {
         var feeQuote = new FeeQuote
         {
             Id               = 1,
             CreatedAt        = MockedClock.UtcNow,
             ValidFrom        = MockedClock.UtcNow,
             Identity         = userAndIssuer?.Identity,
             IdentityProvider = userAndIssuer?.IdentityProvider,
             Fees             = new[] {
                 new Fee {
                     FeeType   = Const.FeeType.Standard,
                     MiningFee = new FeeAmount {
                         Satoshis      = 500,
                         Bytes         = 1000,
                         FeeAmountType = Const.AmountType.MiningFee
                     },
                     RelayFee = new FeeAmount {
                         Satoshis      = 250,
                         Bytes         = 1000,
                         FeeAmountType = Const.AmountType.RelayFee
                     },
                 },
                 new Fee {
                     FeeType   = Const.FeeType.Data,
                     MiningFee = new FeeAmount {
                         Satoshis      = 500,
                         Bytes         = 1000,
                         FeeAmountType = Const.AmountType.MiningFee
                     },
                     RelayFee = new FeeAmount {
                         Satoshis      = 250,
                         Bytes         = 1000,
                         FeeAmountType = Const.AmountType.RelayFee
                     },
                 },
             }
         };
         if (FeeQuoteRepository.InsertFeeQuoteAsync(feeQuote).Result == null)
         {
             throw new Exception("Can not insert test fee quote");
         }
     }
 }
コード例 #9
0
        public async Task <ActionResult <FeeQuoteViewModelGet> > GetFeeQuote()
        {
            if (!IdentityProviderStore.GetUserAndIssuer(User, Request.Headers, out var identity))
            {
                return(Unauthorized("Incorrectly formatted token"));
            }

            logger.LogInformation($"Get FeeQuote for user { ((identity == null) ? "/" : identity.ToString() )} ...");
            FeeQuote feeQuote = feeQuoteRepository.GetCurrentFeeQuoteByIdentity(identity);


            if (feeQuote == null)
            {
                logger.LogInformation($"There are no active feeQuotes.");

                return(NotFound());
            }

            var feeQuoteViewModelGet = new FeeQuoteViewModelGet(feeQuote)
            {
                Timestamp = clock.UtcNow(),
            };

            feeQuoteViewModelGet.ExpiryTime = feeQuoteViewModelGet.Timestamp.Add(TimeSpan.FromMinutes(quoteExpiryMinutes));

            var info = blockChainInfo.GetInfo();

            feeQuoteViewModelGet.MinerId = await minerId.GetCurrentMinerIdAsync();

            feeQuoteViewModelGet.CurrentHighestBlockHash   = info.BestBlockHash;
            feeQuoteViewModelGet.CurrentHighestBlockHeight = info.BestBlockHeight;

            logger.LogInformation($"Returning feeQuote with ExpiryTime: {feeQuoteViewModelGet.ExpiryTime}.");

            return(await SignIfRequiredAsync(feeQuoteViewModelGet, feeQuoteViewModelGet.MinerId));
        }
コード例 #10
0
 public Task <FeeQuote> InsertFeeQuoteAsync(FeeQuote feeQuote)
 {
     throw new NotImplementedException();
 }
コード例 #11
0
ファイル: Mapi.cs プロジェクト: prayer0/merchantapi-reference
        /// <summary>
        /// Check if specified transaction meets fee policy
        /// </summary>
        /// <param name="txBytesLength">Transactions</param>
        /// <param name="sumPrevOuputs">result of CollectPreviousOutputs. If previous outputs are not found there, the node is consulted</param>
        /// <returns></returns>
        public (bool okToMine, bool okToRely) CheckFees(Transaction transaction, long txBytesLength, Money sumPrevOuputs, FeeQuote feeQuote)
        {
            // This could leave some og the bytes unparsed. In this case we would charge for bytes at the ned of
            // the stream that will not be published to the blockchain, but this is sender's problem.

            Money sumNewOuputs = Money.Zero;
            long  dataBytes    = 0;

            foreach (var output in transaction.Outputs)
            {
                sumNewOuputs += output.Value;
                if (output.Value < 0L)
                {
                    throw new ExceptionWithSafeErrorMessage("Negative inputs are not allowed");
                }
                if (IsDataOuput(output))
                {
                    dataBytes += output.ScriptPubKey.Length;
                }
            }


            long actualFee   = (sumPrevOuputs - sumNewOuputs).Satoshi;
            long normalBytes = txBytesLength - dataBytes;

            long feesRequiredMining = 0;
            long feesRequiredRelay  = 0;

            foreach (var fee in feeQuote.Fees)
            {
                if (fee.FeeType == "standard")
                {
                    feesRequiredMining += (normalBytes * fee.MiningFee.Satoshis) / fee.MiningFee.Bytes;
                    feesRequiredRelay  += (normalBytes * fee.RelayFee.Satoshis) / fee.RelayFee.Bytes;
                }
                else if (fee.FeeType == "data")
                {
                    feesRequiredMining += (dataBytes * fee.MiningFee.Satoshis) / fee.MiningFee.Bytes;
                    feesRequiredRelay  += (dataBytes * fee.RelayFee.Satoshis) / fee.RelayFee.Bytes;
                }
            }

            bool okToMine  = actualFee >= feesRequiredMining;
            bool okToRelay = actualFee >= feesRequiredRelay;

            return(okToMine, okToRelay);
        }
コード例 #12
0
 public PolicyQuoteViewModelGet(FeeQuote feeQuote, string[] urls) : base(feeQuote, urls)
 {
     Policies = feeQuote.PoliciesDict;
     // Other fields are initialized from BlockChainInfo and MinerId
 }