Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const axios = require('axios');
- const bsv = require('bsv');
- var fs = require('fs');
- var path = require('path');
- let BN = bsv.crypto.BN
- __dirname = path.resolve();
- function int2SM(num) {
- let n = BN.fromNumber(num)
- let m = n.toSM({ endian: 'little'} )
- return m.toString('hex')
- }
- (async() => {
- const NETWORK = 'test'
- const API_PREFIX = 'https://api.whatsonchain.com/v1/bsv/' + NETWORK
- const MIN_FEE = 546
- const LOCK_AMOUNT = 100000
- const UNLOCK_AMOUNT = LOCK_AMOUNT - 10000
- const FLAGS = bsv.Script.Interpreter.SCRIPT_VERIFY_MINIMALDATA | bsv.Script.Interpreter.SCRIPT_ENABLE_SIGHASH_FORKID | bsv.Script.Interpreter.SCRIPT_ENABLE_MAGNETIC_OPCODES | bsv.Script.Interpreter.SCRIPT_ENABLE_MONOLITH_OPCODES
- const SIGHASH_TYPE = bsv.crypto.Signature.SIGHASH_ALL | bsv.crypto.Signature.SIGHASH_FORKID
- // mainnet
- // const key = "L1HBjGiu9W5tsu7axNKRY1cz4xdLuwEnAC7u3b6n2Ex98nNh6UvK"
- // testnet
- const key = 'cU2eUM62Hkur8sQVv7z1VtkXHHTA1YSGqxjAGYgbDPQaYcg5NXKd'
- // const key = 'cPkteUUh4eG1mjkhphV1MZWm7JmYZuK4j8LaDpPwo3mxcZW49ibj'
- // const key = 'cTzbQjXykayjM7rkERDeyf9h6V9DjsHqv7twhtU78EkqksQ95LJD'
- const privateKey = new bsv.PrivateKey(key);
- const ADDR = privateKey.toAddress();
- // console.log(address.toString()) //'mpRPo9bMQ1HaZetSL7EfaDuzfdLyJ3PVoy' 'mg1Rwf7NTTbgRUYAFiqJk1ryaKx74Y7zDf' 'myfKHweiqRe4z1KRXBEkud3FteCQn23wEr'
- const scriptP2PKH = bsv.Script.buildPublicKeyHashOut(ADDR).toHex();
- // console.log(script) // 76a91461abec89cd14603c8c7d45f679e93ac0beea866288ac
- const fetchUtxos = async (address) => {
- let { data: utxos } = await axios.get(`${API_PREFIX}/address/${ADDR}/unspent`)
- utxos = utxos.map(utxo => ({
- txId: utxo.tx_hash,
- outputIndex: utxo.tx_pos,
- satoshis: utxo.value,
- script: scriptP2PKH
- }))
- return utxos
- }
- // lock fund in a script
- const buildScriptLockTx = (utxos, scriptPubKey) => {
- let tx = new bsv.Transaction().from(utxos)
- tx.addOutput(new bsv.Transaction.Output({
- script: scriptPubKey,
- satoshis: LOCK_AMOUNT
- }))
- tx.addOutput(new bsv.Transaction.Output({
- script: new bsv.Script().add(bsv.Opcode.OP_FALSE).add(bsv.Script.buildDataOut(['sCrypt: the UTXO above (vout[0]) cannot be spent before CoinGeek London 2020'])),
- satoshis: 546
- }))
- tx.change(ADDR)
- if (tx.getFee() < MIN_FEE) {
- tx.fee(MIN_FEE)
- }
- return tx.sign(privateKey)
- }
- // unlock fund from a script
- const buildScriptUnlockTx = (prevTxId, scriptPubKey) => {
- tx = new bsv.Transaction().addInput(new bsv.Transaction.Input({
- prevTxId: prevTxId,
- outputIndex: 0,
- script: new bsv.Script(), // placeholder
- }), scriptPubKey, LOCK_AMOUNT)
- tx.addOutput(new bsv.Transaction.Output({
- script: scriptPubKey,
- satoshis: UNLOCK_AMOUNT
- }))
- tx.nLockTime = 1582156800
- // no need to sign since scriptSig is already set
- return tx
- }
- const sendTx = async (txhex) => {
- const { data: txid } = await axios.post(`${API_PREFIX}/tx/raw`, {
- txhex: txhex
- })
- return txid
- }
- try {
- const scriptPubKeyStr = fs.readFileSync(path.join(__dirname, 'cltv_asm.json'), { encoding: 'utf8' })
- const scriptPubKey = bsv.Script.fromASM(scriptPubKeyStr)
- // step 1: fetch utxos
- const utxos = await fetchUtxos(ADDR)
- // console.log('utxos: ', utxos)
- // step 2: build the locking tx and sign it
- const lockingTx = buildScriptLockTx(utxos, scriptPubKey)
- // step 3: serialize and broadcast the locking tx
- const lockingTxid = await sendTx(lockingTx.serialize())
- console.log('locking tx id: ', lockingTxid)
- // step 4: build the unlocking tx
- const unlockingTx = await buildScriptUnlockTx(lockingTxid, scriptPubKey)
- const INPUT_IDX = 0
- const preimage = bsv.Transaction.sighash.sighashPreimage(unlockingTx, SIGHASH_TYPE, INPUT_IDX, scriptPubKey, new bsv.crypto.BN(LOCK_AMOUNT), FLAGS)
- const preimageASM = preimage.toString('hex')
- const scriptSigStr = preimageASM
- const scriptSig = bsv.Script.fromASM(scriptSigStr)
- unlockingTx.inputs[INPUT_IDX].setScript(scriptSig)
- // step 5: serialized and send it
- const unlockingTxid = await sendTx(unlockingTx.serialize())
- console.log('unlocking tx id: ', unlockingTxid)
- } catch (error) {
- // Error
- if (error.response) {
- // The request was made and the server responded with a status code
- // that falls out of the range of 2xx
- console.log('Failed - StatusCodeError: ' + error.response.status + ' - "' + error.response.data + '"')
- // console.log(error.response.headers);
- } else if (error.request) {
- // The request was made but no response was received
- // `error.request` is an instance of XMLHttpRequest in the
- // browser and an instance of
- // http.ClientRequest in node.js
- console.log(error.request);
- } else {
- // Something happened in setting up the request that triggered an Error
- console.log('Error', error.message);
- }
- console.log(error.config);
- }
- })()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement