-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
TSDK-663 Transaction Pretty Print / Display (#167)
* Updated Readme * Finished UTXO display * Finished Transaction display * Added Txo display * Added blockId display * Parameterized the label padding * Ensured tests pass with padding
- Loading branch information
1 parent
58bc32d
commit 27cdf2d
Showing
12 changed files
with
470 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
30 changes: 30 additions & 0 deletions
30
brambl-sdk/src/main/scala/co/topl/brambl/display/AssetDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.box.{AssetMintingStatement, Value} | ||
import co.topl.brambl.utils.Encoding | ||
import co.topl.brambl.syntax.int128AsBigInt | ||
|
||
trait AssetDisplayOps { | ||
|
||
implicit val assetDisplay: DisplayOps[Value.Asset] = (asset: Value.Asset) => | ||
Seq( | ||
"Asset", | ||
padLabel("GroupId") + asset.groupId.map(gId => gId.display).getOrElse("N/A"), | ||
padLabel("SeriesId") + asset.seriesId.map(sId => sId.display).getOrElse("N/A"), | ||
padLabel("Commitment") + asset.commitment | ||
.map(x => Encoding.encodeToHex(x.toByteArray())) | ||
.getOrElse("No commitment"), | ||
padLabel("Ephemeral-Metadata"), | ||
asset.ephemeralMetadata.map(meta => meta.display).getOrElse("No ephemeral metadata") | ||
).mkString("\n") | ||
|
||
implicit val assetMintingStatementDisplay: DisplayOps[AssetMintingStatement] = (ams: AssetMintingStatement) => | ||
Seq( | ||
padLabel("Group-Token-Utxo") + ams.groupTokenUtxo.display, | ||
padLabel("Series-Token-Utxo") + ams.seriesTokenUtxo.display, | ||
padLabel("Quantity") + (ams.quantity: BigInt).toString, | ||
padLabel("Permanent-Metadata"), | ||
ams.permanentMetadata.map(meta => meta.display).getOrElse("No permanent metadata") | ||
).mkString("\n") | ||
} |
10 changes: 10 additions & 0 deletions
10
brambl-sdk/src/main/scala/co/topl/brambl/display/BlockDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.utils.Encoding | ||
import co.topl.consensus.models.BlockId | ||
|
||
trait BlockDisplayOps { | ||
|
||
implicit val blockIdDisplay: DisplayOps[BlockId] = (blockId: BlockId) => | ||
Encoding.encodeToBase58(blockId.value.toByteArray()) | ||
} |
27 changes: 27 additions & 0 deletions
27
brambl-sdk/src/main/scala/co/topl/brambl/display/GroupDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.{Datum, GroupId, SeriesId} | ||
import co.topl.brambl.utils.Encoding | ||
import co.topl.brambl.models.box.Value | ||
|
||
trait GroupDisplayOps { | ||
implicit val groupIdDisplay: DisplayOps[GroupId] = (id: GroupId) => Encoding.encodeToHex(id.value.toByteArray()) | ||
|
||
implicit val groupPolicyDisplay: DisplayOps[Datum.GroupPolicy] = (gp: Datum.GroupPolicy) => | ||
Seq( | ||
padLabel("Label") + gp.event.label, | ||
padLabel("Registration-Utxo") + gp.event.registrationUtxo.display, | ||
padLabel("Fixed-Series") + displayFixedSeries(gp.event.fixedSeries) | ||
).mkString("\n") | ||
|
||
implicit val groupDisplay: DisplayOps[Value.Group] = (group: Value.Group) => | ||
Seq( | ||
"Group Constructor", | ||
padLabel("Id") + group.groupId.display, | ||
padLabel("Fixed-Series") + displayFixedSeries(group.fixedSeries) | ||
).mkString("\n") | ||
|
||
private def displayFixedSeries(fixedSeries: Option[SeriesId]): String = | ||
fixedSeries.map(sId => sId.display).getOrElse("NO FIXED SERIES") | ||
} |
52 changes: 52 additions & 0 deletions
52
brambl-sdk/src/main/scala/co/topl/brambl/display/SeriesDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.{Datum, SeriesId} | ||
import co.topl.brambl.models.box.{FungibilityType, QuantityDescriptorType} | ||
import co.topl.brambl.utils.Encoding | ||
import co.topl.brambl.models.box.Value | ||
|
||
trait SeriesDisplayOps { | ||
|
||
implicit val seriesIdDisplay: DisplayOps[SeriesId] = (id: SeriesId) => Encoding.encodeToHex(id.value.toByteArray()) | ||
|
||
implicit val fungibilityDisplay: DisplayOps[FungibilityType] = { | ||
case FungibilityType.GROUP_AND_SERIES => "group-and-series" | ||
case FungibilityType.GROUP => "group" | ||
case FungibilityType.SERIES => "series" | ||
case _ => throw new Exception("Unknown fungibility type") // this should not happen | ||
} | ||
|
||
implicit val quantityDescriptorDisplay: DisplayOps[QuantityDescriptorType] = { | ||
case QuantityDescriptorType.LIQUID => "liquid" | ||
case QuantityDescriptorType.ACCUMULATOR => "accumulator" | ||
case QuantityDescriptorType.FRACTIONABLE => "fractionable" | ||
case QuantityDescriptorType.IMMUTABLE => "immutable" | ||
case _ => throw new Exception("Unknown quantity descriptor type") // should not happen | ||
} | ||
|
||
implicit val seriesPolicyDisplay: DisplayOps[Datum.SeriesPolicy] = (sp: Datum.SeriesPolicy) => | ||
Seq( | ||
padLabel("Label") + sp.event.label, | ||
padLabel("Registration-Utxo") + sp.event.registrationUtxo.display, | ||
padLabel("Fungibility") + sp.event.fungibility.display, | ||
padLabel("Quantity-Descriptor") + sp.event.quantityDescriptor.display, | ||
padLabel("Token-Supply") + displayTokenSupply(sp.event.tokenSupply), | ||
padLabel("Permanent-Metadata-Scheme"), | ||
sp.event.permanentMetadataScheme.map(meta => meta.display).getOrElse("No permanent metadata"), | ||
padLabel("Ephemeral-Metadata-Scheme"), | ||
sp.event.ephemeralMetadataScheme.map(meta => meta.display).getOrElse("No ephemeral metadata") | ||
).mkString("\n") | ||
|
||
implicit val seriesDisplay: DisplayOps[Value.Series] = (series: Value.Series) => | ||
Seq( | ||
"Series Constructor", | ||
padLabel("Id") + series.seriesId.display, | ||
padLabel("Fungibility") + series.fungibility.display, | ||
padLabel("Token-Supply") + displayTokenSupply(series.tokenSupply), | ||
padLabel("Quant-Descr.") + series.quantityDescriptor.display | ||
).mkString("\n") | ||
|
||
private def displayTokenSupply(tokenSupply: Option[Int]): String = | ||
tokenSupply.map(_.toString).getOrElse("UNLIMITED") | ||
} |
47 changes: 47 additions & 0 deletions
47
brambl-sdk/src/main/scala/co/topl/brambl/display/StructDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
package co.topl.brambl.display | ||
|
||
import com.google.protobuf.struct.{Struct, Value} | ||
import com.google.protobuf.struct.Value.Kind.{ | ||
BoolValue, | ||
Empty, | ||
ListValue, | ||
NullValue, | ||
NumberValue, | ||
StringValue, | ||
StructValue | ||
} | ||
|
||
trait StructDisplayOps { | ||
private val Indent = 2 | ||
private val InitialIndent = Indent | ||
|
||
implicit val structDisplay: DisplayOps[Struct] = (struct: Struct) => | ||
" " * InitialIndent + display(struct, InitialIndent) | ||
|
||
private def display(struct: Struct, indent: Int): String = | ||
struct.fields.view.keys | ||
.map({ key => | ||
struct.fields(key).kind match { | ||
case StructValue(s) => | ||
s"$key:\n" + " " * (indent + Indent) + s"${display(s, indent + Indent)}" | ||
case ListValue(l) => | ||
s"$key:\n" + l.values | ||
.map(s => " " * (indent + Indent) + s"-${display(s, 0)}") | ||
.mkString("\n") | ||
case _ => s"$key: ${display(struct.fields(key), indent)}" | ||
} | ||
}) | ||
.mkString("\n" + " " * indent) | ||
|
||
private def display(v: Value, indent: Int): String = v match { | ||
case Value(NullValue(_), _) => "null" | ||
case Value(Empty, _) => "empty" | ||
case Value(BoolValue(b), _) => b.toString() | ||
case Value(NumberValue(n), _) => n.toString() | ||
case Value(StringValue(s), _) => s | ||
case Value(ListValue(l), _) => | ||
l.values.map(s => " " * indent + s"- ${display(s, 0)}").mkString("\n") | ||
case Value(StructValue(s), _) => | ||
" " * indent + display(s, indent) | ||
} | ||
} |
28 changes: 28 additions & 0 deletions
28
brambl-sdk/src/main/scala/co/topl/brambl/display/StxoDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.TransactionOutputAddress | ||
import co.topl.brambl.models.transaction.SpentTransactionOutput | ||
import co.topl.brambl.utils.Encoding | ||
import co.topl.genus.services.Txo | ||
|
||
trait StxoDisplayOps { | ||
|
||
implicit val stxoDisplay: DisplayOps[SpentTransactionOutput] = (stxo: SpentTransactionOutput) => | ||
Seq( | ||
padLabel("TxoAddress") + stxo.address.display, | ||
padLabel("Attestation") + "Not implemented", | ||
stxo.value.value.display | ||
).mkString("\n") | ||
|
||
implicit val txoAddressDisplay: DisplayOps[TransactionOutputAddress] = (txoAddress: TransactionOutputAddress) => | ||
s"${Encoding.encodeToBase58(txoAddress.id.value.toByteArray())}#${txoAddress.index}" | ||
|
||
implicit val txoDisplay: DisplayOps[Txo] = (txo: Txo) => | ||
Seq( | ||
padLabel("TxoAddress") + txo.outputAddress.display, | ||
padLabel("LockAddress") + txo.transactionOutput.address.display, | ||
txo.transactionOutput.value.value.display | ||
).mkString("\n") | ||
|
||
} |
44 changes: 44 additions & 0 deletions
44
brambl-sdk/src/main/scala/co/topl/brambl/display/TransactionDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.TransactionId | ||
import co.topl.brambl.models.transaction.IoTransaction | ||
import co.topl.brambl.syntax.ioTransactionAsTransactionSyntaxOps | ||
import co.topl.brambl.utils.Encoding | ||
|
||
trait TransactionDisplayOps { | ||
|
||
implicit val transactionIdDisplay: DisplayOps[TransactionId] = (id: TransactionId) => | ||
Encoding.encodeToBase58(id.value.toByteArray()) | ||
|
||
implicit val transactionDisplay: DisplayOps[IoTransaction] = (tx: IoTransaction) => | ||
s""" | ||
${padLabel("TransactionId")}${tx.transactionId.getOrElse(tx.computeId).display} | ||
|
||
Group Policies | ||
============== | ||
${tx.groupPolicies.map(gp => gp.display).mkString("\n-----------\n")} | ||
|
||
Series Policies | ||
=============== | ||
${tx.seriesPolicies.map(sp => sp.display).mkString("\n-----------\n")} | ||
|
||
Asset Minting Statements | ||
======================== | ||
${tx.mintingStatements.map(ams => ams.display).mkString("\n-----------\n")} | ||
|
||
Inputs | ||
====== | ||
${if (tx.inputs.isEmpty) ("No inputs") | ||
else tx.inputs.map(stxo => stxo.display).mkString("\n-----------\n")} | ||
|
||
Outputs | ||
======= | ||
${if (tx.outputs.isEmpty) ("No outputs") | ||
else tx.outputs.map(utxo => utxo.display).mkString("\n-----------\n")} | ||
|
||
Datum | ||
===== | ||
${padLabel("Value")}${Encoding.encodeToBase58(tx.datum.event.metadata.value.toByteArray())} | ||
""" | ||
} |
19 changes: 19 additions & 0 deletions
19
brambl-sdk/src/main/scala/co/topl/brambl/display/UtxoDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.codecs.AddressCodecs | ||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.LockAddress | ||
import co.topl.brambl.models.transaction.UnspentTransactionOutput | ||
|
||
trait UtxoDisplayOps { | ||
|
||
implicit val utxoDisplay: DisplayOps[UnspentTransactionOutput] = (utxo: UnspentTransactionOutput) => | ||
Seq( | ||
padLabel("LockAddress") + utxo.address.display, | ||
utxo.value.value.display | ||
).mkString("\n") | ||
|
||
implicit val lockAddressDisplay: DisplayOps[LockAddress] = (lockAddress: LockAddress) => | ||
AddressCodecs.encodeAddress(lockAddress) | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
brambl-sdk/src/main/scala/co/topl/brambl/display/ValueDisplayOps.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package co.topl.brambl.display | ||
|
||
import co.topl.brambl.display.DisplayOps.DisplayTOps | ||
import co.topl.brambl.models.box.Value | ||
import co.topl.brambl.models.box.Value.Value._ | ||
import co.topl.brambl.syntax.{int128AsBigInt, valueToQuantitySyntaxOps} | ||
|
||
import scala.util.{Failure, Success, Try} | ||
|
||
trait ValueDisplayOps { | ||
|
||
implicit val valueDisplay: DisplayOps[Value.Value] = (value: Value.Value) => | ||
Seq(typeDisplay(value), quantityDisplay(value)).mkString("\n") | ||
|
||
def typeDisplay(value: Value.Value): String = { | ||
val vType = value match { | ||
case Lvl(_) => "LVL" | ||
case Group(g) => g.display | ||
case Series(s) => s.display | ||
case Asset(a) => a.display | ||
case Topl(_) => "TOPL" | ||
case _ => "Unknown txo type" | ||
} | ||
padLabel("Type") + vType | ||
} | ||
|
||
def quantityDisplay(value: Value.Value): String = { | ||
val quantity = Try { | ||
value.quantity | ||
} match { | ||
case Success(asInt128) => (asInt128: BigInt).toString() | ||
case Failure(_) => "Undefine type" | ||
} | ||
padLabel("Value") + quantity | ||
} | ||
} |
32 changes: 32 additions & 0 deletions
32
brambl-sdk/src/main/scala/co/topl/brambl/display/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package co.topl.brambl | ||
|
||
package object display | ||
extends UtxoDisplayOps | ||
with StxoDisplayOps | ||
with ValueDisplayOps | ||
with StructDisplayOps | ||
with AssetDisplayOps | ||
with GroupDisplayOps | ||
with SeriesDisplayOps | ||
with TransactionDisplayOps | ||
with BlockDisplayOps { | ||
|
||
val LabelLength = 27 | ||
|
||
def padLabel(label: String): String = { | ||
val padding = " " * (LabelLength - label.length).max(0) | ||
s"${label}${padding}: " | ||
} | ||
|
||
trait DisplayOps[T] { | ||
def display(t: T): String | ||
} | ||
|
||
object DisplayOps { | ||
def apply[T](implicit ev: DisplayOps[T]): DisplayOps[T] = ev | ||
|
||
implicit class DisplayTOps[T: DisplayOps](t: T) { | ||
def display: String = DisplayOps[T].display(t) | ||
} | ||
} | ||
} |
Oops, something went wrong.