bitcoin-atm

bitcoin atm for pyc inc.

git clone https://9o.is/git/bitcoin-atm.git

Wallet.scala

(2450B)


      1 package inc.pyc.chimera
      2 package minions
      3 
      4 import inc.pyc._
      5 import bitcoin._
      6 import service._
      7 import BitcoinJsonRPC._
      8 import akka.actor._
      9 import akka.pattern._
     10 import scala.concurrent.Future
     11 
     12 /**
     13  * Minion that has access to bitcoin wallet
     14  * @param service bitcoin wallet service
     15  */
     16 class WalletMinion(service: BitcoinService.Value)
     17   extends Actor 
     18   with ActorLogging 
     19   with Minion
     20   with MinionWorker
     21   with HttpMinion {
     22   
     23   import context.dispatcher
     24   
     25   def name: String = "Wallet_"+util.Random.nextInt
     26   def props: Props = BitcoinService.props(service)
     27   
     28   val tasks: Receive = {
     29     case GetBalance        => getBalance
     30     case qr: QrCode        => validateQr(qr)
     31     case tx: IncompleteTx  => sell(tx)
     32   }
     33   
     34   /**
     35    * Validates bitcoin address in the QR code.
     36    * @param code scanned QR code
     37    */
     38   def validateQr(code: QrCode) {
     39     val future = validateAddress(code.qr) map {
     40       validation =>
     41         if (!validation.isvalid) InvalidBitcoinAddress
     42         else BitcoinAddress(validation.address)
     43     }
     44     pipe (future) to sender
     45   }
     46   
     47   /**
     48    * Sells bitcoins to the user.
     49    */
     50   def sell(tx: IncompleteTx) = workout {
     51     worker =>
     52       // TODO sell bitcoins
     53       // listen for the confirmation from the network, 
     54       // reply when available
     55       log info "SELLING BITCOINS!"
     56       val txid = scala.util.Random.nextLong.toString
     57       sender ! CompleteTx(tx, txid)
     58   }
     59   
     60   /**
     61    * Gets the balance in the wallet.
     62    */
     63   def getBalance = workout {
     64     worker =>
     65       val future = ask(worker, GetBalance).mapTo[String] map {
     66         s => Balance(s.toDouble)
     67       }
     68       pipe (future) to sender
     69   }
     70 
     71   /**
     72    * Validates the bitcoin address with the wallet service.
     73    * @param address bitcoin address
     74    */
     75   def validateAddress(data: String) = workout_ {
     76     val address = extractFromBitcoinUri(data)
     77     ask(_, ValidateAddress(address)).mapTo[AddressValidation]
     78   }
     79   
     80   /**
     81    * Extracts bitcoin address from URI. 
     82    * 
     83    * Note the regex is not what the bitcoin address should exactly be,
     84    * but it works for extraction.
     85    */
     86   def extractFromBitcoinUri(uri: String) = {
     87     val r = "(bitcoin:)?([a-zA-Z0-9]{1,60})(/*?.*)?".r
     88     uri match {
     89       case r(_, address, _) => address
     90       case _ => ""
     91     }
     92   }
     93 }
     94 
     95 
     96 /**
     97  *  Balance remaining in bitcoin wallet.
     98  *  @param remaining balance remaining in bitcoin
     99  */
    100 case class Balance(remaining: Double) {
    101   def satoshis: Int = (remaining * 100000000) toInt
    102 }