SpankChain: onchain txn handling
type TxnMeta = {
  reason: string // "collateralization", "withdrawal", etc
}

function callContractMethod(
  fromAddress: string,
  contractName: string, // "ChannelManager" - ABI + address will be looked up with DI
  method: string,
  args: { name: value, ... },
  value: string,
  meta: TxnMeta,
) {
  let contract = lookupContractAbiAndAddress(contractName)
  let argsArray = contract.convertNamedArgumentsToArray(args)
  let txnData = contract.methods[method](...argsArray)
  return sendTransaction({
    fromAddress,
    toAddress: contract.address,
    data: txnData,
    value,
    meta: {
      ...meta,
      contract: contractName,
      method,
      args,
    },
  })  
}

type TxnRequest {
  logicalId?: string,
  fromAddress: string,
  toAddress: string,
  data: string,
  value: string,
  meta: TxnMeta,
}

class TransactionMonitoringService {
  pollFinished = new Promise()
  
  function sendTransaction(db: DBengine, txnRequest: TxnRequest) {
    txnRequest.logicalId = txnRequest.logicalId || db.queryOne(`
      select nextval onchain_transactions_raw_logical_id_seq
    `)
    let nonce = Max(
      web3.getTransactionCount(txnRequest.fromAddress),
      db.execute(SQL,`
        select max(nonce) + 1