@scrow/tapscript
Version:
A development build of tapscript. Built for escrow.
142 lines (127 loc) • 3.43 kB
text/typescript
import { Buff } from '@cmdcode/buff'
import { hash256 } from '@cmdcode/crypto-tools/hash'
import { is_bytes } from '../util.js'
import { encode_tx } from './encode.js'
import { decode_tx } from './decode.js'
import { create_addr } from '../addr/parse.js'
import {
SizeData,
TxInput,
TxInTemplate,
TxPrevout,
TxBytes,
TxData,
TxTemplate,
TxOutTemplate,
TxOutput
} from '../../types/index.js'
import * as schema from '../../schema/index.js'
const DEFAULT_TX = {
version : 2,
vin : [],
vout : [],
locktime : 0
}
const DEFAULT_VIN = {
scriptSig : [],
sequence : 4294967293,
witness : []
}
const DEFAULT_VOUT = {
value : 0n,
scriptPubKey : []
}
export function parse_txid (
txdata : TxData | TxBytes,
segwit = false
) : string {
const json = parse_tx(txdata)
const data = encode_tx(json, segwit)
return hash256(data).reverse().hex
}
export function parse_txsize (
txdata : TxData | TxBytes
) : SizeData {
const json = parse_tx(txdata)
const bsize = encode_tx(json, true).length
const fsize = encode_tx(json, false).length
const weight = bsize * 3 + fsize
const remain = (weight % 4 > 0) ? 1 : 0
const vsize = Math.floor(weight / 4) + remain
return { size: fsize, bsize, vsize, weight }
}
export function create_vin (
vin : TxInTemplate | TxInput
) : TxInput {
const sequence = (typeof vin.sequence === 'string')
? Buff.hex(vin.sequence).num
: vin.sequence ?? DEFAULT_VIN.sequence
const prevout = (typeof vin.prevout !== 'undefined')
? create_vout(vin.prevout)
: vin.prevout
return { ...DEFAULT_VIN, ...vin, prevout, sequence }
}
export function create_prevout (
vin : TxInTemplate | TxInput
) : TxPrevout {
if (vin.prevout === undefined) {
throw new Error('Prevout is undefined!')
}
return create_vin(vin) as TxPrevout
}
export function create_vout (
vout : TxOutTemplate | TxOutput
) : TxOutput {
let value : bigint
if (typeof vout.value === 'number') {
value = BigInt(vout.value)
} else if (typeof vout.value === 'string') {
value = Buff.hex(vout.value).big
} else if (typeof vout.value === 'bigint') {
value = vout.value
} else {
value = 0n
}
return { ...DEFAULT_VOUT, ...vout, value }
}
export function create_tx (
template : TxTemplate
) : TxData {
const locktime = (typeof template.locktime === 'string')
? Buff.hex(template.locktime).num
: template.locktime ?? DEFAULT_TX.locktime
const tx = { ...DEFAULT_TX, ...template, locktime }
tx.vin = tx.vin.map(txin => create_vin(txin))
tx.vout = tx.vout.map(txout => create_vout(txout))
return schema.tx.txdata.parse(tx)
}
export function parse_prevout (
address : string,
txdata : TxData,
template ?: TxTemplate
) : TxPrevout | null {
const vout = txdata.vout.findIndex(txout => {
return address === create_addr(txout.scriptPubKey)
})
if (vout !== -1) {
const txid = parse_txid(txdata)
const prevout = txdata.vout[vout]
return create_prevout({ ...template, txid, vout, prevout })
} else {
return null
}
}
export function parse_tx (
txdata : TxBytes | TxData | TxTemplate
) : TxData {
return (is_bytes(txdata))
? decode_tx(txdata)
: create_tx(txdata)
}
export function buffer_tx (
txdata : TxBytes | TxData | TxTemplate
) : Buff {
return (is_bytes(txdata))
? Buff.bytes(txdata)
: encode_tx(parse_tx(txdata))
}