# install.packages("rbch")
# install.packages("data.table")
# install.packages("future.apply")
# install.packages("stringr")

library(rbch)
library(data.table)
library(future.apply)
library(stringr)


bitcoin.conf.file <- ""
# Input filepath for your bitcoin.conf file

data.dir <- ""
# Input data directory here, with trailing "/"

bch.config <- rbch::conrpc(bitcoin.conf.file)


con <- DBI::dbConnect(RSQLite::SQLite(), paste0(data.dir, "tx-graph-node-indices.db"))


# first.fusion.height <- 646085

# current.block.height <- rbch::getblockchaininfo(bch.config)@result$blocks

tx.graph.files <- list.files(data.dir)
tx.graph.files <- tx.graph.files[grepl("^tx_graph.+rds$", tx.graph.files)]

first.fusion.height <- min(as.numeric(unlist(stringr::str_extract_all(tx.graph.files, "[0-9]+"))))
current.block.height <- max(as.numeric(unlist(stringr::str_extract_all(tx.graph.files, "[0-9]+"))))


heights.to.process <- first.fusion.height:current.block.height
heights.to.process <- split(heights.to.process, 
  cut(heights.to.process, ceiling(length(heights.to.process)/50)))

future::plan(future::multiprocess())

coinbases <- list()

for (height.set in heights.to.process) {
  
  extracted.txs <- future.apply::future_lapply(height.set, function(iter.block.height) {
    
    if (iter.block.height %% 1000 == 0) {
      cat(iter.block.height, base::date(), "\n")
    }
    
    block.hash <- rbch::getblockhash(bch.config, iter.block.height)
    block.data <- rbch::getblock(bch.config, blockhash = block.hash@result, verbosity = "l2")
    # Argument verbose = 2 gives full transaction data
    # For some reason it doesn't give the fee: 
    # https://docs.bitcoincashnode.org/doc/json-rpc/getrawtransaction.html
    
    raw.txs.ls <- block.data@result$tx
    
    coinbase.tx <- raw.txs.ls[[1]]
    
    value <- vector("numeric", length(coinbase.tx$vout) )
      
    for (j in seq_along(coinbase.tx$vout)) { 
      value[j] <- coinbase.tx$vout[[j]]$value
    }
    
    outgoing <- data.table(txid = coinbase.tx$txid, 
      position = seq_along(coinbase.tx$vout), value = value, stringsAsFactors = FALSE)
    
    list(outgoing)
    
  })
  
  
  print(object.size(extracted.txs), units = "Mb")
  
  extracted.txs <- unlist(extracted.txs, recursive = FALSE)
  
  outgoing <- data.table::rbindlist(extracted.txs)
  
  coinbases[[length(coinbases) + 1]] <- outgoing
  
  rm(extracted.txs)
  rm(outgoing)
  
}


coinbases <- data.table::rbindlist(coinbases)

nrow(coinbases)


coinbases$txid_position <- paste0(coinbases$txid, "-", 
  formatC(coinbases$position, width = 4, format = "f", flag = "0", digits = 0))


DBI::dbWriteTable(con, "coinbases", coinbases, overwrite = TRUE)


DBI::dbWriteTable(con, "coinbases_intermediate_1", 
  data.frame(txid_position = character(0), stringsAsFactors = FALSE),
  overwrite = TRUE)


base::date()
DBI::dbExecute(con, "INSERT INTO coinbases_intermediate_1 SELECT 
  txid_position FROM
  coinbases EXCEPT 
  SELECT origin FROM edgelist")
base::date()


unspent.coinbases <- DBI::dbGetQuery(con, 
  'SELECT * FROM coinbases_intermediate_1')

unspent.coinbases <- merge(unspent.coinbases, coinbases)


saveRDS(unspent.coinbases, 
  file = paste0(data.dir, "unspent_coinbases.rds"), 
  compress = FALSE)