mirror of
https://github.com/digital-asset/daml.git
synced 2024-09-20 01:07:18 +03:00
LF: Exhaustive test for valueTranslator. (#10927)
* LF: Exhaustive test for value translator. CHANGELOG_BEGIN CHANGELOG_END * cosmetic
This commit is contained in:
parent
409c0b4f60
commit
ac02dbdeb9
@ -79,8 +79,8 @@ private[engine] final class ValueTranslator(
|
||||
throw Error.Preprocessing.ValueNesting(value)
|
||||
} else {
|
||||
val newNesting = nesting + 1
|
||||
def typeError(msg: String = s"mismatching type: $ty and value: $value0") =
|
||||
throw Error.Preprocessing.TypeMismatch(ty, value0, msg)
|
||||
def typeError(msg: String = s"mismatching type: ${ty0.pretty} and value: $value0") =
|
||||
throw Error.Preprocessing.TypeMismatch(ty0, value0, msg)
|
||||
val (ty1, tyArgs) = AstUtil.destructApp(ty0)
|
||||
ty1 match {
|
||||
case TBuiltin(bt) =>
|
||||
|
@ -27,7 +27,7 @@ class CommandPreprocessorSpec
|
||||
import com.daml.lf.transaction.test.TransactionBuilder.Implicits.{defaultPackageId => _, _}
|
||||
private implicit val defaultPackageId = defaultParserParameters.defaultPackageId
|
||||
|
||||
lazy val pkg =
|
||||
private[this] val pkg =
|
||||
p"""
|
||||
module Mod {
|
||||
|
||||
@ -71,7 +71,7 @@ class CommandPreprocessorSpec
|
||||
private[this] val compiledPackage = ConcurrentCompiledPackages()
|
||||
assert(compiledPackage.addPackage(defaultPackageId, pkg) == ResultDone.Unit)
|
||||
|
||||
val valueParties = ValueList(FrontStack(ValueParty("Alice")))
|
||||
private[this] val valueParties = ValueList(FrontStack(ValueParty("Alice")))
|
||||
|
||||
"preprocessCommand" should {
|
||||
|
||||
|
@ -180,278 +180,6 @@ class EngineTest
|
||||
}
|
||||
|
||||
"command translation" should {
|
||||
"translate create commands argument including labels" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:Simple")
|
||||
val command =
|
||||
CreateCommand(id, ValueRecord(Some(id), ImmArray((Some[Name]("p"), ValueParty(party)))))
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
|
||||
}
|
||||
|
||||
"translate create commands argument without labels" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:Simple")
|
||||
val command =
|
||||
CreateCommand(id, ValueRecord(Some(id), ImmArray((None, ValueParty(party)))))
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"not translate create commands argument wrong label" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:Simple")
|
||||
val command =
|
||||
CreateCommand(
|
||||
id,
|
||||
ValueRecord(Some(id), ImmArray((Some[Name]("this_is_not_the_one"), ValueParty(party)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) { case Left(Error.Preprocessing(error)) =>
|
||||
error shouldBe a[Error.Preprocessing.TypeMismatch]
|
||||
}
|
||||
}
|
||||
|
||||
"translate exercise commands argument including labels" in {
|
||||
val originalCoid = toContractId("BasicTests:CallablePayout:1")
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command = ExerciseCommand(
|
||||
templateId,
|
||||
originalCoid,
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((Some[Name]("newReceiver"), ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"translate exercise commands argument without labels" in {
|
||||
val originalCoid = toContractId("BasicTests:CallablePayout:1")
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command = ExerciseCommand(
|
||||
templateId,
|
||||
originalCoid,
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((None, ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"translate exercise-by-key commands with argument with labels" in {
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:WithKey")
|
||||
val command = ExerciseByKeyCommand(
|
||||
templateId,
|
||||
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
|
||||
"SumToK",
|
||||
ValueRecord(None, ImmArray((Some[Name]("n"), ValueInt64(5)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"translate exercise-by-key commands with argument without labels" in {
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:WithKey")
|
||||
val command = ExerciseByKeyCommand(
|
||||
templateId,
|
||||
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
|
||||
"SumToK",
|
||||
ValueRecord(None, ImmArray((None, ValueInt64(5)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"not translate exercise-by-key commands with argument with wrong labels" in {
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:WithKey")
|
||||
val command = ExerciseByKeyCommand(
|
||||
templateId,
|
||||
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
|
||||
"SumToK",
|
||||
ValueRecord(None, ImmArray((Some[Name]("WRONG"), ValueInt64(5)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) { case Left(Error.Preprocessing(error)) =>
|
||||
error shouldBe a[Error.Preprocessing.TypeMismatch]
|
||||
error.message should startWith("Missing record field 'n' for record")
|
||||
}
|
||||
}
|
||||
|
||||
"not translate exercise-by-key commands if the template specifies no key" in {
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command = ExerciseByKeyCommand(
|
||||
templateId,
|
||||
ValueRecord(None, ImmArray((None, ValueParty(alice)), (None, ValueInt64(42)))),
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((None, ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) {
|
||||
case Left(Error.Preprocessing(Error.Preprocessing.Lookup(language.LookupError(ref, _)))) =>
|
||||
ref shouldBe a[language.Reference.TemplateKey]
|
||||
}
|
||||
}
|
||||
|
||||
"not translate exercise-by-key commands if the given key does not match the type specified in the template" in {
|
||||
val templateId = Identifier(basicTestsPkgId, "BasicTests:WithKey")
|
||||
val command = ExerciseByKeyCommand(
|
||||
templateId,
|
||||
ValueRecord(None, ImmArray((None, ValueInt64(42)), (None, ValueInt64(42)))),
|
||||
"SumToK",
|
||||
ValueRecord(None, ImmArray((None, ValueInt64(5)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) { case Left(Error.Preprocessing(error)) =>
|
||||
error shouldBe a[Error.Preprocessing.TypeMismatch]
|
||||
}
|
||||
}
|
||||
|
||||
"translate create-and-exercise commands argument including labels" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command =
|
||||
CreateAndExerciseCommand(
|
||||
id,
|
||||
ValueRecord(
|
||||
Some(Identifier(basicTestsPkgId, "BasicTests:CallablePayout")),
|
||||
ImmArray(
|
||||
(Some[Ref.Name]("giver"), ValueParty(clara)),
|
||||
(Some[Ref.Name]("receiver"), ValueParty(clara)),
|
||||
),
|
||||
),
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((Some[Name]("newReceiver"), ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
|
||||
}
|
||||
|
||||
"translate create-and-exercise commands argument without labels" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command =
|
||||
CreateAndExerciseCommand(
|
||||
id,
|
||||
ValueRecord(
|
||||
Some(Identifier(basicTestsPkgId, "BasicTests:CallablePayout")),
|
||||
ImmArray((None, ValueParty(clara)), (None, ValueParty(clara))),
|
||||
),
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((None, ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
res shouldBe a[Right[_, _]]
|
||||
}
|
||||
|
||||
"not translate create-and-exercise commands argument wrong label in create arguments" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command =
|
||||
CreateAndExerciseCommand(
|
||||
id,
|
||||
ValueRecord(
|
||||
Some(Identifier(basicTestsPkgId, "BasicTests:CallablePayout")),
|
||||
ImmArray(
|
||||
(None, ValueParty(clara)),
|
||||
(Some[Ref.Name]("this_is_not_the_one"), ValueParty(clara)),
|
||||
),
|
||||
),
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((None, ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) { case Left(Error.Preprocessing(error)) =>
|
||||
error shouldBe a[Error.Preprocessing.TypeMismatch]
|
||||
}
|
||||
}
|
||||
|
||||
"not translate create-and-exercise commands argument wrong label in choice arguments" in {
|
||||
val id = Identifier(basicTestsPkgId, "BasicTests:CallablePayout")
|
||||
val command =
|
||||
CreateAndExerciseCommand(
|
||||
id,
|
||||
ValueRecord(
|
||||
Some(Identifier(basicTestsPkgId, "BasicTests:CallablePayout")),
|
||||
ImmArray((None, ValueParty(clara)), (None, ValueParty(clara))),
|
||||
),
|
||||
"Transfer",
|
||||
ValueRecord(None, ImmArray((Some[Name]("this_is_not_the_one"), ValueParty(clara)))),
|
||||
)
|
||||
|
||||
val res = preprocessor
|
||||
.preprocessCommands(ImmArray(command))
|
||||
.consume(lookupContract, lookupPackage, lookupKey)
|
||||
inside(res) { case Left(Error.Preprocessing(error)) =>
|
||||
error shouldBe a[Error.Preprocessing.TypeMismatch]
|
||||
}
|
||||
}
|
||||
|
||||
"translate Optional values" in {
|
||||
val (optionalPkgId, _, allOptionalPackages) =
|
||||
loadPackage("daml-lf/tests/Optional.dar")
|
||||
|
||||
val translator =
|
||||
new preprocessing.Preprocessor(
|
||||
ConcurrentCompiledPackages(suffixLenientEngine.config.getCompilerConfig)
|
||||
)
|
||||
|
||||
val id = Identifier(optionalPkgId, "Optional:Rec")
|
||||
val someValue =
|
||||
ValueRecord(
|
||||
Some(id),
|
||||
ImmArray(Some[Name]("recField") -> ValueOptional(Some(ValueText("foo")))),
|
||||
)
|
||||
val noneValue =
|
||||
ValueRecord(Some(id), ImmArray(Some[Name]("recField") -> ValueOptional(None)))
|
||||
val typ = TTyConApp(id, ImmArray.Empty)
|
||||
|
||||
translator
|
||||
.translateValue(typ, someValue)
|
||||
.consume(lookupContract, allOptionalPackages.get, lookupKey) shouldEqual
|
||||
Right(SRecord(id, ImmArray("recField"), ArrayList(SOptional(Some(SText("foo"))))))
|
||||
|
||||
translator
|
||||
.translateValue(typ, noneValue)
|
||||
.consume(lookupContract, allOptionalPackages.get, lookupKey) shouldEqual
|
||||
Right(SRecord(id, ImmArray("recField"), ArrayList(SOptional(None))))
|
||||
|
||||
}
|
||||
|
||||
"returns correct error when resuming" in {
|
||||
val translator =
|
||||
new preprocessing.Preprocessor(
|
||||
|
@ -11,39 +11,47 @@ import com.daml.lf.language.Util._
|
||||
import com.daml.lf.speedy.SValue._
|
||||
import com.daml.lf.value.Value
|
||||
import com.daml.lf.value.Value._
|
||||
import org.scalatest.Inside
|
||||
import org.scalatest.matchers.should.Matchers
|
||||
import org.scalatest.prop.TableDrivenPropertyChecks
|
||||
import org.scalatest.wordspec.AnyWordSpec
|
||||
|
||||
import scala.util.{Failure, Success, Try}
|
||||
|
||||
class ValueTranslatorSpec extends AnyWordSpec with Matchers with TableDrivenPropertyChecks {
|
||||
class ValueTranslatorSpec
|
||||
extends AnyWordSpec
|
||||
with Inside
|
||||
with Matchers
|
||||
with TableDrivenPropertyChecks {
|
||||
|
||||
import Preprocessor.ArrayList
|
||||
import com.daml.lf.testing.parser.Implicits._
|
||||
import com.daml.lf.transaction.test.TransactionBuilder.Implicits.{defaultPackageId => _, _}
|
||||
private implicit val defaultPackageId = defaultParserParameters.defaultPackageId
|
||||
private[this] implicit val defaultPackageId: Ref.PackageId =
|
||||
defaultParserParameters.defaultPackageId
|
||||
|
||||
val aCid =
|
||||
private[this] val aCid =
|
||||
ContractId.V1.assertBuild(
|
||||
crypto.Hash.hashPrivateKey("a Contract ID"),
|
||||
Bytes.assertFromString("00"),
|
||||
)
|
||||
|
||||
lazy val pkg =
|
||||
private[this] val pkg =
|
||||
p"""
|
||||
module Mod {
|
||||
|
||||
|
||||
record @serializable Tuple (a: *) (b: *) = { x: a, y: b };
|
||||
record @serializable Record = { field : Int64 };
|
||||
variant @serializable Either (a: *) (b: *) = Left : a | Right : b;
|
||||
enum Enum = value1 | value2;
|
||||
enum Color = red | green | blue;
|
||||
|
||||
record Tricky (b: * -> *) = { x : b Unit };
|
||||
|
||||
record MyCons = { head : Int64, tail: Mod:MyList };
|
||||
variant MyList = MyNil : Unit | MyCons: Mod:MyCons ;
|
||||
|
||||
record @serializable RecordRef = { owner: Party, cid: (ContractId Mod:Record) };
|
||||
record @serializable Template = { field : Int64 };
|
||||
record @serializable TemplateRef = { owner: Party, cid: (ContractId Mod:Template) };
|
||||
|
||||
}
|
||||
"""
|
||||
@ -85,7 +93,7 @@ class ValueTranslatorSpec extends AnyWordSpec with Matchers with TableDrivenProp
|
||||
// ValueNumeric(Numeric.assertFromString("9.000000000")),
|
||||
(TParty, ValueParty("Alice"), SParty("Alice")),
|
||||
(
|
||||
TContractId(t"Mod:Record"),
|
||||
TContractId(t"Mod:Template"),
|
||||
ValueContractId(aCid),
|
||||
SContractId(aCid),
|
||||
),
|
||||
@ -106,16 +114,16 @@ class ValueTranslatorSpec extends AnyWordSpec with Matchers with TableDrivenProp
|
||||
),
|
||||
(TOptional(TText), ValueOptional(Some(ValueText("text"))), SOptional(Some(SText("text")))),
|
||||
(
|
||||
t"Mod:Record",
|
||||
ValueRecord("", ImmArray("field" -> ValueInt64(33))),
|
||||
SRecord("Mod:Record", ImmArray("field"), ArrayList(SInt64(33))),
|
||||
t"Mod:Tuple Int64 Text",
|
||||
ValueRecord("", ImmArray("x" -> ValueInt64(33), "y" -> ValueText("a"))),
|
||||
SRecord("Mod:Tuple", ImmArray("x", "y"), ArrayList(SInt64(33), SText("a"))),
|
||||
),
|
||||
(
|
||||
t"Mod:Either Text Int64",
|
||||
ValueVariant("", "Left", ValueText("some test")),
|
||||
SVariant("Mod:Either", "Left", 0, SText("some test")),
|
||||
t"Mod:Either Int64 Text",
|
||||
ValueVariant("", "Right", ValueText("some test")),
|
||||
SVariant("Mod:Either", "Right", 1, SText("some test")),
|
||||
),
|
||||
(Ast.TTyCon("Mod:Enum"), ValueEnum("", "value1"), SEnum("Mod:Enum", "value1", 0)),
|
||||
(Ast.TTyCon("Mod:Color"), ValueEnum("", "blue"), SEnum("Mod:Color", "blue", 2)),
|
||||
(
|
||||
Ast.TApp(Ast.TTyCon("Mod:Tricky"), Ast.TBuiltin(Ast.BTList)),
|
||||
ValueRecord("", ImmArray("" -> ValueNil)),
|
||||
@ -125,7 +133,61 @@ class ValueTranslatorSpec extends AnyWordSpec with Matchers with TableDrivenProp
|
||||
|
||||
"succeeds on well type values" in {
|
||||
forAll(testCases) { (typ, value, svalue) =>
|
||||
unsafeTranslateValue(typ, value) shouldBe svalue
|
||||
Try(unsafeTranslateValue(typ, value)) shouldBe Success(svalue)
|
||||
}
|
||||
}
|
||||
|
||||
"handle different representation of the same record" in {
|
||||
val typ = t"Mod:Tuple Int64 Text"
|
||||
val testCases = Table(
|
||||
"record",
|
||||
ValueRecord("Mod:Tuple", ImmArray("x" -> ValueInt64(33), "y" -> ValueText("a"))),
|
||||
ValueRecord("Mod:Tuple", ImmArray("y" -> ValueText("a"), "x" -> ValueInt64(33))),
|
||||
ValueRecord("", ImmArray("x" -> ValueInt64(33), "y" -> ValueText("a"))),
|
||||
ValueRecord("", ImmArray("" -> ValueInt64(33), "" -> ValueText("a"))),
|
||||
)
|
||||
val svalue = SRecord("Mod:Tuple", ImmArray("x", "y"), ArrayList(SInt64(33), SText("a")))
|
||||
|
||||
forEvery(testCases)(testCase =>
|
||||
Try(unsafeTranslateValue(typ, testCase)) shouldBe Success(svalue)
|
||||
)
|
||||
}
|
||||
|
||||
"handle different representation of the same variant" in {
|
||||
val typ = t"Mod:Either Text Int64"
|
||||
val testCases = Table(
|
||||
"variant",
|
||||
ValueVariant("Mod:Either", "Left", ValueText("some test")),
|
||||
ValueVariant("", "Left", ValueText("some test")),
|
||||
)
|
||||
val svalue = SVariant("Mod:Either", "Left", 0, SText("some test"))
|
||||
|
||||
forEvery(testCases)(value => Try(unsafeTranslateValue(typ, value)) shouldBe Success(svalue))
|
||||
}
|
||||
|
||||
"handle different representation of the same enum" in {
|
||||
val typ = t"Mod:Color"
|
||||
val testCases = Table("enum", ValueEnum("Mod:Color", "green"), ValueEnum("", "green"))
|
||||
val svalue = SEnum("Mod:Color", "green", 1)
|
||||
forEvery(testCases)(value => Try(unsafeTranslateValue(typ, value)) shouldBe Success(svalue))
|
||||
}
|
||||
|
||||
"return proper mismatch error" in {
|
||||
val res = Try(
|
||||
unsafeTranslateValue(
|
||||
t"Mod:Tuple Int64 Text",
|
||||
ValueRecord(
|
||||
"",
|
||||
ImmArray(
|
||||
"x" -> ValueInt64(33),
|
||||
"y" -> ValueParty("Alice"), // Here the field has type Party instead of Text
|
||||
),
|
||||
),
|
||||
)
|
||||
)
|
||||
inside(res) { case Failure(Error.Preprocessing.TypeMismatch(typ, value, _)) =>
|
||||
typ shouldBe t"Text"
|
||||
value shouldBe ValueParty("Alice")
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,17 +223,17 @@ class ValueTranslatorSpec extends AnyWordSpec with Matchers with TableDrivenProp
|
||||
val cid = ValueContractId(culprit)
|
||||
Table[Ast.Type, Value](
|
||||
("type" -> "value"),
|
||||
t"ContractId Mod:Record" -> cid,
|
||||
TList(t"ContractId Mod:Record") -> ValueList(FrontStack(cid)),
|
||||
TTextMap(t"ContractId Mod:Record") -> ValueTextMap(SortedLookupList(Map("0" -> cid))),
|
||||
TGenMap(TInt64, t"ContractId Mod:Record") -> ValueGenMap(ImmArray(ValueInt64(1) -> cid)),
|
||||
TGenMap(t"ContractId Mod:Record", TInt64) -> ValueGenMap(ImmArray(cid -> ValueInt64(0))),
|
||||
TOptional(t"ContractId Mod:Record") -> ValueOptional(Some(cid)),
|
||||
Ast.TTyCon("Mod:RecordRef") -> ValueRecord(
|
||||
t"ContractId Mod:Template" -> cid,
|
||||
TList(t"ContractId Mod:Template") -> ValueList(FrontStack(cid)),
|
||||
TTextMap(t"ContractId Mod:Template") -> ValueTextMap(SortedLookupList(Map("0" -> cid))),
|
||||
TGenMap(TInt64, t"ContractId Mod:Template") -> ValueGenMap(ImmArray(ValueInt64(1) -> cid)),
|
||||
TGenMap(t"ContractId Mod:Template", TInt64) -> ValueGenMap(ImmArray(cid -> ValueInt64(0))),
|
||||
TOptional(t"ContractId Mod:Template") -> ValueOptional(Some(cid)),
|
||||
t"Mod:TemplateRef" -> ValueRecord(
|
||||
"",
|
||||
ImmArray("" -> ValueParty("Alice"), "" -> cid),
|
||||
),
|
||||
TTyConApp("Mod:Either", ImmArray(t"ContractId Mod:Record", TInt64)) -> ValueVariant(
|
||||
TTyConApp("Mod:Either", ImmArray(t"ContractId Mod:Template", TInt64)) -> ValueVariant(
|
||||
"",
|
||||
"Left",
|
||||
cid,
|
||||
|
Loading…
Reference in New Issue
Block a user