Skip to content

Commit 0a78fb5

Browse files
Bromel777GusevTimofey
authored andcommitted
* fix transfer command * Travis, hi!
1 parent 3c65a3c commit 0a78fb5

File tree

5 files changed

+98
-43
lines changed

5 files changed

+98
-43
lines changed

src/main/scala/encry/cli/ConsoleListener.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ object ConsoleListener {
5757
"createKey" -> CreateKey,
5858
"pubKeys" -> PrintPubKeys,
5959
"balance" -> GetBalance,
60-
//"transfer" -> Transfer, //TODO: after transfer fix - add
60+
"transfer" -> Transfer,
6161
"privKey" -> PrintPrivKeys //Todo delete
6262
))
6363

src/main/scala/encry/cli/commands/Transfer.scala

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import akka.util.Timeout
55
import encry.EncryApp._
66
import encry.cli.{Ast, Response}
77
import encry.modifiers.mempool.{Transaction, TransactionFactory}
8-
import encry.modifiers.state.box.{AssetBox, EncryProposition}
8+
import encry.modifiers.state.box.AssetBox
99
import encry.settings.EncryAppSettings
1010
import encry.view.EncryNodeViewHolder.ReceivableMessages._
1111
import encry.view.history.EncryHistory
@@ -16,38 +16,38 @@ import org.encryfoundation.common.transaction.EncryAddress.Address
1616
import scala.concurrent.Future
1717
import scala.util.Try
1818

19-
//TODO: Fix me
20-
//object Transfer extends Command {
21-
//
22-
// /**
23-
// * Command "wallet transfer -addr=<addr[String]> -fee=<fee[Num]> -amount=<amount[Num]>"
24-
// * Example "wallet transfer -addr='3jSD9fwHEHJwHq99ARqhnNhqGXeKnkJMyX4FZjHV6L3PjbCmjG' -fee=10000 -amount=2000"
25-
// */
26-
// override def execute(args: Command.Args, settings: EncryAppSettings): Future[Option[Response]] = {
27-
// implicit val timeout: Timeout = Timeout(settings.restApi.timeout)
28-
// (nodeViewHolder ?
29-
// GetDataFromCurrentView[EncryHistory, UtxoState, EncryWallet, Mempool, Option[Transaction]] { view =>
30-
// Try {
31-
// val secret: PrivateKey25519 = view.vault.accountManager.mandatoryAccount
32-
// val recipient: Address = args.requireArg[Ast.Str]("addr").s
33-
// val fee: Long = args.requireArg[Ast.Num]("fee").i
34-
// val amount: Long = args.requireArg[Ast.Num]("amount").i
35-
// val boxes: IndexedSeq[AssetBox] = view.vault.walletStorage.allBoxes.filter(_.isInstanceOf[AssetBox])
36-
// .map(_.asInstanceOf[AssetBox]).foldLeft(Seq[AssetBox]()) { case (seq, box) =>
37-
// if (seq.map(_.amount).sum < (amount + fee)) seq :+ box else seq
38-
// }.toIndexedSeq
39-
// TransactionFactory.defaultPaymentTransactionScratch(secret, fee, 0L, boxes, recipient, amount)
40-
// }.toOption
41-
// }).flatMap {
42-
// case Some(tx: Transaction) =>
43-
// timeProvider
44-
// .time()
45-
// .map { time =>
46-
// val txWithTimestamp = tx.copy(timestamp = time)
47-
// nodeViewHolder ! LocallyGeneratedTransaction[EncryProposition, Transaction](txWithTimestamp)
48-
// Some(Response(txWithTimestamp.toString))
49-
// }
50-
// case _ => Future.successful(Some(Response("Operation failed. Malformed data.")))
51-
// }
52-
// }
53-
//}
19+
object Transfer extends Command {
20+
21+
/**
22+
* Command "wallet transfer -addr=<addr[String]> -fee=<fee[Num]> -amount=<amount[Num]>"
23+
* Example "wallet transfer -addr='9fRWpnERVQKzR14qN5EGknx8xk11SU6LoZxcJAc53uAv3HRbL4K' -fee=10000 -amount=2000"
24+
*/
25+
override def execute(args: Command.Args, settings: EncryAppSettings): Future[Option[Response]] = {
26+
implicit val timeout: Timeout = Timeout(settings.restApi.timeout)
27+
(nodeViewHolder ?
28+
GetDataFromCurrentView[EncryHistory, UtxoState, EncryWallet, Option[Transaction]] { view =>
29+
Try {
30+
val secret: PrivateKey25519 = view.vault.accountManager.mandatoryAccount
31+
val recipient: Address = args.requireArg[Ast.Str]("addr").s
32+
val fee: Long = args.requireArg[Ast.Num]("fee").i
33+
val amount: Long = args.requireArg[Ast.Num]("amount").i
34+
val boxes: IndexedSeq[AssetBox] = view.vault.walletStorage.getAllBoxes().filter(_.isInstanceOf[AssetBox])
35+
.map(_.asInstanceOf[AssetBox]).foldLeft(Seq[AssetBox]()) { case (seq, box) =>
36+
if (seq.map(_.amount).sum < (amount + fee)) seq :+ box else seq
37+
}.toIndexedSeq
38+
TransactionFactory.defaultPaymentTransaction(
39+
secret,
40+
fee,
41+
System.currentTimeMillis(),
42+
boxes.map(_ -> None),
43+
recipient,
44+
amount)
45+
}.toOption
46+
}).flatMap {
47+
case Some(tx: Transaction) =>
48+
memoryPool ! LocallyGeneratedTransaction(tx)
49+
Future.successful(Some(Response(tx.toString)))
50+
case _ => Future.successful(Some(Response("Operation failed. Malformed data.")))
51+
}
52+
}
53+
}

src/main/scala/encry/modifiers/mempool/TransactionFactory.scala

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package encry.modifiers.mempool
22

3+
import com.typesafe.scalalogging.StrictLogging
34
import encry.modifiers.mempool.directive.{Directive, TransferDirective}
45
import encry.modifiers.state.box.Box.Amount
56
import encry.modifiers.state.box.MonetaryBox
@@ -8,9 +9,11 @@ import org.encryfoundation.common.crypto.{PrivateKey25519, PublicKey25519, Signa
89
import org.encryfoundation.common.transaction.EncryAddress.Address
910
import org.encryfoundation.common.transaction.{Input, Proof, PubKeyLockedContract}
1011
import org.encryfoundation.common.utils.TaggedTypes.ADKey
12+
import org.encryfoundation.prismlang.compiler.CompiledContract
1113
import org.encryfoundation.prismlang.core.wrapped.BoxedValue
14+
import scala.util.Random
1215

13-
object TransactionFactory {
16+
object TransactionFactory extends StrictLogging {
1417

1518
def defaultPaymentTransactionScratch(privKey: PrivateKey25519,
1619
fee: Amount,
@@ -45,4 +48,57 @@ object TransactionFactory {
4548

4649
Transaction(0, timestamp, IndexedSeq.empty, directives, None)
4750
}
51+
52+
def prepareTransaction(privKey: PrivateKey25519,
53+
fee: Long,
54+
timestamp: Long,
55+
useOutputs: Seq[(MonetaryBox, Option[(CompiledContract, Seq[Proof])])],
56+
directivesSeq: IndexedSeq[Directive],
57+
amount: Long,
58+
tokenIdOpt: Option[ADKey] = None): Transaction = {
59+
60+
val pubKey: PublicKey25519 = privKey.publicImage
61+
62+
val uInputs: IndexedSeq[Input] = useOutputs.toIndexedSeq.map { case (box, contractOpt) =>
63+
Input.unsigned(
64+
box.id,
65+
contractOpt match {
66+
case Some((ct, _)) => Left(ct)
67+
case None => Right(PubKeyLockedContract(pubKey.pubKeyBytes))
68+
}
69+
)
70+
}
71+
72+
val change: Long = amount
73+
74+
if (change < 0) {
75+
logger.warn(s"Transaction impossible: required amount is bigger than available. Change is: $change.")
76+
throw new RuntimeException("Transaction impossible: required amount is bigger than available.")
77+
}
78+
79+
val directives: IndexedSeq[Directive] =
80+
if (change > 0) directivesSeq ++: IndexedSeq(TransferDirective(pubKey.address.address, change, tokenIdOpt))
81+
else directivesSeq
82+
83+
val uTransaction: UnsignedTransaction = UnsignedTransaction(fee, timestamp, uInputs, directives)
84+
val signature: Signature25519 = privKey.sign(uTransaction.messageToSign)
85+
val proofs: IndexedSeq[Seq[Proof]] = useOutputs.flatMap(_._2.map(_._2)).toIndexedSeq
86+
87+
uTransaction.toSigned(proofs, Some(Proof(BoxedValue.Signature25519Value(signature.bytes.toList))))
88+
}
89+
90+
def defaultPaymentTransaction(privKey: PrivateKey25519,
91+
fee: Long,
92+
timestamp: Long,
93+
useOutputs: Seq[(MonetaryBox, Option[(CompiledContract, Seq[Proof])])],
94+
recipient: String,
95+
amount: Long,
96+
tokenIdOpt: Option[ADKey] = None): Transaction = {
97+
val howMuchCanTransfer: Long = useOutputs.map(_._1.amount).sum - fee
98+
val howMuchWillTransfer: Long = howMuchCanTransfer - Math.abs(Random.nextLong % howMuchCanTransfer)
99+
val change: Long = howMuchCanTransfer - howMuchWillTransfer
100+
val directives: IndexedSeq[TransferDirective] =
101+
IndexedSeq(TransferDirective(recipient, howMuchWillTransfer, tokenIdOpt))
102+
prepareTransaction(privKey, fee, timestamp, useOutputs, directives, change, tokenIdOpt)
103+
}
48104
}

src/main/scala/encry/modifiers/mempool/directive/TransferDirective.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,25 @@
11
package encry.modifiers.mempool.directive
22

33
import TransactionProto.TransactionProtoMessage.DirectiveProtoMessage
4-
import TransactionProto.TransactionProtoMessage.DirectiveProtoMessage.{ADKeyProto, DirectiveProto, ScriptedAssetDirectiveProtoMessage, TransferDirectiveProtoMessage}
4+
import TransactionProto.TransactionProtoMessage.DirectiveProtoMessage.{ADKeyProto, TransferDirectiveProtoMessage}
55
import com.google.common.primitives.{Bytes, Ints, Longs}
66
import com.google.protobuf.ByteString
7-
import encry.utils.CoreTaggedTypes.ModifierId
87
import encry.modifiers.mempool.directive.Directive.DTypeId
98
import encry.modifiers.state.box.Box.Amount
109
import encry.modifiers.state.box.{AssetBox, EncryBaseBox, EncryProposition}
1110
import encry.settings.Constants
11+
import encry.utils.CoreTaggedTypes.ModifierId
1212
import encry.utils.Utils
1313
import io.circe.syntax._
1414
import io.circe.{Decoder, Encoder, HCursor}
1515
import org.encryfoundation.common.Algos
1616
import org.encryfoundation.common.serialization.Serializer
1717
import org.encryfoundation.common.transaction.EncryAddress
1818
import org.encryfoundation.common.transaction.EncryAddress.Address
19-
import scorex.crypto.encode.Base16
2019
import org.encryfoundation.common.utils.TaggedTypes.ADKey
20+
import scorex.crypto.encode.Base16
2121
import scorex.crypto.hash.Digest32
2222
import supertagged.@@
23-
2423
import scala.util.Try
2524

2625
case class TransferDirective(address: Address,

src/main/scala/encry/modifiers/state/box/EncryProposition.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ package encry.modifiers.state.box
22

33
import encry.settings.Constants
44
import encry.view.history.History.Height
5-
import io.circe.{Decoder, Encoder, HCursor}
65
import io.circe.syntax._
6+
import io.circe.{Decoder, Encoder, HCursor}
77
import io.iohk.iodb.ByteArrayWrapper
88
import org.encryfoundation.common.Algos
99
import org.encryfoundation.common.serialization.Serializer

0 commit comments

Comments
 (0)