diff --git a/daml/Main.daml b/daml/Main.daml
index 94fb5b6..8a13296 100644
--- a/daml/Main.daml
+++ b/daml/Main.daml
@@ -11,42 +11,42 @@ import DA.Optional
initialize : Script [Party]
initialize = do
- operator <- allocateParty "Operator"
- operatorId <- validateUserId "operator"
- alice <- allocateParty "Alice"
- aliceId <- validateUserId "alice"
- bob <- allocateParty "Bob"
- bobId <- validateUserId "bob"
- eve <- allocateParty "Eve"
- eveId <- validateUserId "eve"
- operatorCid <- submit operator do
- createCmd Operator with operator = operator, address = ""
- orgCid <- submit operator do
- exerciseCmd operatorCid Operator_CreateOrganization
- with orgName = "Topl"
- membershipOfferCid <- submit operator do
- exerciseCmd orgCid Organization_InviteMember
- with
- invitee = alice
- membershipAcceptance <- submit alice do
- exerciseCmd membershipOfferCid Membershp_Accept
- submit operator do
- exerciseCmd membershipAcceptance AddUserToOrganization
- someOrg <- queryContractKey @Organization operator (operator, "Topl")
- membershipOfferCid <- submit operator do
- exerciseCmd (fromSome someOrg)._1 Organization_InviteMember
- with invitee = bob
- membershipAcceptance <- submit bob do
- exerciseCmd membershipOfferCid Membershp_Accept
- submit operator do
- exerciseCmd membershipAcceptance AddUserToOrganization
- userInvitationCid <- submit operator do
- exerciseCmd operatorCid Operator_InviteUser
- with user = alice
- aliceUserCid <- submit alice do
- exerciseCmd userInvitationCid UserInvitation_Accept
- createUser (Daml.Script.User aliceId (Some alice)) [CanActAs alice]
- createUser (Daml.Script.User operatorId (Some operator)) [CanActAs operator]
- createUser (Daml.Script.User bobId (Some bob)) [CanActAs bob]
- createUser (Daml.Script.User eveId (Some eve)) [CanActAs eve]
- pure [alice]
\ No newline at end of file
+ -- operator <- allocateParty "operator"
+ -- operatorId <- validateUserId "operator"
+ -- alice <- allocateParty "Alice"
+ -- aliceId <- validateUserId "alice"
+ -- bob <- allocateParty "Bob"
+ -- bobId <- validateUserId "bob"
+ -- eve <- allocateParty "Eve"
+ -- eveId <- validateUserId "eve"
+ -- operatorCid <- submit operator do
+ -- createCmd Operator with operator = operator, address = "AUANVY6RqbJtTnQS1AFTQBjXMFYDknhV8NEixHFLmeZynMxVbp64"
+ -- orgCid <- submit operator do
+ -- exerciseCmd operatorCid Operator_CreateOrganization
+ -- with orgName = "Topl"
+ -- membershipOfferCid <- submit operator do
+ -- exerciseCmd orgCid Organization_InviteMember
+ -- with
+ -- invitee = alice
+ -- membershipAcceptance <- submit alice do
+ -- exerciseCmd membershipOfferCid Membershp_Accept
+ -- submit operator do
+ -- exerciseCmd membershipAcceptance AddUserToOrganization
+ -- someOrg <- queryContractKey @Organization operator (operator, "Topl")
+ -- membershipOfferCid <- submit operator do
+ -- exerciseCmd (fromSome someOrg)._1 Organization_InviteMember
+ -- with invitee = bob
+ -- membershipAcceptance <- submit bob do
+ -- exerciseCmd membershipOfferCid Membershp_Accept
+ -- submit operator do
+ -- exerciseCmd membershipAcceptance AddUserToOrganization
+ -- userInvitationCid <- submit operator do
+ -- exerciseCmd operatorCid Operator_InviteUser
+ -- with user = alice
+ -- aliceUserCid <- submit alice do
+ -- exerciseCmd userInvitationCid UserInvitation_Accept
+ -- createUser (Daml.Script.User aliceId (Some alice)) [CanActAs alice]
+ -- createUser (Daml.Script.User operatorId (Some operator)) [CanActAs operator]
+ -- createUser (Daml.Script.User bobId (Some bob)) [CanActAs bob]
+ -- createUser (Daml.Script.User eveId (Some eve)) [CanActAs eve]
+ pure []
\ No newline at end of file
diff --git a/daml/Tests/Asset.daml b/daml/Tests/Asset.daml
index d86442d..62a3bd4 100644
--- a/daml/Tests/Asset.daml
+++ b/daml/Tests/Asset.daml
@@ -18,7 +18,6 @@ module Tests.Asset where
exerciseCmd orgId Organization_CreateAsset with
requestor = alice
version = 1
- issuerAddress = org.address
shortName = "Wheat"
return (operator, alice, bob, org)
-- now we create an asset creator
@@ -40,6 +39,7 @@ module Tests.Asset where
unsignedAssetMintingCid <- submit operator do
exerciseCmd assetMintingRequestCid MintingRequest_Accept with
txToSign = "ZZZZ"
+ boxNonce = 123
signedAssetMintingCreated <- submit operator do
exerciseCmd unsignedAssetMintingCid UnsignedMinting_Sign with
signedMintTx = "WWWWW"
@@ -75,6 +75,7 @@ module Tests.Asset where
unsignedAssetTransferCid <- submit operator do
exerciseCmd assetTransferRequestCid AssetTransferRequest_Accept with
txToSign = "ZZZZ"
+ newBoxNonce = 1234
signedAssetTransferCreated <- submit operator do
exerciseCmd unsignedAssetTransferCid UnsignedAssetTransfer_Sign with
signedTx = "WWWWW"
diff --git a/daml/Topl/Asset.daml b/daml/Topl/Asset.daml
index 2074cf0..b439da5 100644
--- a/daml/Topl/Asset.daml
+++ b/daml/Topl/Asset.daml
@@ -40,6 +40,7 @@ module Topl.Asset where
choice MintingRequest_Accept : UnsignedAssetMintingCid with
txToSign : Text
+ boxNonce : Int
controller operator
do
create UnsignedAssetMinting with
@@ -66,6 +67,7 @@ module Topl.Asset where
quantity : Int
someCommitRoot : Optional Text
someMetadata : Optional Text
+ boxNonce : Int
fee : Int
mintTxToSign : Text
where
@@ -99,6 +101,7 @@ module Topl.Asset where
quantity : Int
someCommitRoot : Optional Text
someMetadata : Optional Text
+ boxNonce : Int
fee : Int
mintTxToSign : Text
signedMintTx : Text
@@ -122,6 +125,11 @@ module Topl.Asset where
controller operator
do
return ()
+ choice SignedAssetMinting_Fail : SignedAssetMintingCid
+ with reason : Text
+ controller operator
+ do
+ create this with sendStatus = FailedToSend with ..
choice SignedAssetMinting_Confirm : SignedAssetMintingCid
with
txId : Text
@@ -150,15 +158,18 @@ module Topl.Asset where
quantity : Int
someCommitRoot : Optional Text
someMetadata : Optional Text
+ boxNonce : Int
fee : Int
where
signatory operator, requestor
choice AssetTransferRequest_Accept : UnsignedAssetTransferRequestCid with
txToSign : Text
+ newBoxNonce : Int
controller operator
do
create UnsignedAssetTransferRequest with
txToSign = txToSign
+ boxNonce = newBoxNonce
..
choice AssetTransferRequest_Reject : ()
controller operator
@@ -182,6 +193,7 @@ module Topl.Asset where
quantity : Int
someCommitRoot : Optional Text
someMetadata : Optional Text
+ boxNonce : Int
fee : Int
txToSign : Text
where
@@ -217,6 +229,7 @@ module Topl.Asset where
quantity : Int
someCommitRoot : Optional Text
someMetadata : Optional Text
+ boxNonce : Int
fee : Int
txToSign : Text
signedTx : Text
diff --git a/daml/Topl/Organization.daml b/daml/Topl/Organization.daml
index cbefef5..bfcdd53 100644
--- a/daml/Topl/Organization.daml
+++ b/daml/Topl/Organization.daml
@@ -106,6 +106,7 @@ module Topl.Organization where
quantity = signedAssetMinting.quantity
someMetadata = signedAssetMinting.someMetadata
someCommitRoot = signedAssetMinting.someCommitRoot
+ boxNonce = signedAssetMinting.boxNonce
..
nonconsuming choice Organization_AddSignedAssetTransfer: AssetIouCid with
@@ -124,6 +125,7 @@ module Topl.Organization where
quantity = signedAssetTransfer.quantity
someMetadata = signedAssetTransfer.someMetadata
someCommitRoot = signedAssetTransfer.someCommitRoot
+ boxNonce = signedAssetTransfer.boxNonce
..
@@ -153,7 +155,6 @@ module Topl.Organization where
newOrg Organization_CreateAsset with
requestor = head members
version = assetCode.version
- issuerAddress = assetCode.issuerAddress
shortName = assetCode.shortName)))
(create this with wouldBeMembers = [], members = members, assetCodes = [])
assetCodes
@@ -171,7 +172,6 @@ module Topl.Organization where
with
requestor : Party
version : Int
- issuerAddress : Text
shortName : Text
controller requestor
do
@@ -179,7 +179,6 @@ module Topl.Organization where
let asset = AssetCode
with
version = version
- issuerAddress = issuerAddress
shortName = shortName
create AssetCreator with
operator = operator
@@ -242,7 +241,8 @@ module Topl.Organization where
quantity : Int
someMetadata : Optional Text
assetCode : AssetCode
- someCommitRoot : Optional Text
+ someCommitRoot : Optional Text
+ boxNonce : Int
where
signatory operator, organization.members
diff --git a/daml/Topl/Utils.daml b/daml/Topl/Utils.daml
index c69cf0a..b0c6022 100644
--- a/daml/Topl/Utils.daml
+++ b/daml/Topl/Utils.daml
@@ -16,7 +16,6 @@ data SendStatus = New
data AssetCode = AssetCode with
version : Int
- issuerAddress : Text
shortName : Text
deriving (Eq, Show)
diff --git a/pom.xml b/pom.xml
index abcf142..a9ed3db 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,7 +7,7 @@
co.topl.daml
topl-daml-api
jar
- 1.0.0
+ 1.0.0-SNAPSHOT
UTF-8
@@ -195,10 +195,10 @@
- run-alice
+ run-asset-operator
- alice
+ assetoperator
@@ -208,7 +208,7 @@
exec-maven-plugin
1.6.0
- co.topl.daml.AliceMain
+ co.topl.daml.AssetOperatorMain
${ledgerhost}
${ledgerport}
@@ -218,6 +218,40 @@
${keyfilepassword}
+
+
+ run-demo-asset-operator
+
+ java
+
+
+
+
+
+
+
+
+ run-alice
+
+
+ alice
+
+
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.6.0
+
+ co.topl.daml.AliceMain
+
+ ${ledgerhost}
+ ${ledgerport}
+ ${keyfilename}
+ ${key1filepassword}
+
+
run-demo-alice
diff --git a/src/main/java/co/topl/daml/AliceMain.java b/src/main/java/co/topl/daml/AliceMain.java
index 62db726..3a6386e 100644
--- a/src/main/java/co/topl/daml/AliceMain.java
+++ b/src/main/java/co/topl/daml/AliceMain.java
@@ -12,14 +12,14 @@
import com.daml.ledger.javaapi.data.Transaction;
import com.daml.ledger.rxjava.DamlLedgerClient;
import com.daml.ledger.rxjava.UserManagementClient;
-import co.topl.daml.processors.UnsignedTransferProcessor;
+import co.topl.daml.polys.processors.UnsignedTransferProcessor;
import akka.actor.ActorSystem;
import co.topl.client.Provider;
import akka.http.javadsl.model.Uri;
import io.reactivex.Flowable;
-import co.topl.daml.processors.DamlAppContext;
-import co.topl.daml.processors.ToplContext;
+import co.topl.daml.DamlAppContext;
+import co.topl.daml.ToplContext;
public class AliceMain {
diff --git a/src/main/java/co/topl/daml/AssetOperatorMain.java b/src/main/java/co/topl/daml/AssetOperatorMain.java
new file mode 100644
index 0000000..af20956
--- /dev/null
+++ b/src/main/java/co/topl/daml/AssetOperatorMain.java
@@ -0,0 +1,85 @@
+package co.topl.daml;
+
+import java.util.Collections;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.daml.ledger.javaapi.data.FiltersByParty;
+import com.daml.ledger.javaapi.data.GetUserRequest;
+import com.daml.ledger.javaapi.data.LedgerOffset;
+import com.daml.ledger.javaapi.data.NoFilter;
+import com.daml.ledger.javaapi.data.Transaction;
+import com.daml.ledger.rxjava.DamlLedgerClient;
+import com.daml.ledger.rxjava.UserManagementClient;
+import co.topl.daml.assets.processors.AssetMintingRequestProcessor;
+import co.topl.daml.assets.processors.UnsignedMintingRequestProcessor;
+import co.topl.daml.assets.processors.SignedMintingRequestProcessor;
+import co.topl.daml.assets.processors.AssetTransferRequestProcessor;
+import co.topl.daml.assets.processors.UnsignedAssetTransferRequestProcessor;
+import co.topl.daml.assets.processors.SignedAssetTransferRequestProcessor;
+import akka.actor.ActorSystem;
+import co.topl.client.Provider;
+import akka.http.javadsl.model.Uri;
+
+import io.reactivex.Flowable;
+import co.topl.daml.DamlAppContext;
+import co.topl.daml.ToplContext;
+
+public class AssetOperatorMain {
+
+ // FIXME: Divide into smaller methods.
+
+ // constants for referring to users with access to the parties
+ public static final String OPERATOR_USER = "operator";
+
+ // application id used for sending commands
+ private static final String APP_ID = "OperatorMainApp";
+
+ private static final Logger logger = LoggerFactory.getLogger(OperatorMain.class);
+
+ public static void main(String[] args) {
+ // FIXME: add more robust handling of parameters.
+ if (args.length < 4) {
+ System.err.println("Usage: HOST PORT PROJECTID APIKEY KEYFILENAME KEYFILEPASSWORD");
+ System.exit(-1);
+ }
+ String host = args[0];
+ int port = Integer.parseInt(args[1]);
+ String projectId = args[2];
+ String apiKey = args[3];
+ String keyfile = args[4];
+ String password = args[5];
+ DamlLedgerClient client = DamlLedgerClient.newBuilder(host, port).build();
+ client.connect();
+ UserManagementClient userManagementClient = client.getUserManagementClient();
+
+ String operatorParty = userManagementClient.getUser(new GetUserRequest(OPERATOR_USER)).blockingGet().getUser()
+ .getPrimaryParty().get();
+ Flowable transactions = client.getTransactionsClient().getTransactions(
+ LedgerOffset.LedgerEnd.getInstance(),
+ new FiltersByParty(Collections.singletonMap(operatorParty, NoFilter.instance)), true);
+ Uri uri = Uri.create("http://localhost:9085");
+ DamlAppContext damlAppContext = new DamlAppContext(APP_ID, operatorParty, client);
+ ToplContext toplContext = new ToplContext(ActorSystem.create(), new Provider.PrivateTestNet(uri.asScala(), ""));
+ AssetMintingRequestProcessor assetMintingRequestProcessor = new AssetMintingRequestProcessor(damlAppContext,
+ toplContext);
+ transactions.forEach(assetMintingRequestProcessor::processTransaction);
+ UnsignedMintingRequestProcessor unsignedMintingRequestProcessor = new UnsignedMintingRequestProcessor(
+ damlAppContext, toplContext, keyfile, password);
+ transactions.forEach(unsignedMintingRequestProcessor::processTransaction);
+ SignedMintingRequestProcessor signedMintingRequestProcessor = new SignedMintingRequestProcessor(damlAppContext,
+ toplContext);
+ transactions.forEach(signedMintingRequestProcessor::processTransaction);
+
+ AssetTransferRequestProcessor assetTransferRequestProcessor = new AssetTransferRequestProcessor(damlAppContext,
+ toplContext);
+ transactions.forEach(assetTransferRequestProcessor::processTransaction);
+ UnsignedAssetTransferRequestProcessor unsignedTransferRequestProcessor = new UnsignedAssetTransferRequestProcessor(
+ damlAppContext, toplContext, keyfile, password);
+ transactions.forEach(unsignedTransferRequestProcessor::processTransaction);
+ SignedAssetTransferRequestProcessor signedTransferRequestProcessor = new SignedAssetTransferRequestProcessor(
+ damlAppContext, toplContext);
+ transactions.forEach(signedTransferRequestProcessor::processTransaction);
+ }
+}
diff --git a/src/main/java/co/topl/daml/OperatorMain.java b/src/main/java/co/topl/daml/OperatorMain.java
index e52a55b..ed7fb9d 100644
--- a/src/main/java/co/topl/daml/OperatorMain.java
+++ b/src/main/java/co/topl/daml/OperatorMain.java
@@ -12,15 +12,16 @@
import com.daml.ledger.javaapi.data.Transaction;
import com.daml.ledger.rxjava.DamlLedgerClient;
import com.daml.ledger.rxjava.UserManagementClient;
-import co.topl.daml.processors.TransferProcessor;
-import co.topl.daml.processors.SignedTransferProcessor;
+import co.topl.daml.polys.processors.TransferRequestProcessor;
+import co.topl.daml.polys.processors.SignedTransferProcessor;
+import co.topl.daml.assets.processors.AssetMintingRequestProcessor;
import akka.actor.ActorSystem;
import co.topl.client.Provider;
import akka.http.javadsl.model.Uri;
import io.reactivex.Flowable;
-import co.topl.daml.processors.DamlAppContext;
-import co.topl.daml.processors.ToplContext;
+import co.topl.daml.DamlAppContext;
+import co.topl.daml.ToplContext;
public class OperatorMain {
@@ -54,9 +55,12 @@ public static void main(String[] args) {
DamlAppContext damlAppContext = new DamlAppContext(APP_ID, operatorParty, client);
ToplContext toplContext = new ToplContext(ActorSystem.create(),
new Provider.ValhallaTestNet(uri.asScala(), apiKey));
- TransferProcessor transferProcessor = new TransferProcessor(damlAppContext, toplContext);
+ TransferRequestProcessor transferProcessor = new TransferRequestProcessor(damlAppContext, toplContext);
transactions.forEach(transferProcessor::processTransaction);
SignedTransferProcessor signedTransferProcessor = new SignedTransferProcessor(damlAppContext, toplContext);
transactions.forEach(signedTransferProcessor::processTransaction);
+ AssetMintingRequestProcessor assetMintingRequestProcessor = new AssetMintingRequestProcessor(damlAppContext,
+ toplContext);
+ transactions.forEach(assetMintingRequestProcessor::processTransaction);
}
}
diff --git a/src/main/resources/logback.xml b/src/main/resources/logback.xml
index ca03174..b857a2f 100644
--- a/src/main/resources/logback.xml
+++ b/src/main/resources/logback.xml
@@ -12,6 +12,6 @@
-
+
\ No newline at end of file
diff --git a/src/main/scala/co/topl/daml/processors/AbstractProcessor.scala b/src/main/scala/co/topl/daml/AbstractProcessor.scala
similarity index 95%
rename from src/main/scala/co/topl/daml/processors/AbstractProcessor.scala
rename to src/main/scala/co/topl/daml/AbstractProcessor.scala
index 657a91c..d3df87d 100644
--- a/src/main/scala/co/topl/daml/processors/AbstractProcessor.scala
+++ b/src/main/scala/co/topl/daml/AbstractProcessor.scala
@@ -1,12 +1,12 @@
-package co.topl.daml.processors
+package co.topl.daml
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
import com.daml.ledger.javaapi.data.Transaction
-import io.reactivex.Single
import com.google.protobuf.Empty
+import io.reactivex.Single
import java.util.stream
-import com.daml.ledger.javaapi.data.CreatedEvent
-import com.daml.ledger.javaapi.data.Command
import scala.concurrent.ExecutionContext
abstract class AbstractProcessor(damlAppContext: DamlAppContext, toplContext: ToplContext) {
diff --git a/src/main/scala/co/topl/daml/processors/Context.scala b/src/main/scala/co/topl/daml/Context.scala
similarity index 90%
rename from src/main/scala/co/topl/daml/processors/Context.scala
rename to src/main/scala/co/topl/daml/Context.scala
index 0d853e7..0f7a80b 100644
--- a/src/main/scala/co/topl/daml/processors/Context.scala
+++ b/src/main/scala/co/topl/daml/Context.scala
@@ -1,4 +1,4 @@
-package co.topl.daml.processors
+package co.topl.daml
import co.topl.client.Provider
import com.daml.ledger.rxjava.DamlLedgerClient
diff --git a/src/main/scala/co/topl/daml/assets/processors/AssetMintingRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/AssetMintingRequestProcessor.scala
new file mode 100644
index 0000000..ee57393
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/AssetMintingRequestProcessor.scala
@@ -0,0 +1,161 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import cats.data.NonEmptyChain
+import co.topl.akkahttprpc.implicits.client.rpcToClient
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.PublicKeyPropositionCurve25519._
+import co.topl.attestation._
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.topl.asset.AssetMintingRequest
+import co.topl.daml.processEventAux
+import co.topl.daml.utf8StringToLatin1ByteArray
+import co.topl.modifier.box.AssetCode
+import co.topl.modifier.box.AssetValue
+import co.topl.modifier.box.SecurityRoot
+import co.topl.modifier.transaction.AssetTransfer
+import co.topl.modifier.transaction.builder.BoxSelectionAlgorithms
+import co.topl.rpc.ToplRpc
+import co.topl.rpc.implicits.client._
+import co.topl.utils.IdiomaticScalaTransition.implicits.toValidatedOps
+import co.topl.utils.Int128
+import co.topl.utils.StringDataTypes
+import co.topl.utils.StringDataTypes.Base58Data
+import co.topl.utils.StringDataTypes.Latin1Data
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import org.slf4j.LoggerFactory
+import scodec.bits.ByteVector
+
+import java.util.stream
+import scala.collection.JavaConverters._
+import scala.collection.immutable.ListMap
+import scala.concurrent.Await
+
+import ToplRpc.Transaction.RawAssetTransfer
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+import co.topl.modifier.box.SimpleValue
+
+class AssetMintingRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ val logger = LoggerFactory.getLogger(classOf[AssetMintingRequestProcessor])
+
+ import toplContext.provider._
+
+ // FIXME: improve readbility by breaking into smaller methods
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(AssetMintingRequest.TEMPLATE_ID, event) {
+ val mintingRequestContract =
+ AssetMintingRequest.Contract.fromCreatedEvent(event).id
+ val assetMintingRequest =
+ AssetMintingRequest.fromValue(
+ event.getArguments()
+ )
+ val address = assetMintingRequest.from.asScala.toSeq
+ .map(Base58Data.unsafe)
+ .map(_.decodeAddress.getOrThrow())
+ val params =
+ ToplRpc.NodeView.Balances
+ .Params(
+ address.toList
+ )
+ val balances = ToplRpc.NodeView.Balances.rpc(params)
+ import scala.concurrent.duration._
+ import scala.language.postfixOps
+ Await.result(
+ balances.fold(
+ failure => {
+ logger.info("Failed to obtain raw transaction from server.")
+ logger.debug("Error: {}", failure)
+ stream.Stream.of(
+ mintingRequestContract
+ .exerciseTransferRequest_Reject()
+ )
+ },
+ balance => {
+ val to =
+ (
+ Base58Data.unsafe(assetMintingRequest.to.get(0)._1).decodeAddress.getOrThrow(),
+ SimpleValue(
+ balance.values.map(_.Boxes.PolyBox.head.value.quantity).head - Int128(assetMintingRequest.fee)
+ )
+ ) :: assetMintingRequest.to.asScala.toSeq
+ .map(x =>
+ (
+ Base58Data.unsafe(x._1).decodeAddress.getOrThrow(),
+ AssetValue(
+ Int128(x._2.intValue()),
+ AssetCode(
+ assetMintingRequest.assetCode.version.toByte,
+ Base58Data
+ .unsafe(assetMintingRequest.from.get(0))
+ .decodeAddress
+ .getOrThrow(),
+ Latin1Data.fromData(
+ utf8StringToLatin1ByteArray(assetMintingRequest.assetCode.shortName)
+ )
+ ),
+ assetMintingRequest.someCommitRoot
+ .map(x => SecurityRoot.fromBase58(Base58Data.unsafe(x)))
+ .orElse(SecurityRoot.empty),
+ assetMintingRequest.someMetadata
+ .map(x =>
+ Option(
+ Latin1Data.fromData(
+ utf8StringToLatin1ByteArray(x)
+ )
+ )
+ )
+ .orElse(None)
+ )
+ )
+ )
+ .toList
+
+ val assetTransfer = AssetTransfer(
+ balance.values.toList.flatMap(_.Boxes.PolyBox).map(x => (address.head, x.nonce)).toIndexedSeq,
+ to.toIndexedSeq,
+ ListMap(),
+ Int128(
+ assetMintingRequest.fee
+ ),
+ System.currentTimeMillis(),
+ None,
+ true
+ )
+ val mintingRequest = AssetTransferSerializer.toBytes(
+ assetTransfer
+ )
+ val encodedTx =
+ ByteVector(
+ mintingRequest
+ ).toBase58
+ logger.info("Successfully generated raw transaction for contract {}.", mintingRequestContract.contractId)
+ import io.circe.syntax._
+ logger.info("The returned json: {}", mintingRequest.asJson)
+ logger.debug(
+ "Encoded transaction: {}",
+ encodedTx
+ )
+
+ stream.Stream.of(
+ mintingRequestContract
+ .exerciseMintingRequest_Accept(
+ encodedTx,
+ assetTransfer.newBoxes.toList.reverse.head.nonce
+ )
+ )
+ }
+ ),
+ 3 second
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/assets/processors/AssetTransferRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/AssetTransferRequestProcessor.scala
new file mode 100644
index 0000000..d2dcd4d
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/AssetTransferRequestProcessor.scala
@@ -0,0 +1,171 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import cats.data.NonEmptyChain
+import co.topl.akkahttprpc.implicits.client.rpcToClient
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.PublicKeyPropositionCurve25519._
+import co.topl.attestation._
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.processEventAux
+import co.topl.daml.utf8StringToLatin1ByteArray
+import co.topl.modifier.box.AssetCode
+import co.topl.modifier.box.AssetValue
+import co.topl.modifier.box.SecurityRoot
+import co.topl.modifier.transaction.AssetTransfer
+import co.topl.modifier.transaction.builder.BoxSelectionAlgorithms
+import co.topl.rpc.ToplRpc
+import co.topl.rpc.implicits.client._
+import co.topl.utils.IdiomaticScalaTransition.implicits.toValidatedOps
+import co.topl.utils.Int128
+import co.topl.utils.StringDataTypes
+import co.topl.utils.StringDataTypes.Base58Data
+import co.topl.utils.StringDataTypes.Latin1Data
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import org.slf4j.LoggerFactory
+import scodec.bits.ByteVector
+
+import java.util.stream
+import scala.collection.JavaConverters._
+import scala.collection.immutable.ListMap
+import scala.concurrent.Await
+
+import ToplRpc.Transaction.RawAssetTransfer
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+import co.topl.modifier.box.SimpleValue
+import co.topl.daml.api.model.topl.asset.AssetTransferRequest
+
+class AssetTransferRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ val logger = LoggerFactory.getLogger(classOf[AssetTransferRequestProcessor])
+
+ import toplContext.provider._
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(AssetTransferRequest.TEMPLATE_ID, event) {
+ val transferRequestContract =
+ AssetTransferRequest.Contract.fromCreatedEvent(event).id
+ val assetTransferRequest =
+ AssetTransferRequest.fromValue(
+ event.getArguments()
+ )
+ val address = assetTransferRequest.from.asScala.toSeq
+ .map(Base58Data.unsafe)
+ .map(_.decodeAddress.getOrThrow())
+ val params =
+ ToplRpc.NodeView.Balances
+ .Params(
+ address.toList
+ )
+ val balances = ToplRpc.NodeView.Balances.rpc(params)
+
+ import scala.concurrent.duration._
+ import scala.language.postfixOps
+ Await.result(
+ balances.fold(
+ failure => {
+ logger.info("Failed to obtain raw transaction from server.")
+ logger.debug("Error: {}", failure)
+ stream.Stream.of(
+ transferRequestContract
+ .exerciseAssetTransferRequest_Reject()
+ )
+ },
+ balance => {
+ val to =
+ (
+ Base58Data.unsafe(assetTransferRequest.to.get(0)._1).decodeAddress.getOrThrow(),
+ SimpleValue(
+ balance.values.map(_.Boxes.PolyBox.head.value.quantity).head - Int128(assetTransferRequest.fee)
+ )
+ ) :: assetTransferRequest.to.asScala.toSeq
+ .map(x =>
+ (
+ Base58Data.unsafe(x._1).decodeAddress.getOrThrow(),
+ AssetValue(
+ Int128(x._2.intValue()),
+ AssetCode(
+ assetTransferRequest.assetCode.version.toByte,
+ Base58Data
+ .unsafe(assetTransferRequest.from.get(0))
+ .decodeAddress
+ .getOrThrow(),
+ Latin1Data.fromData(
+ utf8StringToLatin1ByteArray(assetTransferRequest.assetCode.shortName)
+ )
+ ),
+ assetTransferRequest.someCommitRoot
+ .map(x => SecurityRoot.fromBase58(Base58Data.unsafe(x)))
+ .orElse(SecurityRoot.empty),
+ assetTransferRequest.someMetadata
+ .map(x =>
+ Option(
+ Latin1Data.fromData(
+ utf8StringToLatin1ByteArray(x)
+ )
+ )
+ )
+ .orElse(None)
+ )
+ )
+ )
+ .toList
+
+ val assetTransfer = AssetTransfer(
+ balance.values.toList
+ .flatMap(_.Boxes.PolyBox)
+ .map(x => (address.head, x.nonce))
+ .toIndexedSeq
+ .++(
+ balance.values.toList
+ .flatMap(_.Boxes.AssetBox)
+ .filter(_.nonce == assetTransferRequest.boxNonce)
+ .map(x => (address.head, x.nonce))
+ .toIndexedSeq
+ ),
+ to.toIndexedSeq,
+ ListMap(),
+ Int128(
+ assetTransferRequest.fee
+ ),
+ System.currentTimeMillis(),
+ None,
+ false
+ )
+ val transferRequest = AssetTransferSerializer.toBytes(
+ assetTransfer
+ )
+ val encodedTx =
+ ByteVector(
+ transferRequest
+ ).toBase58
+ logger.info("Successfully generated raw transaction for contract {}.", transferRequestContract.contractId)
+ import io.circe.syntax._
+ logger.info("The returned json: {}", transferRequest.asJson)
+ logger.debug(
+ "Encoded transaction: {}",
+ encodedTx
+ )
+
+ stream.Stream.of(
+ transferRequestContract
+ .exerciseAssetTransferRequest_Accept(
+ encodedTx,
+ assetTransfer.newBoxes.toList.reverse.head.nonce
+ )
+ )
+ }
+ ),
+ 3 second
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/assets/processors/SignedAssetTransferRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/SignedAssetTransferRequestProcessor.scala
new file mode 100644
index 0000000..9574018
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/SignedAssetTransferRequestProcessor.scala
@@ -0,0 +1,161 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import cats.implicits._
+import co.topl.akkahttprpc.InvalidParametersError
+import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
+import co.topl.akkahttprpc.implicits.client._
+import co.topl.attestation.Address
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.da.types
+import co.topl.daml.api.model.topl.asset.SignedAssetMinting
+import co.topl.daml.api.model.topl.asset.SignedAssetTransfer
+import co.topl.daml.api.model.topl.asset.SignedAssetTransfer_Confirm
+import co.topl.daml.api.model.topl.organization.Organization
+import co.topl.daml.api.model.topl.transfer.SignedTransfer
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+import co.topl.daml.api.model.topl.utils.SendStatus
+import co.topl.daml.api.model.topl.utils.sendstatus.Confirmed
+import co.topl.daml.api.model.topl.utils.sendstatus.FailedToSend
+import co.topl.daml.api.model.topl.utils.sendstatus.Pending
+import co.topl.daml.api.model.topl.utils.sendstatus.Sent
+import co.topl.daml.processEventAux
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+import co.topl.rpc.ToplRpc
+import co.topl.rpc.implicits.client._
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import io.circe.DecodingFailure
+import io.circe.parser.parse
+import io.circe.syntax._
+import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
+import java.time.Instant
+import java.util.Optional
+import java.util.stream
+import scala.concurrent.Await
+import scala.concurrent.Future
+import scala.io.Source
+
+class SignedAssetTransferRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ implicit val networkPrefix = toplContext.provider.networkPrefix
+ implicit val jsonDecoder = co.topl.modifier.transaction.Transaction.jsonDecoder
+
+ val logger = LoggerFactory.getLogger(classOf[SignedAssetTransferRequestProcessor])
+ import toplContext.provider._
+
+ private def lift[E, A](a: Either[E, A]) = EitherT[Future, E, A](Future(a))
+
+ private def handlePending(
+ signedTransferRequest: SignedAssetTransfer,
+ signedTransferRequestContract: SignedAssetTransfer.ContractId
+ ): stream.Stream[Command] = {
+ val result = for {
+ transactionAsBytes <-
+ lift(
+ ByteVector
+ .fromBase58(signedTransferRequest.signedTx)
+ .map(_.toArray)
+ .toRight(RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid signed tx from base 58", Nil))))
+ )
+ _ = logger.debug("transactionAsBytes = {}", transactionAsBytes)
+ signedTx <- lift(
+ AssetTransferSerializer
+ .parseBytes(transactionAsBytes)
+ .toEither
+ .left
+ .map(_ => RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid bytes for transaction", Nil))))
+ )
+ _ = logger.debug("from address = {}", signedTx.from.head._1.toString())
+ broadcastResult <- ToplRpc.Transaction.BroadcastTx.rpc(ToplRpc.Transaction.BroadcastTx.Params(signedTx))
+ } yield broadcastResult
+ import scala.concurrent.duration._
+ import scala.language.postfixOps
+ Await
+ .result(result.value, 3 second)
+ .fold(
+ failure => {
+ logger.info("Failed to broadcast transaction to server.")
+ logger.debug("Error: {}", failure)
+ // FIXME: error handling
+ stream.Stream.of(
+ signedTransferRequestContract
+ .exerciseSignedAssetTransfer_Fail("Failed broadcast to server")
+ )
+ },
+ success => {
+ logger.info("Successfully broadcasted transaction to network.")
+ logger.debug(
+ "Server answer: {}",
+ success.asJson
+ )
+ stream.Stream.of(
+ signedTransferRequestContract
+ .exerciseSignedAssetTransfer_Sent(new Sent(Instant.now(), damlAppContext.appId, Optional.empty()))
+ )
+ }
+ )
+ }
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(SignedAssetTransfer.TEMPLATE_ID, event) {
+ val signedTransferRequestContract =
+ SignedAssetTransfer.Contract.fromCreatedEvent(event).id
+ val signedTransferRequest =
+ SignedAssetTransfer.fromValue(
+ event.getArguments()
+ )
+ if (signedTransferRequest.sendStatus.isInstanceOf[Pending]) {
+ handlePending(signedTransferRequest, signedTransferRequestContract)
+ } else if (signedTransferRequest.sendStatus.isInstanceOf[FailedToSend]) {
+ logger.error("Failed to send contract.")
+ stream.Stream.of(
+ signedTransferRequestContract
+ .exerciseSignedAssetTransfer_Archive()
+ )
+ } else if (signedTransferRequest.sendStatus.isInstanceOf[Sent]) {
+ logger.info("Successfully sent.")
+ stream.Stream.of(
+ signedTransferRequestContract
+ .exerciseSignedAssetTransfer_Confirm(
+ new SignedAssetTransfer_Confirm(
+ (signedTransferRequest.sendStatus.asInstanceOf[Sent]).txHash.orElseGet(() => ""),
+ 1
+ )
+ )
+ )
+ } else if (signedTransferRequest.sendStatus.isInstanceOf[Confirmed]) {
+ logger.info("Successfully confirmed.")
+
+ stream.Stream.of(
+ Organization
+ .byKey(new types.Tuple2(signedTransferRequest.operator, signedTransferRequest.someOrgName.get()))
+ .exerciseOrganization_AddSignedAssetTransfer(signedTransferRequestContract)
+ )
+ } else {
+ stream.Stream.of(
+ signedTransferRequestContract
+ .exerciseSignedAssetTransfer_Archive()
+ )
+ }
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/assets/processors/SignedMintingRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/SignedMintingRequestProcessor.scala
new file mode 100644
index 0000000..5506223
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/SignedMintingRequestProcessor.scala
@@ -0,0 +1,166 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import cats.implicits._
+import co.topl.akkahttprpc.InvalidParametersError
+import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
+import co.topl.akkahttprpc.implicits.client._
+import co.topl.attestation.Address
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.da.types
+import co.topl.daml.api.model.topl.asset.SignedAssetMinting
+import co.topl.daml.api.model.topl.asset.SignedAssetMinting_Confirm
+import co.topl.daml.api.model.topl.organization.Organization
+import co.topl.daml.api.model.topl.transfer.SignedTransfer
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+import co.topl.daml.api.model.topl.utils.SendStatus
+import co.topl.daml.api.model.topl.utils.sendstatus.Confirmed
+import co.topl.daml.api.model.topl.utils.sendstatus.FailedToSend
+import co.topl.daml.api.model.topl.utils.sendstatus.Pending
+import co.topl.daml.api.model.topl.utils.sendstatus.Sent
+import co.topl.daml.processEventAux
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+import co.topl.rpc.ToplRpc
+import co.topl.rpc.implicits.client._
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.api.v1.CommandsOuterClass
+import com.daml.ledger.api.v1.TransactionFilterOuterClass
+import com.daml.ledger.api.v1.ValueOuterClass.Identifier
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import com.daml.ledger.javaapi.data.TransactionFilter
+import io.circe.DecodingFailure
+import io.circe.parser.parse
+import io.circe.syntax._
+import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
+import java.time.Instant
+import java.util.Optional
+import java.util.stream
+import scala.concurrent.Await
+import scala.concurrent.Future
+import scala.io.Source
+
+class SignedMintingRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ implicit val networkPrefix = toplContext.provider.networkPrefix
+ implicit val jsonDecoder = co.topl.modifier.transaction.Transaction.jsonDecoder
+
+ val logger = LoggerFactory.getLogger(classOf[SignedMintingRequestProcessor])
+ import toplContext.provider._
+
+ private def lift[E, A](a: Either[E, A]) = EitherT[Future, E, A](Future(a))
+
+ private def handlePending(
+ signedMintingRequest: SignedAssetMinting,
+ signedMintingRequestContract: SignedAssetMinting.ContractId
+ ): stream.Stream[Command] = {
+ val result = for {
+ transactionAsBytes <-
+ lift(
+ ByteVector
+ .fromBase58(signedMintingRequest.signedMintTx)
+ .map(_.toArray)
+ .toRight(RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid signed tx from base 58", Nil))))
+ )
+ _ = logger.debug("transactionAsBytes = {}", transactionAsBytes)
+ signedTx <- lift(
+ AssetTransferSerializer
+ .parseBytes(transactionAsBytes)
+ .toEither
+ .left
+ .map(_ => RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid bytes for transaction", Nil))))
+ )
+ _ = logger.debug("from address = {}", signedTx.from.head._1.toString())
+ broadcastResult <- ToplRpc.Transaction.BroadcastTx.rpc(ToplRpc.Transaction.BroadcastTx.Params(signedTx))
+ } yield broadcastResult
+ import scala.concurrent.duration._
+ import scala.language.postfixOps
+ Await
+ .result(result.value, 3 second)
+ .fold(
+ failure => {
+ logger.info("Failed to broadcast transaction to server.")
+ logger.debug("Error: {}", failure)
+ // FIXME: error handling
+ stream.Stream.of(
+ signedMintingRequestContract
+ .exerciseSignedAssetMinting_Fail("Failed broadcast to server")
+ )
+ },
+ success => {
+ logger.info("Successfully broadcasted transaction to network.")
+ logger.debug(
+ "Server answer: {}",
+ success.asJson
+ )
+ stream.Stream.of(
+ signedMintingRequestContract
+ .exerciseSignedAssetMinting_Sent(
+ new Sent(Instant.now(), damlAppContext.appId, Optional.of(success.id.toString()))
+ )
+ )
+ }
+ )
+ }
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(SignedAssetMinting.TEMPLATE_ID, event) {
+ val signedMintingRequestContract =
+ SignedAssetMinting.Contract.fromCreatedEvent(event).id
+ val signedMintingRequest =
+ SignedAssetMinting.fromValue(
+ event.getArguments()
+ )
+ if (signedMintingRequest.sendStatus.isInstanceOf[Pending]) {
+ handlePending(signedMintingRequest, signedMintingRequestContract)
+ } else if (signedMintingRequest.sendStatus.isInstanceOf[FailedToSend]) {
+ logger.error("Failed to send contract.")
+ stream.Stream.of(
+ signedMintingRequestContract
+ .exerciseSignedAssetMinting_Archive()
+ )
+ } else if (signedMintingRequest.sendStatus.isInstanceOf[Sent]) {
+ logger.info("Successfully sent.")
+ stream.Stream.of(
+ signedMintingRequestContract
+ .exerciseSignedAssetMinting_Confirm(
+ new SignedAssetMinting_Confirm(
+ (signedMintingRequest.sendStatus.asInstanceOf[Sent]).txHash.orElseGet(() => ""),
+ 1
+ )
+ )
+ )
+ } else if (signedMintingRequest.sendStatus.isInstanceOf[Confirmed]) {
+ logger.info("Successfully confirmed.")
+
+ stream.Stream.of(
+ Organization
+ .byKey(new types.Tuple2(signedMintingRequest.operator, signedMintingRequest.someOrgName.get()))
+ .exerciseOrganization_AddSignedAssetMinting(signedMintingRequestContract)
+ )
+ } else {
+ stream.Stream.of(
+ signedMintingRequestContract
+ .exerciseSignedAssetMinting_Archive()
+ )
+ }
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/assets/processors/UnsignedAssetTransferRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/UnsignedAssetTransferRequestProcessor.scala
new file mode 100644
index 0000000..4951a7a
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/UnsignedAssetTransferRequestProcessor.scala
@@ -0,0 +1,104 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import co.topl.akkahttprpc.InvalidParametersError
+import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
+import co.topl.attestation.Address
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.topl.asset.UnsignedAssetMinting
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+
+import co.topl.daml.processEventAux
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import io.circe.DecodingFailure
+import io.circe.parser.parse
+import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
+import java.util.stream
+import scala.concurrent.Future
+import scala.io.Source
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+import co.topl.daml.api.model.topl.asset.UnsignedAssetTransferRequest
+
+class UnsignedAssetTransferRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext,
+ fileName: String,
+ password: String
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ implicit val networkPrefix = toplContext.provider.networkPrefix
+
+ val logger = LoggerFactory.getLogger(classOf[UnsignedAssetTransferRequestProcessor])
+
+ val keyRing: KeyRing[PrivateKeyCurve25519, KeyfileCurve25519] =
+ KeyRing.empty[PrivateKeyCurve25519, KeyfileCurve25519]()(
+ toplContext.provider.networkPrefix,
+ PrivateKeyCurve25519.secretGenerator,
+ KeyfileCurve25519Companion
+ )
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(UnsignedAssetTransferRequest.TEMPLATE_ID, event) {
+ val unsidgnedTransferRequestContract =
+ UnsignedAssetTransferRequest.Contract.fromCreatedEvent(event).id
+ val unsidgnedTransferRequest =
+ UnsignedAssetTransferRequest.fromValue(
+ event.getArguments()
+ )
+ val keyfile = Source.fromFile(new File(fileName)).getLines().mkString("").mkString
+ (for {
+ jsonKey <- parse(keyfile)
+ address <- Brambl.importCurve25519JsonToKeyRing(jsonKey, password, keyRing)
+ msg2Sign <- ByteVector
+ .fromBase58(unsidgnedTransferRequest.txToSign)
+ .map(_.toArray)
+ .toRight(RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid contract", Nil))))
+ rawTx <- AssetTransferSerializer.parseBytes(msg2Sign).toEither
+ signedTx <- Right {
+ val signFunc = (addr: Address) => keyRing.generateAttestation(addr)(rawTx.messageToSign)
+ logger.debug("listOfAddresses = {}", keyRing.addresses)
+ val signatures = keyRing.addresses.map(signFunc).reduce(_ ++ _)
+ rawTx.copy(attestation = signatures)
+ }
+ } yield signedTx).fold(
+ failure => {
+ logger.info("Failed to sign transaction.")
+ logger.debug("Error: {}", failure)
+ stream.Stream.of(
+ unsidgnedTransferRequestContract
+ .exerciseUnsignedAssetTransfer_Archive()
+ )
+ },
+ signedTx => {
+ val signedTxString = ByteVector(AssetTransferSerializer.toBytes(signedTx)).toBase58
+ logger.info("Successfully signed transaction for contract {}.", unsidgnedTransferRequestContract.contractId)
+ logger.debug("signedTx = {}", signedTx)
+ logger.debug(
+ "Encoded transaction: {}",
+ signedTxString
+ )
+ stream.Stream.of(
+ unsidgnedTransferRequestContract
+ .exerciseUnsignedAssetTransfer_Sign(signedTxString)
+ )
+ }
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/assets/processors/UnsignedMintingRequestProcessor.scala b/src/main/scala/co/topl/daml/assets/processors/UnsignedMintingRequestProcessor.scala
new file mode 100644
index 0000000..18456b5
--- /dev/null
+++ b/src/main/scala/co/topl/daml/assets/processors/UnsignedMintingRequestProcessor.scala
@@ -0,0 +1,103 @@
+package co.topl.daml.assets.processors
+
+import cats.data.EitherT
+import co.topl.akkahttprpc.InvalidParametersError
+import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
+import co.topl.attestation.Address
+import co.topl.attestation.AddressCodec.implicits._
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.topl.asset.UnsignedAssetMinting
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+
+import co.topl.daml.processEventAux
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import io.circe.DecodingFailure
+import io.circe.parser.parse
+import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
+import java.util.stream
+import scala.concurrent.Future
+import scala.io.Source
+import co.topl.modifier.transaction.serialization.AssetTransferSerializer
+
+class UnsignedMintingRequestProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext,
+ fileName: String,
+ password: String
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ implicit val networkPrefix = toplContext.provider.networkPrefix
+
+ val logger = LoggerFactory.getLogger(classOf[UnsignedMintingRequestProcessor])
+
+ val keyRing: KeyRing[PrivateKeyCurve25519, KeyfileCurve25519] =
+ KeyRing.empty[PrivateKeyCurve25519, KeyfileCurve25519]()(
+ toplContext.provider.networkPrefix,
+ PrivateKeyCurve25519.secretGenerator,
+ KeyfileCurve25519Companion
+ )
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(UnsignedAssetMinting.TEMPLATE_ID, event) {
+ val unsidgnedMintingRequestContract =
+ UnsignedAssetMinting.Contract.fromCreatedEvent(event).id
+ val unsidgnedMintingRequest =
+ UnsignedAssetMinting.fromValue(
+ event.getArguments()
+ )
+ val keyfile = Source.fromFile(new File(fileName)).getLines().mkString("").mkString
+ (for {
+ jsonKey <- parse(keyfile)
+ address <- Brambl.importCurve25519JsonToKeyRing(jsonKey, password, keyRing)
+ msg2Sign <- ByteVector
+ .fromBase58(unsidgnedMintingRequest.mintTxToSign)
+ .map(_.toArray)
+ .toRight(RpcErrorFailure(InvalidParametersError(DecodingFailure("Invalid contract", Nil))))
+ rawTx <- AssetTransferSerializer.parseBytes(msg2Sign).toEither
+ signedTx <- Right {
+ val signFunc = (addr: Address) => keyRing.generateAttestation(addr)(rawTx.messageToSign)
+ logger.debug("listOfAddresses = {}", keyRing.addresses)
+ val signatures = keyRing.addresses.map(signFunc).reduce(_ ++ _)
+ rawTx.copy(attestation = signatures)
+ }
+ } yield signedTx).fold(
+ failure => {
+ logger.info("Failed to sign transaction.")
+ logger.debug("Error: {}", failure)
+ stream.Stream.of(
+ unsidgnedMintingRequestContract
+ .exerciseUnsignedMinting_Archive()
+ )
+ },
+ signedTx => {
+ val signedTxString = ByteVector(AssetTransferSerializer.toBytes(signedTx)).toBase58
+ logger.info("Successfully signed transaction for contract {}.", unsidgnedMintingRequestContract.contractId)
+ logger.debug("signedTx = {}", signedTx)
+ logger.debug(
+ "Encoded transaction: {}",
+ signedTxString
+ )
+ stream.Stream.of(
+ unsidgnedMintingRequestContract
+ .exerciseUnsignedMinting_Sign(signedTxString)
+ )
+ }
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/operator/AssetIouProcessor.scala b/src/main/scala/co/topl/daml/operator/AssetIouProcessor.scala
new file mode 100644
index 0000000..003a7f8
--- /dev/null
+++ b/src/main/scala/co/topl/daml/operator/AssetIouProcessor.scala
@@ -0,0 +1,34 @@
+package co.topl.daml.operator
+
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.AbstractProcessor
+import com.daml.ledger.javaapi.data.CreatedEvent
+
+import java.util.stream
+import com.daml.ledger.javaapi.data.Command
+import co.topl.daml.processEventAux
+import co.topl.daml.api.model.topl.organization.AssetIou
+import co.topl.daml.api.model.da.types
+
+class AssetIouProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext,
+ lambda: java.util.function.BiConsumer[AssetIou, AssetIou.ContractId]
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(AssetIou.TEMPLATE_ID, event) {
+ val assetIouContract =
+ AssetIou.Contract.fromCreatedEvent(event).id
+ val assetIou =
+ AssetIou.fromValue(
+ event.getArguments()
+ )
+ lambda.accept(assetIou, assetIouContract)
+ stream.Stream.empty()
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/operator/MembershipAcceptanceProcessor.scala b/src/main/scala/co/topl/daml/operator/MembershipAcceptanceProcessor.scala
new file mode 100644
index 0000000..851de47
--- /dev/null
+++ b/src/main/scala/co/topl/daml/operator/MembershipAcceptanceProcessor.scala
@@ -0,0 +1,31 @@
+package co.topl.daml.operator
+
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.AbstractProcessor
+import com.daml.ledger.javaapi.data.CreatedEvent
+
+import java.util.stream
+import com.daml.ledger.javaapi.data.Command
+import co.topl.daml.processEventAux
+import co.topl.daml.api.model.topl.organization.MembershipAcceptance
+
+class MembershipAcceptanceProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(MembershipAcceptance.TEMPLATE_ID, event) {
+ val membershipAcceptanceContract =
+ MembershipAcceptance.Contract.fromCreatedEvent(event).id
+
+ stream.Stream.of(
+ membershipAcceptanceContract
+ .exerciseAddUserToOrganization()
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/operator/MembershipOfferProcessor.scala b/src/main/scala/co/topl/daml/operator/MembershipOfferProcessor.scala
new file mode 100644
index 0000000..b44778c
--- /dev/null
+++ b/src/main/scala/co/topl/daml/operator/MembershipOfferProcessor.scala
@@ -0,0 +1,32 @@
+package co.topl.daml.operator
+
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.AbstractProcessor
+import com.daml.ledger.javaapi.data.CreatedEvent
+
+import java.util.stream
+import com.daml.ledger.javaapi.data.Command
+import co.topl.daml.processEventAux
+import co.topl.daml.api.model.topl.organization.MembershipAcceptance
+import co.topl.daml.api.model.topl.organization.MembershipOffer
+
+class MembershipOfferProcessor(
+ damlAppContext: DamlAppContext,
+ toplContext: ToplContext
+) extends AbstractProcessor(damlAppContext, toplContext) {
+
+ def processEvent(
+ workflowsId: String,
+ event: CreatedEvent
+ ): stream.Stream[Command] = processEventAux(MembershipOffer.TEMPLATE_ID, event) {
+ val membershipOfferContract =
+ MembershipOffer.Contract.fromCreatedEvent(event).id
+
+ stream.Stream.of(
+ membershipOfferContract
+ .exerciseMembershp_Accept()
+ )
+ }
+
+}
diff --git a/src/main/scala/co/topl/daml/processors/package.scala b/src/main/scala/co/topl/daml/package.scala
similarity index 90%
rename from src/main/scala/co/topl/daml/processors/package.scala
rename to src/main/scala/co/topl/daml/package.scala
index 990af84..e3c0f97 100644
--- a/src/main/scala/co/topl/daml/processors/package.scala
+++ b/src/main/scala/co/topl/daml/package.scala
@@ -1,4 +1,4 @@
-package co.topl.daml
+package co.topl
import cats.data.EitherT
import scala.concurrent.Future
@@ -14,7 +14,7 @@ import com.daml.ledger.rxjava.LedgerClient
import java.util.UUID
import io.reactivex.subjects.SingleSubject
-package object processors {
+package object daml {
type RpcErrorOr[T] = EitherT[Future, RpcClientFailure, T]
@@ -49,4 +49,9 @@ package object processors {
)
} else return SingleSubject.create()
}
+
+ def utf8StringToLatin1ByteArray(str: String) = str.zipWithIndex
+ .map(e => str.codePointAt(e._2).toByte)
+ .toArray
+
}
diff --git a/src/main/scala/co/topl/daml/processors/SignedTransferProcessor.scala b/src/main/scala/co/topl/daml/polys/processors/SignedTransferProcessor.scala
similarity index 91%
rename from src/main/scala/co/topl/daml/processors/SignedTransferProcessor.scala
rename to src/main/scala/co/topl/daml/polys/processors/SignedTransferProcessor.scala
index 3ff4733..aff89c2 100644
--- a/src/main/scala/co/topl/daml/processors/SignedTransferProcessor.scala
+++ b/src/main/scala/co/topl/daml/polys/processors/SignedTransferProcessor.scala
@@ -1,41 +1,48 @@
-package co.topl.daml.processors
+package co.topl.daml.polys.processors
-import java.util.stream
-import com.daml.ledger.javaapi.data.Command
-import com.daml.ledger.javaapi.data.CreatedEvent
-import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
-import co.topl.attestation.keyManagement.{KeyRing, KeyfileCurve25519, KeyfileCurve25519Companion, PrivateKeyCurve25519}
-import co.topl.client.Brambl
+import cats.data.EitherT
+import cats.implicits._
+import co.topl.akkahttprpc.InvalidParametersError
import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
+import co.topl.akkahttprpc.implicits.client._
import co.topl.attestation.Address
-import io.circe.parser.parse
-import scala.io.Source
-import java.io.File
-import cats.data.EitherT
-import co.topl.utils.StringDataTypes
import co.topl.attestation.AddressCodec.implicits._
-import scodec.bits._
-import co.topl.akkahttprpc.RpcErrorFailure
-import co.topl.akkahttprpc.InvalidParametersError
-import io.circe.DecodingFailure
-import scala.concurrent.Future
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.topl.transfer.SignedTransfer
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+import co.topl.daml.api.model.topl.utils.SendStatus
+import co.topl.daml.api.model.topl.utils.sendstatus.FailedToSend
+import co.topl.daml.api.model.topl.utils.sendstatus.Pending
+import co.topl.daml.api.model.topl.utils.sendstatus.Sent
+import co.topl.daml.processEventAux
import co.topl.modifier.transaction.PolyTransfer
import co.topl.modifier.transaction.serialization.PolyTransferSerializer
-import org.slf4j.LoggerFactory
-import co.topl.daml.api.model.topl.transfer.SignedTransfer
import co.topl.rpc.ToplRpc
-
-import co.topl.akkahttprpc.implicits.client._
import co.topl.rpc.implicits.client._
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import io.circe.DecodingFailure
+import io.circe.parser.parse
import io.circe.syntax._
-import cats.implicits._
-import scala.concurrent.Await
-import co.topl.daml.api.model.topl.utils.sendstatus.Pending
-import co.topl.daml.api.model.topl.utils.sendstatus.FailedToSend
-import co.topl.daml.api.model.topl.utils.SendStatus
-import co.topl.daml.api.model.topl.utils.sendstatus.Sent
+import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
import java.time.Instant
import java.util.Optional
+import java.util.stream
+import scala.concurrent.Await
+import scala.concurrent.Future
+import scala.io.Source
class SignedTransferProcessor(
damlAppContext: DamlAppContext,
diff --git a/src/main/scala/co/topl/daml/processors/TransferProcessor.scala b/src/main/scala/co/topl/daml/polys/processors/TransferRequestProcessor.scala
similarity index 94%
rename from src/main/scala/co/topl/daml/processors/TransferProcessor.scala
rename to src/main/scala/co/topl/daml/polys/processors/TransferRequestProcessor.scala
index 73a2aea..d810e85 100644
--- a/src/main/scala/co/topl/daml/processors/TransferProcessor.scala
+++ b/src/main/scala/co/topl/daml/polys/processors/TransferRequestProcessor.scala
@@ -1,4 +1,4 @@
-package co.topl.daml.processors
+package co.topl.daml.polys.processors
import com.daml.ledger.rxjava.DamlLedgerClient
import io.reactivex.Single
@@ -40,13 +40,17 @@ import io.reactivex.subjects.SingleSubject
import com.google.protobuf.Empty
import org.slf4j.LoggerFactory
import co.topl.modifier.transaction.serialization.PolyTransferSerializer
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.processEventAux
-class TransferProcessor(
+class TransferRequestProcessor(
damlAppContext: DamlAppContext,
toplContext: ToplContext
) extends AbstractProcessor(damlAppContext, toplContext) {
- val logger = LoggerFactory.getLogger(classOf[TransferProcessor])
+ val logger = LoggerFactory.getLogger(classOf[TransferRequestProcessor])
import toplContext.provider._
diff --git a/src/main/scala/co/topl/daml/processors/UnsignedTransferProcessor.scala b/src/main/scala/co/topl/daml/polys/processors/UnsignedTransferProcessor.scala
similarity index 89%
rename from src/main/scala/co/topl/daml/processors/UnsignedTransferProcessor.scala
rename to src/main/scala/co/topl/daml/polys/processors/UnsignedTransferProcessor.scala
index a2388c0..ac7c0e5 100644
--- a/src/main/scala/co/topl/daml/processors/UnsignedTransferProcessor.scala
+++ b/src/main/scala/co/topl/daml/polys/processors/UnsignedTransferProcessor.scala
@@ -1,27 +1,35 @@
-package co.topl.daml.processors
+package co.topl.daml.polys.processors
-import java.util.stream
-import com.daml.ledger.javaapi.data.Command
-import com.daml.ledger.javaapi.data.CreatedEvent
-import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
-import co.topl.attestation.keyManagement.{KeyRing, KeyfileCurve25519, KeyfileCurve25519Companion, PrivateKeyCurve25519}
-import co.topl.client.Brambl
+import cats.data.EitherT
+import co.topl.akkahttprpc.InvalidParametersError
import co.topl.akkahttprpc.RpcClientFailure
+import co.topl.akkahttprpc.RpcErrorFailure
import co.topl.attestation.Address
-import io.circe.parser.parse
-import scala.io.Source
-import java.io.File
-import cats.data.EitherT
-import co.topl.utils.StringDataTypes
import co.topl.attestation.AddressCodec.implicits._
-import scodec.bits._
-import co.topl.akkahttprpc.RpcErrorFailure
-import co.topl.akkahttprpc.InvalidParametersError
-import io.circe.DecodingFailure
-import scala.concurrent.Future
+import co.topl.attestation.keyManagement.KeyRing
+import co.topl.attestation.keyManagement.KeyfileCurve25519
+import co.topl.attestation.keyManagement.KeyfileCurve25519Companion
+import co.topl.attestation.keyManagement.PrivateKeyCurve25519
+import co.topl.client.Brambl
+import co.topl.daml.AbstractProcessor
+import co.topl.daml.DamlAppContext
+import co.topl.daml.ToplContext
+import co.topl.daml.api.model.topl.transfer.UnsignedTransfer
+import co.topl.daml.processEventAux
import co.topl.modifier.transaction.PolyTransfer
import co.topl.modifier.transaction.serialization.PolyTransferSerializer
+import co.topl.utils.StringDataTypes
+import com.daml.ledger.javaapi.data.Command
+import com.daml.ledger.javaapi.data.CreatedEvent
+import io.circe.DecodingFailure
+import io.circe.parser.parse
import org.slf4j.LoggerFactory
+import scodec.bits._
+
+import java.io.File
+import java.util.stream
+import scala.concurrent.Future
+import scala.io.Source
class UnsignedTransferProcessor(
damlAppContext: DamlAppContext,