1
0

signSharedTx.ts 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. /* Import modules. */
  2. import BCHJS from '@psf/bch-js'
  3. import { Transaction } from 'bitcoinjs-lib'
  4. import { mnemonicToSeed } from '@nexajs/hdnode'
  5. import { encodeNullData } from '@nexajs/script'
  6. import { utf8ToBin } from '@nexajs/utils'
  7. const bchjs = new BCHJS()
  8. /**
  9. * Build Shared Transaction
  10. *
  11. * Combine all participating inputs and outputs into one (signed) transaction.
  12. */
  13. export default function (_sessionid, _mnemonic, _inputs, _outputs) {
  14. console.log('SIGN SHARED TX', _sessionid, _inputs, _outputs)
  15. /* Initialize locals. */
  16. let accountIdx
  17. let addressIdx
  18. let changeIdx
  19. let chidleNode
  20. let data
  21. let ecPair
  22. let ownedInputs
  23. let protocolId
  24. let msg
  25. let rawTx
  26. let redeemScript
  27. let script
  28. let wif
  29. /* Initialize transaction builde.r */
  30. const transactionBuilder = new bchjs.TransactionBuilder()
  31. /* Handle inputs. */
  32. _inputs.forEach(_input => {
  33. /* Add input. */
  34. transactionBuilder.addInput(_input.tx_hash, _input.tx_pos)
  35. })
  36. /* Set protocol ID. */
  37. protocolId = '1337'
  38. /* Set protocol message. */
  39. msg = 'testing...'
  40. script = [
  41. utf8ToBin(protocolId),
  42. utf8ToBin(msg),
  43. // utf8ToBin(_sessionid),
  44. ]
  45. // console.log('my SCRIPT', script)
  46. // console.log('encodeNullData', encodeNullData(script))
  47. // Compile the script array into a bitcoin-compliant hex encoded string.
  48. // const data = bchjs.Script.encode(script)
  49. data = Buffer.from(encodeNullData(script))
  50. // console.log('OP_RETURN (data)', data)
  51. // Add the OP_RETURN output.
  52. transactionBuilder.addOutput(data, 0)
  53. /* Handle outputs. */
  54. _outputs.forEach(_output => {
  55. /* Add output. */
  56. transactionBuilder.addOutput(_output.address, _output.value)
  57. })
  58. /* Convert mnemonic to seed. */
  59. const seed = mnemonicToSeed(_mnemonic)
  60. /* Conver to seed buffer. */
  61. // FIXME Migrate to TypedArrays.
  62. const seedBuffer = Buffer.from(seed, 'hex')
  63. /* Generate master node. */
  64. const masterNode = bchjs.HDNode.fromSeed(seedBuffer)
  65. /* Set account index. */
  66. accountIdx = 0
  67. /* Set change index. */
  68. changeIdx = 0
  69. /* Set address index. */
  70. addressIdx = 0
  71. /* Generate child node. */
  72. chidleNode = masterNode
  73. .derivePath(`m/44'/145'/${accountIdx}'/${changeIdx}/${addressIdx}`)
  74. /* Generate wallet import format (WIF). */
  75. wif = bchjs.HDNode.toWIF(chidleNode)
  76. // console.log('BCH WIF', wif)
  77. /* Generate elliptic pair. */
  78. ecPair = bchjs.ECPair.fromWIF(wif)
  79. // FIXME Identify our owned inputs.
  80. ownedInputs = [ 0, 1, 2 ]
  81. for (let i = 0; i < _inputs.length; i++) {
  82. /* Verify input ownership. */
  83. if (!ownedInputs.includes(i)) {
  84. continue
  85. }
  86. /* Sign (our own) input. */
  87. transactionBuilder.sign(
  88. i,
  89. ecPair,
  90. redeemScript,
  91. Transaction.SIGHASH_ALL,
  92. _inputs[i].value,
  93. )
  94. }
  95. /* Generate (incomplete) transaction. */
  96. const tx = transactionBuilder.transaction.buildIncomplete()
  97. // console.log('TRANSACTION', tx)
  98. /* Convert to (raw) hex. */
  99. rawTx = tx.toHex()
  100. /* Return raw (hex) transaction. */
  101. return rawTx
  102. }