/// <summary> /// Simple transaction that is locked for x amount of hours before being processed /// </summary> public static bool SimpleTimeLockContract() { //Create a client for our QBitNinja API calls var client = new QBitNinjaClient(_network); var contractorPrivateKey = (_contractorHdRoot.Derive(new KeyPath("m/44'/0'/0'/0/0"))).PrivateKey.GetWif(_network); var contractorSecret = new BitcoinSecret(contractorPrivateKey.ToString(), _network); var contracteeAddress = BitcoinAddress.Create("n4bEeKENL9rED2cG31TjSNzPs6T15TCq96", _network); //Calculate all payments and fees var contracteePaymentAmount = new Money(0.1m, MoneyUnit.BTC); var minerFee = new Money(0.00007m, MoneyUnit.BTC); int lockTimeMinutes = 5; // <-- Minutes to wait until transaction is allowed to process var lockTime = new LockTime(DateTimeOffset.UtcNow.AddMinutes(5)); Console.WriteLine("LockTime set to:" + lockTime.ToString()); //Collect the spendable coins from a previous transction GetTransactionResponse transactionResponse = client.GetTransaction(uint256.Parse("e4a06cac11b257908a908e90dda19b4b5e3d5a0f172d6b90ad8b0950878507be")).Result; List <ICoin> receivedCoins = transactionResponse.ReceivedCoins; OutPoint outPointToSpend = null; Console.WriteLine("------ Available Coins ------"); Console.WriteLine(); foreach (var coin in receivedCoins) { if (coin.TxOut.ScriptPubKey == contractorPrivateKey.ScriptPubKey) { outPointToSpend = coin.Outpoint; Money amount = (Money)coin.Amount; var paymentScript = coin.TxOut.ScriptPubKey; var address = paymentScript.GetDestinationAddress(_network); Console.WriteLine("Amount: " + amount.ToDecimal(MoneyUnit.BTC) + " | " + paymentScript + " | " + address); Console.WriteLine(); } } if (outPointToSpend == null) { Console.WriteLine("Transaction does not contain our ScriptPubKey!"); return(false); } Console.WriteLine("-----------------------------"); //calculate change amount (not actually used, TransactionBuilder will handle for us): var txInAmount = (Money)receivedCoins[(int)outPointToSpend.N].Amount; var changeAmount = txInAmount - contracteePaymentAmount - minerFee; #region Console Output (Payment Details) Console.WriteLine(); Console.WriteLine(); Console.WriteLine("------ Payment Details ------"); Console.WriteLine(); Console.WriteLine("Total available: " + txInAmount.ToString() + " btc"); Console.WriteLine(); Console.WriteLine("Total payments: " + contracteePaymentAmount.ToString() + " btc"); Console.WriteLine(); Console.WriteLine("Total fees: " + minerFee.ToString() + " btc"); Console.WriteLine(); Console.WriteLine("Change: " + changeAmount.ToString() + " btc"); Console.WriteLine(); Console.WriteLine("-----------------------------"); Console.WriteLine(""); Console.WriteLine("Press any key to create transaction..."); Console.ReadLine(); #endregion try { //Now we can build a transaction where we send a timelock payment to the contractor var txBuilder = new TransactionBuilder(); var tx = txBuilder .AddCoins(receivedCoins) .AddKeys(contractorSecret.PrivateKey) .Send(contracteeAddress.ScriptPubKey, contracteePaymentAmount) .SendFees(minerFee) .SetChange(contractorSecret.GetAddress()) //.SetLockTime(lockTime) .BuildTransaction(true); tx.LockTime = 500123; if (txBuilder.Verify(tx)) { Console.WriteLine(tx.ToString()); Console.WriteLine("Timelock contract created, signed and verified!"); Console.WriteLine(""); Console.WriteLine("Press any key to broadcast..."); Console.ReadLine(); //Console.WriteLine(); //Console.WriteLine(tx.ToString()); //<-- Print out entire transaction as JSON #region Broadcast transaction using NBitcoin with node connection /* * //Use Bitnodes to find a node to connect to: https://bitnodes.earn.com/ | https://bitnodes.earn.com/nodes/ * //For Testnet you may have to find a faucet provider that also provides node information. * * * var node = NBitcoin.Protocol.Node.Connect(_network, "52.10.6.141:18333"); //<-- ReadMe has Terminal commands for looking up available Testnet Nodes. All Testnodes use :18333 * node.VersionHandshake(); * * // var payload = NBitcoin.Protocol.Payload(tx); * * //inform the server * node.SendMessage(new InvPayload(tx)); * Thread.Sleep(1000); * * //send the transaction * node.SendMessage(new TxPayload(tx)); * Thread.Sleep(5000); * * node.Disconnect(); * * Console.WriteLine("Transaction ID: " + tx.GetHash().ToString()); * Console.WriteLine(); * */ #endregion #region Broadcast transaction using QbitServerClient //Broadcast using QBit server: BroadcastResponse broadcastResponse = client.Broadcast(tx).Result; Console.WriteLine("Transaction ID: " + tx.GetHash().ToString()); Console.WriteLine(); if (broadcastResponse.Success) { Console.WriteLine("Broadcast succeeded!"); } else { Console.WriteLine("Broadcast Error!"); Console.WriteLine(); Console.WriteLine(broadcastResponse.Error.Reason); } #endregion } else { Console.WriteLine("Timelock contract has some issues."); } } catch (Exception e) { Console.WriteLine(e.Message); } Console.WriteLine(); return(true); }
public void ToStringTest(LockTime first, string expected) { string actual = first.ToString(); Assert.Equal(expected, actual); }