public async Task <OfferData> ProposeOffer(Proposal proposal, PubKey bobPubKey) { var key = new Key(); _Repository.SaveKey(key); var initiator = GetChain(proposal.From.Chain); var taker = GetChain(proposal.To.Chain); var preimage = new Preimage(); _Repository.SavePreimage(preimage); var lockTimes = new[] { CalculateLockTime(proposal.From, TimeSpan.FromHours(2.0)), CalculateLockTime(proposal.To, TimeSpan.FromHours(1.0)) }; return(new OfferData() { Initiator = new OfferParty() { Asset = proposal.From, PubKey = key.PubKey }, Taker = new OfferParty() { Asset = proposal.To, PubKey = bobPubKey }, LockTime = await lockTimes[0].ConfigureAwait(false), CounterOfferLockTime = await lockTimes[1].ConfigureAwait(false), Hash = preimage.GetHash() }); }
internal void SavePreimage(Preimage preimage) { _Repo.UpdateOrInsert("1", preimage.GetHash().ToString(), preimage.Bytes, (o, n) => n); }
public async Task <bool> WaitOfferTakenAsync(OfferData offerData, CancellationToken cancellation = default(CancellationToken)) { var decodedTxById = new Dictionary <uint256, JObject>(); var initiator = GetChain(offerData.Initiator.Asset.Chain); var redeemHash = offerData.CreateRedeemScript().Hash; int offset = 0; int takeCount = 10; while (true) { cancellation.ThrowIfCancellationRequested(); var transactions = await initiator.RPCClient.SendCommandAsync(RPCOperations.listtransactions, "*", takeCount, offset, true).ConfigureAwait(false); offset += takeCount; //If we reach end of the list, start over if (transactions.Result == null || ((JArray)transactions.Result).Count() == 0) { offset = 0; await Task.Delay(1000, cancellation).ConfigureAwait(false); continue; } bool startOver = false; //Check if the preimage is present foreach (var tx in ((JArray)transactions.Result)) { int confirmation = 0; if (tx["confirmations"] != null) { confirmation = tx["confirmations"].Value <int>(); } //Old transaction, skip if (confirmation > 144) { startOver = true; continue; } //Coinbase we can't have the preimage var category = tx["category"]?.Value <string>(); if (category == "immature" || category == "generate") { continue; } var txId = new uint256(tx["txid"].Value <string>()); JObject txObj = null; if (!decodedTxById.TryGetValue(txId, out txObj)) { var getTransaction = await initiator.RPCClient.SendCommandAsync("gettransaction", txId.ToString(), true); var decodeRawTransaction = await initiator.RPCClient.SendCommandAsync("decoderawtransaction", getTransaction.Result["hex"]); txObj = (JObject)decodeRawTransaction.Result; decodedTxById.Add(txId, txObj); } foreach (var input in txObj["vin"]) { var scriptSig = input["scriptSig"]["asm"].Value <string>(); var sigParts = scriptSig.Split(' ').ToList(); // Add the hash in txin if segwit if (input["txinwitness"] is JArray scriptWitness) { sigParts.AddRange(scriptWitness.Select(c => c.Value <string>())); } foreach (var sigPart in sigParts) { if (!HexEncoder.IsWellFormed(sigPart)) { continue; } var preimage = new Preimage(Encoders.Hex.DecodeData(sigPart)); if (preimage.GetHash() == offerData.Hash) { _Repository.SavePreimage(preimage); return(true); } } } } //If we reach end of the list, start over if (startOver) { offset = 0; await Task.Delay(1000, cancellation).ConfigureAwait(false); continue; } } }