Hello,
I am new learner to daml. I am having a use case in which I want to implement access control model, As you guys are familiar with the existing daml wallet, There’s a feature, you can send few coins to another party & that party need to accept the transaction. However, I want to give that control to some middle party who can also accept or reject the incoming requests.
please let me know, how can we achieve it in same scenario ?
Hi @Virendra_Solanke
Welcome to the Daml community.
Here’s one way you can model this delegation.
module AssetWithTransferAcceptDelegation where
import Daml.Script
template Asset
with
issuer : Party
owner : Party
amount : Decimal
where
signatory issuer, owner
choice Propose_Transfer : ContractId AssetTransfer
with
recipient : Party
controller owner
do
create AssetTransfer with
asset = this
recipient
transfer_accept_delegate = None
template AssetTransfer
with
asset : Asset
recipient : Party
transfer_accept_delegate : Optional Party
where
signatory (signatory asset)
observer recipient, transfer_accept_delegate
choice AssetTransfer_Accept : ContractId Asset
controller recipient
do
create asset with
owner = recipient
-- This choice provides visibility of the AssetTransfer contract to the delegate
choice AssetTransfer_Add_Delegate : ContractId AssetTransfer
with
delegate : Party
controller recipient
do
create this with
transfer_accept_delegate = Some delegate
-- This template is a role contract providing asset transfer recipient's authority,
-- which is required to create Asset contract in recipient's name
template AssetTransferDelegate
with
delegator : Party
delegate : Party
where
signatory delegator
observer delegate
-- This choice could be consuming or nonconsuming
-- depending on whether the delegation to accept transfer
-- should be valid for only one transfer
-- or whether it should be persistent
choice AssetTransfer_Accept_By_Delegate : ContractId Asset
with
transferCid : ContractId AssetTransfer
controller delegate
do
exercise transferCid AssetTransfer_Accept
test = script do
issuer <- allocateParty "Issuer"
alice <- allocateParty "Alice"
bob <- allocateParty "Bob"
charlie <- allocateParty "Charlie"
-- Issuer creates asset
a <- submit issuer do
createCmd Asset with
issuer
owner = issuer
amount = 10.0
-- Issuer proposes asset transfer to Alice
atp <- submit issuer do
exerciseCmd a Propose_Transfer with recipient = alice
-- Alice accepts the transfer. Now Alice owns the asset.
a <- submit alice do
exerciseCmd atp AssetTransfer_Accept
-- Alice proposes asset transfer to Bob
atp <- submit alice do
exerciseCmd a Propose_Transfer with recipient = bob
-- Bob gives visibility of AssetTransfer contract to Charlie
atp <- submit bob do
exerciseCmd atp AssetTransfer_Add_Delegate with delegate = charlie
-- Bob creates delegation contract, which provides Bob's authority
-- required to create Asset with owner = bob
atd <- submit bob do
createCmd AssetTransferDelegate with
delegator = bob
delegate = charlie
-- Charlie accepts asset transfer proposal on Bob's behalf
a <- submit charlie do
exerciseCmd atd AssetTransfer_Accept_By_Delegate with transferCid = atp
return ()
1 Like
Hi,@a_putkov
Thanks for the solution. I will try to integrate this with front end soon.
Hi, @a_putkov . I have tried given solution. Also I have tried to build the given code . but its giving an error .
so I have question regarding the problem statement I am trying to solve & as follows :-
Can we achieve this by only mentioning extra party as signatory in Asset Template of existing daml sample wallet & then from front end we pass the third party id within payload ?
I don’t see how adding another signatory on the Asset template would be helpful here. The effect of adding another signatory to the Asset template would be the requirement to have that party’s authorization for every creation and archival of an Asset contract. In other words it would complicate the creation and archival of Asset contracts, and it won’t do anything to help with delegation.
Delegation of authority in Daml is achieved through choices and their controllers. By specifying a controller on a choice the signatories on the template delegate their authority to the choice controller. The controller is the party that can exercise the choice, while all actions in the body of the choice carry the authority of the contract’s signatories.
In the Wallet Sample App the acceptance of a transfer proposal results in the creation of an Asset contract, which requires the authority of the owner of the Asset contract being created (i.e. of the recipient of the transfer proposal). To delegate this authority to another party we need a template, where the recipient of the transfer is a signatory and the delegate is the controller on a choice. Neither Asset nor AssetTransfer template satisfies this criteria, which is why the example I provided introduces another template named AssetTransferDelegate.
I assume the errors you experienced came about when you replaced the Asset module in the Wallet Sample App with AssetWithTransferAcceptDelegation module I provided, right? If this is indeed what happened, the compile errors should be expected, since AssetWithTransferAcceptDelegation module modifies the original Asset and AssetTransfer templates, and these modifications need to be reflected in other modules that utilize these templates.
Hi @a_putkov ,
Thanks for the brief on signatory & delegation . I will let u know once I succeed.
Hi @a_putkov ,
Please let me know if this will work . I want some 3rd party might accept or reject incoming request.
module Asset where
data AssetType = AssetType with
issuer: Party
symbol: Text
reference : Optional Text
deriving (Eq, Show)
template Asset with
assetType : AssetType
owner : Party
amount : Decimal
observers : Set Party
where
signatory assetType.issuer, owner
observer observers
ensure (if assetType.fungible then amount>0.0 else (amount==1.0))
choice Propose_Transfer : ContractId AssetTransfer
with
recipient : Party
controller owner
do
create AssetTransfer with
asset = this
recipient
transfer_accept_delegate = None
template AssetTransfer
with
asset : Asset
recipient : Party
transfer_accept_delegate : Optional Party
where
signatory (signatory asset)
observer recipient
ensure (if asset.assetType.fungible then asset.amount>0.0 else (asset.amount==1.0))
choice AssetTransfer_Add_Delegate : ContractId AssetTransfer
with
delegate : Party
controller recipient
do
create this with
transfer_accept_delegate = Some delegate
choice Cancel_Transfer : ContractId Asset
controller asset.owner, transfer_accept_delegate
do
create asset
choice Reject_Transfer : ContractId Asset
controller recipient, transfer_accept_delegate
do
create asset
choice Accept_Transfer : ContractId Asset
controller recipient, asset.assetType.issuer, transfer_accept_delegate
do
create asset with
owner = recipient
observers = Set.empty
template AssetTransferDelegate
with
delegator : Party
delegate : Party
where
signatory delegator
observer delegate
choice AssetTransfer_Accept_By_Delegate : ContractId Asset
with
transferCid : ContractId AssetTransfer
controller delegate
do
exercise transferCid Accept_Transfer
Nope. This won’t work, I’m afraid. When you list multiple parties as controllers of a choice, the authority of all of these parties will be required to exercise the choice. E.g. the exercise of your Accept_Transfer choice on the AssetTransfer template will need to be jointly authorized by the asset issuer, the recipient of the transfer and the delegate. The AssetTransfer_Accept_By_Delegate choice on AssetTransferDelegate template provides the authority of the delegator. If the delegator is the recipient of the transfer and AssetTransfer_Accept_By_Delegate choice is exercised by the delegate, then the exercise of Accept_Transfer choice on AssetTransfer contract that is called from AssetTransfer_Accept_By_Delegate choice will be authorized by the recipient and the delegate. However, the Accept_Transfer choice requires authorization from 3 controllers including the asset issuer. Hence the exercise will fail because of missing authorization from the asset issuer.
so even if we remove transfer_accept_delegate as controller , it will not work in this template ?
could you please suggest what will be the possible solution for this template from wallet reference application ? I am just playing around & looking for possibilities I can try.
Simple use case I want to built in existing wallet reference app is to just show that incoming request in third parties account, so that he can also accept or reject on behalf of some party.
@Virendra_Solanke
If you remove transfer_accept_delegate from the list of controllers of Accept_Transfer choice, then the party provided in transfer_accept_delegate field (supposedly the delegate) will not be able to exercise the choice, which certainly doesn’t help your use case.
I’m not sure I understand the request for an example, as I did provide one (including a test script to demonstrate that it works) earlier on this thread. Does the example I provided not work for you for some reason?
Hi @a_putkov ,
I have tried your example, It works fine, But I am asking for the wallet app which is I am referring currently.
we know whenever some party sends some asset tokens to some other party, the request comes under inbound or outbound, what I am trying to do is, the same request must go to some other party other than who is doing transactions. so that we can allow that third party to accept or reject it.
I hope this time, I am able to explain you the problem I am trying to solve.
@Virendra_Solanke
It’s perfectly possible to implement the workflow you’re interested in in the Wallet Sample App. But it’s not trivial. The example I provided is one step towards the complete implementation, but it’s far from the full solution. It modifies the original implementation in the Wallet Sample App of Asset & AssetTransfer templates and introduces a new AssetTransferDelegate template. These changes have a knock-on effect on other parts of the app, namely on the templates in the Account module, the triggers and the UI code. All these pieces will need to be modified to reflect the changes in the Asset module. And then an additional workflow will need to be created in the UI to allow the recipient of the transfer to select a delegate.
Does this make sense?
Yes @a_putkov it make sense now.
Thank you for the brief again.