ethereumjs-tx is a library with this example:
npm install ethereumjs-tx
const Tx = require('ethereumjs-tx').Transaction
var privateKey = new Buffer('e331b6d69882b4cb4ea581d88e0b604039a3de5967688d3dcffdd2270c0fd109', 'hex')
var rawTx = {
nonce: '0x00',
gasPrice: '0x09184e72a000',
gasLimit: '0x2710',
to: '0x0000000000000000000000000000000000000000',
value: '0x00',
data: '0x7f7465737432000000000000000000000000000000000000000000000000000000600057'
}
var tx = new Tx(rawTx)
tx.sign(privateKey)
var serializedTx = tx.serialize()
console.log(serializedTx.toString('hex'))
To expand the other response, to provide offline transaction signing in Nethereum you can do the following:
First, you will need your private key, and sender address. You can retrieve the sender address from your private key using Nethereum.Core.Signing.Crypto.EthECKey.GetPublicAddress(privateKey);
if you only have the private key.
var privateKey = "0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7";
var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c";
Now using web3 first you will need to retrieve the total number of transactions of your sender address.
var web3 = new Web3();
var txCount = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(senderAddress);
The txCount will be used as the nonce to sign the transaction.
Now using web3 again, you can build an encoded transaction as following:
var encoded = web3.OfflineTransactionSigning.SignTransaction(privateKey, receiveAddress, 10, txCount.Value);
If you need to include the data and gas there are overloads for it.
You can verify an encoded transaction:
Assert.True(web3.OfflineTransactionSigning.VerifyTransaction(encoded));
Or get the sender address from an encoded transaction:
web3.OfflineTransactionSigning.GetSenderAddress(encoded);
To send the encoded transaction you will "SendRawTransaction"
var txId = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + encoded);
You can see this example on the unit test
Or a "real" implementation on the Game sample
Best Answer
Richard's answer pointed me in the right direction, but I had to remove some cruft to get it to do what I wanted. Here's some code that works (just replace the hardcoded values):