I have an interface defined as below:
data VAsset = VAsset with
issuer : Party
owner : Party
obs: [Party]
quantity: Decimal
assetType: Text
interface IAsset where
viewtype VAsset
setOwner: Party -> IAsset
setObs: [Party] -> IAsset
setQuantity : Decimal -> IAsset
I am trying to use it in a template as given below:
template TransferProposal --this gives error
with
newOwner: Party
asset: IAsset
where
signatory (signatory asset)
choice AcceptProposal: ContractId IAsset
controller newOwner
do
create (fromInterface @VAsset asset) with
owner = newOwner
Two questions:
- I get an error:
No instance for (Show IAsset)
arising from the second field of ‘TransferProposal’ (type ‘IAsset’)
Possible fix:
use a standalone 'deriving instance' declaration,
so you can specify the instance context yourself
• When deriving the instance for (Show TransferProposal)typecheck
I tried making VAsset deriving (Eq, Show) but that doesn’t help.
- Is the create… statement written above the right way to create an asset without knowing which asset type it is? Only owner is changed.
Thanks!!
An interface can only be used to abstract over the representation of whole contracts on the ledger, providing (one way!) access to each one’s view, and of course abstract choice signatures. It cannot be used to abstract over arbitrary data structures, which is what the asset
variable as used here must be.
This is because there is no way to make an interface serializable according to the specific definition linked here. The (Eq, Show)
test is usually just a quick sanity check as a shortcut to this, but even if you try to hack around the system, you won’t be allowed to do it:
error type checking template Main.TransferProposal :
expected serializable type:
* reason: template argument
* found: Main:TransferProposal
* problem:
unserializable data type Main:TransferProposal [Daml-LF typechecker]
You cannot create a contract without knowing what template type it has. Once it has been created, you can interact with its choices, its view, and optionally convert to a template (note that @VAsset
cannot possibly be a fromInterface
argument because it is not a template), but it must be created concretely.
To abstract over create
template, that selection should be abstracted behind an interface choice; if you have a ContractId
of that interface, you can then invoke all sorts of choices whose actual concrete resulting templates depend on the implementer of the interface.
Thanks @Stephen
The error goes away if I change the asset type to ContractId IAsset
template TransferProposal
with
newOwner: Party
asset: ContractId IAsset
...