diff --git a/src/main/scala/com/fluency03/blockchain/api/actors/PeerActor.scala b/src/main/scala/com/fluency03/blockchain/api/actors/PeerActor.scala index ac238b5..bcde51b 100644 --- a/src/main/scala/com/fluency03/blockchain/api/actors/PeerActor.scala +++ b/src/main/scala/com/fluency03/blockchain/api/actors/PeerActor.scala @@ -5,36 +5,38 @@ import java.security.KeyPair import akka.actor.Props import com.fluency03.blockchain.api.actors.PeerActor._ -import com.fluency03.blockchain.core.Peer +import com.fluency03.blockchain.core.{Peer, Wallet} import scala.collection.mutable object PeerActor { final case object GetPublicKeys - final case object CreateKeyPair + final case object CreateWallet def props: Props = Props[PeerActor] } class PeerActor extends ActorSupport { - override def preStart(): Unit = log.info("{} started!", this.getClass.getSimpleName) + override def preStart(): Unit = { + log.info("{} started!", this.getClass.getSimpleName) + addWallet() + log.info("Created initial wallet: {}", wallets.head._1) + } override def postStop(): Unit = log.info("{} stopped!", this.getClass.getSimpleName) // TODO (Chang): need persistence - val wallets = mutable.Map.empty[String, KeyPair] - addNewKeyPair() - + val wallets = mutable.Map.empty[String, Wallet] val others = mutable.Map.empty[String, Peer] def receive: Receive = { - case GetPublicKeys => sender() ! wallets.values.map(_.getPublic.toHex).toSet - case CreateKeyPair => sender() ! addNewKeyPair().getPublic.toHex + case GetPublicKeys => sender() ! wallets.values.map(_.address).toSet + case CreateWallet => sender() ! addWallet() case _ => unhandled _ } - private def addNewKeyPair(): KeyPair = { - val pair: KeyPair = Crypto.generateKeyPair() - wallets += (pair.getPublic.toHex -> pair) - pair + private def addWallet(): String = { + val newWallet = Wallet() + wallets += (newWallet.address -> newWallet) + newWallet.address } } diff --git a/src/main/scala/com/fluency03/blockchain/core/Wallet.scala b/src/main/scala/com/fluency03/blockchain/core/Wallet.scala new file mode 100644 index 0000000..fcaf404 --- /dev/null +++ b/src/main/scala/com/fluency03/blockchain/core/Wallet.scala @@ -0,0 +1,28 @@ +package com.fluency03.blockchain +package core + +import java.security.KeyPair + +import com.fluency03.blockchain.core.Wallet.balanceOfWallet + +import scala.collection.mutable + +case class Wallet() { + + private[this] val keyPair: KeyPair = Crypto.generateKeyPair() + + lazy val address: String = keyPair.getPublic.toHex + + def balance(uTxOs: mutable.Map[Outpoint, TxOut]): Long = balanceOfWallet(this, uTxOs) + +} + +object Wallet { + + def balanceOfWallet(wallet: Wallet, uTxOs: mutable.Map[Outpoint, TxOut]): Long = + balanceOfAddress(wallet.address, uTxOs) + + def balanceOfAddress(address: String, uTxOs: mutable.Map[Outpoint, TxOut]): Long = + uTxOs.values.filter(_.address == address).map(_.amount).sum + +} \ No newline at end of file diff --git a/src/test/scala/com/fluency03/blockchain/api/actors/PeerActorTest.scala b/src/test/scala/com/fluency03/blockchain/api/actors/PeerActorTest.scala index e176005..cf8706c 100644 --- a/src/test/scala/com/fluency03/blockchain/api/actors/PeerActorTest.scala +++ b/src/test/scala/com/fluency03/blockchain/api/actors/PeerActorTest.scala @@ -2,7 +2,7 @@ package com.fluency03.blockchain.api.actors import akka.actor.{ActorRef, ActorSystem, Props} import akka.testkit.{ImplicitSender, TestKit} -import com.fluency03.blockchain.api.actors.PeerActor.GetPublicKeys +import com.fluency03.blockchain.api.actors.PeerActor.{CreateWallet, GetPublicKeys} import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} class PeerActorTest extends TestKit(ActorSystem("PeerActorTest")) with ImplicitSender @@ -22,6 +22,13 @@ class PeerActorTest extends TestKit(ActorSystem("PeerActorTest")) with ImplicitS val publicKeys = expectMsgType[Set[String]] publicKeys.size shouldEqual 1 + peerActor ! CreateWallet + expectMsgType[String] + + peerActor ! GetPublicKeys + val publicKeys2 = expectMsgType[Set[String]] + publicKeys2.size shouldEqual 2 + peerActor ! "other" expectNoMessage } diff --git a/src/test/scala/com/fluency03/blockchain/core/WalletTest.scala b/src/test/scala/com/fluency03/blockchain/core/WalletTest.scala new file mode 100644 index 0000000..856fe73 --- /dev/null +++ b/src/test/scala/com/fluency03/blockchain/core/WalletTest.scala @@ -0,0 +1,26 @@ +package com.fluency03.blockchain.core + +import com.fluency03.blockchain.core.Wallet._ + +import org.scalatest.{FlatSpec, Matchers} + +import scala.collection.mutable + +class WalletTest extends FlatSpec with Matchers { + + "balanceOfWallet" should "obtain the balance of a Wallet based on UTXOs." in { + val wallet = Wallet() + val uTxOs: mutable.Map[Outpoint, TxOut] = mutable.Map.empty[Outpoint, TxOut] + + balanceOfWallet(wallet, uTxOs) shouldEqual 0 + wallet.balance(uTxOs) shouldEqual 0 + + uTxOs += (Outpoint("def0", 0) -> TxOut(wallet.address, 40)) + uTxOs += (Outpoint("def0", 1) -> TxOut("abc4", 40)) + + balanceOfWallet(wallet, uTxOs) shouldEqual 40 + wallet.balance(uTxOs) shouldEqual 40 + } + + +}