DAML: Create a template in scenario requiring a ContractId as input and exercise a choice automatically after submit - daml

I have 2 questions regarding DAML the possibility of automated choices and scenario.
I have this template that requires the input of a ContractId:
template Create_Creation
with
current_login : Party
artist : Party
title : Text
votingRight : Set Party
observers_list_id : ContractId Observers
where
signatory current_login
I need to create some of these templates in scenario, but am unable to specify a ContractId (like #0:0), giving me errors such as: Couldn't match expected type 'ContractId Observers' with actual type 'Text' Is it possible to specify a ContractId in scenario?
Next, in the above template I have a choice defined called Load_all_creation_observers that creates a template Creation and loads the observers specified in template Observers into it as observers:
choice Load_all_creation_observers : ContractId Creation
controller current_login
do
observers_list <- fetch observers_list_id
create Creation with created_by = current_login; artist = artist; title = title;
votingRight = votingRight; observers_list_id = observers_list_id; observers = observers_list.observers
template Observers
with
superuser : Party
observers : Set Party
where
signatory superuser
observer observers
As the code stands now, when a user creates a Create_Creation template he is required to perform the Load_all_creation_observers choice to create the Creation template with all the observers loaded into it. Is it possible to perform this choice automatically when a user submits the Create_Creation template? or maybe not make it a choice at all and define it as automated functionality like you would do in normal programming languages (if statements). You can only seem to define do functions in choices.

Given that the question about contract ids has already been answered, I’ll focus on your second question.
You cannot execute a choice automatically (you could have some off-ledger automation, e.g. a DAML trigger that does that but you don’t get any atomicity guarantees in that case). The way I would solve this problem is to define a new template with a single choice and then call that choice using CreateAndExercise on the ledger API. This is pretty much equivalent to defining a top-level function. For your example this would look something like the following
template CreateCreationTemplate
with
p : Party
where
signatory p
choice CreateCreation : ContractId Creation
with
observers_list_id : ContractId Observers
artist : Party
title : Text
votingRight : Set Party
do observers_list <- fetch observers_list_id
create Creation with
created_by = p
artist = artist
title = title
votingRight = votingRight
observers_list_id = observers_list_id
observers = observers_list.observers
You could have some of the fields of the choice as fields of a template but as a general guideline, I tend to only have the party as a field of the template when emulating top-level functions.
Depending on your usage, it is also possible to have a single “factory” template with a non-consuming CreateCreation choice.

In a scenario, the only contracts that exist on the ledger are those that have been created thus far in that scenario. So if there is an Observers contractId an Observers contract must have been created at some previous point in the scenario.
ContractIds are opaque and definitely not predictable, so it makes no sense to think of a contract-id literal. Instead, when the contract is created, bind the resulting id at that point. Ie.
test = scenario do
su <- getParty "Super User"
obsId <- su submit create Observers with ...
p1 <- getParty "Party 1"
ccId <- p1 submit create Create_Creation with ...; observers_list_id = obsId

Related

Is it possible to restrict a template to be created only once per day

Is it possible to define a template Daily, which can only be created once per day in the sense that if Alice creates one, Bob no longer can, and if Bob creates one, Alice no longer can?
When asking about constraints like "one per day" in DAML, one has to think about the scope of that constraint and who guarantees it.
The simplest possible template in DAML is
template Daily
with
holder : Party
where
signatory holder
An instance of this template is only known to holder. There is no party, or set of parties that could ensure that there is only one such contract instance between Alice and Bob. In certain ledger topologies, Alice and Bob may not even know about each other, nor is there any party that knows about both.
A set of parties that guarantees the uniqueness is needed:
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
...
The uniqueness guarantors need to be able to enable or block the creation of a Daily. In other words, they need to be signatories.
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
where
signatory holder, uniquenessGuarantors
Now the easiest way to guarantee any sort of uniqueness in DAML is by using contract keys. Since we want one per day, we need a Date field.
template Daily
with
holder : Party
uniquenessGuarantors : [Party]
date : Date
where
signatory holder, uniquenessGuarantors
key (uniquenessGuarantors, date) : ([Party], Date)
maintainer key._1
What this says is that there is a unique copy of Daily for each key, and the guarantors in key._1 are responsible for making it so.
Finally you need a mechanism for actually creating these things, a sort of DailyFactory provided by the guarantors. That factory can also take care of making sure that date is always set to the current date on the ledger.
template DailyFactory
with
uniquenessGuarantors : [Party]
holder : Party
where
signatory uniquenessGuarantors
controller holder can
nonconsuming FabricateDaily
: ContractId Daily
do
now <- getTime
let date = toDateUTC now
create Daily with ..
A simple test shows how it works, with uniqueness being guaranteed by a single party Charlie:
test_daily = scenario do
[alice, bob, charlie] <- mapA getParty ["Alice", "Bob", "Charlie"]
fAlice <- submit charlie do
create DailyFactory with
holder = alice
uniquenessGuarantors = [charlie]
fBob <- submit charlie do
create DailyFactory with
holder = bob
uniquenessGuarantors = [charlie]
-- Alice can get hold of a `Daily`
submit alice do
exercise fAlice FabricateDaily
-- Neither can create a second
submitMustFail alice do
exercise fAlice FabricateDaily
submitMustFail bob do
exercise fBob FabricateDaily
-- The next day bob can create one
pass (days 1)
submit bob do
exercise fBob FabricateDaily
-- But neither can create a second
submitMustFail alice do
exercise fAlice FabricateDaily
submitMustFail bob do
exercise fBob FabricateDaily
Note that in terms of privacy, Alice and Bob don't know about each other or the other's Daily or DailyFactory, but the uniquenessGuarantors know all parties for which uniqueness is maintained, and know of all Daily instances for which they guarantee uniqueness. They have to!
To run the above snippets, you need to import DA.Time and DA.Date.
Beware that getTime returns UTC - and consequently the code would guarantee uniqueness, one per day, according to UTC, but not for example according to local calendar (which could be, say, Auckland NZ).

In DAML, what to return when a choice could lead to different new contracts to be created

In DAML, if I have a choice called submit and it could lead to new contract approvedRequest or rejectedRequest. How should I manage the return value in the choice?
template Request
with
content : Text
anyone : Party
where
signatory anyone
--what to return ? ApprovedRequest or RejectedRequest
controller anyone can
Submit : ContractId ApprovedRequest
do
-- passed all the checks and approved
create ApprovedRequest with request = Request
Perhaps Maybe (ContractId ApprovedRequest) will work here? Alternatively, perhaps Either (ContractId RejectedRequest, ContractId ApprovedRequest)?

textX: How to generate object names with ObjectProcessors?

I have a simple example model where I would like to generate names for the objects of the Position rule that were not given a name with as <NAME>. This is needed so that I can find them later with the built-in FQN scope provider.
My idea would be to do this in the position_name_generator object processor but that will be only be called after the whole model is parsed. I don´t really understand the reason for that, since by the time I would need a Position object in the Project, the objects are already created, still the object processor will not be called.
Another idea would be to do this in a custom scope provider for Position.location which would then first do the name generation and then use the built-in FQN to find the Location object. Although this would work, I consider this hacky and I would prefer to avoid it.
What would be the textX way of solving this issue?
(Please take into account that this is only a small example. In reality a similar functionality is required for a rather big and complex model. To change this behaviour with the generated names is not possible since it is a requirement.)
import textx
MyLanguage = """
Model
: (locations+=Location)*
(employees+=Employee)*
(positions+=Position)*
(projects+=Project)*
;
Project
: 'project' name=ID
('{'
('use' use=[Position])*
'}')?
;
Position
: 'define' 'position' employee=[Employee|FQN] '->' location=[Location|FQN] ('as' name=ID)?
;
Employee
: 'employee' name=ID
;
Location
: 'location' name=ID
( '{'
(sub_location+=Location)+
'}')?
;
FQN
: ID('.' ID)*
;
Comment:
/\/\/.*$/
;
"""
MyCode = """
location Building
{
location Entrance
location Exit
}
employee Hans
employee Juergen
// Shall be referred to with the given name: "EntranceGuy"
define position Hans->Building.Entrance as EntranceGuy
// Shall be referred to with the autogenerated name: <Employee>"At"<LastLocation>
define position Juergen->Building.Exit
project SecurityProject
{
use EntranceGuy
use JuergenAtExit
}
"""
def position_name_generator(obj):
if "" == obj.name:
obj.name = obj.employee.name + "At" + obj.location.name
def main():
meta_model = textx.metamodel_from_str(MyLanguage)
meta_model.register_scope_providers({
"Position.location": textx.scoping.providers.FQN(),
})
meta_model.register_obj_processors({
"Position": position_name_generator,
})
model = meta_model.model_from_str(MyCode)
assert model, "Could not create model..."
if "__main__" == __name__:
main()
What is the textx way to solve this...
The use case you describe is to define the name of an object based on other model elements, including a reference to other model elements. This is currently not part of any test and use cases included in our test suite and the textx docu.
Object processors are executed at defined stages during model construction (see http://textx.github.io/textX/stable/scoping/#using-the-scope-provider-to-modify-a-model). In the described setup they are executed after reference resolution. Since the name to be defined/deduced itself is required for reference resolution, object processors cannot be used here (even if we allow to control when object processors are executed, before or after scope resolution, the described setup still will not work).
Given the dynamics of model loading (see http://textx.github.io/textX/stable/scoping/#using-the-scope-provider-to-modify-a-model), the solution is located within a scope provider (as you suggested). Here, we allow to control the order of reference resolution, such that references to the object being named by a custom procedure are postponed, until references required to deduce/define the name resolved.
Possible workaround
A preliminary sketch of how your use case can be solved is discussed in a https://github.com/textX/textX/pull/194 (with an attached issue https://github.com/textX/textX/issues/193). This textx PR contains a version of scoping.py you could probably use for your project (just copy and rename the module). A full-fledged solution could be part of the textx TEP-001, where we plan to make scoping more controllable to the end-user.
Playing around with this absolutely interesting issue revealed new aspects to me for the textx framework.
names dependent on model contents (involving unresolved references). This name resolution, which can be Postponed (in the referenced PR, see below), in terms of our reference resolution logic.
Even more interesting are the consequences of that: What happens to references pointing to locations, where unresolved names are found? Here, we must postpone the reference resolution process, because we cannot know if the name might match when resolved...
Your example is included: https://github.com/textX/textX/blob/analysis/issue193/tests/functional/test_scoping/test_name_resolver/test_issue193_auto_name.py

RXSwift eventlistener

I´m kind of new to the reactive pattern and now I have my first bigger question.
I have done a few asychronous requests in the reactive way. But what I wan´t to do now is a "Eventlistener".
I have a Session object, at the moment I have an SessionEventListener protocol. The Session has a list of listeners and informs all of them about a successfull login and an logout. This Listeners can subscribe and unsubscribe. This thing I want to create reactive now.
How would you do that?
My Idea is to define a BehaviourSubject:
public let loginEventBehaviourSubject = BehaviorSubject(value: true)
now I can send onNext true if the session logged in, and false if it was logged out:
loginEventBehaviourSubject.onNext(true) // on login
loginEventBehaviourSubject.onNext(false) // on logout
And my "listeners" can subscribe to it.
But I would prefere to have subjects for every event:
public let loginEventBehaviourSubject = BehaviorSubject(value: )
public let logoutEventBehaviourSubject = BehaviorSubject(value: )
But then I wouldn´t need the bool. Can I make a kind of "empty" Subject, that only fire "events" without submitting really data.
And then my last question:
Why do I have to add an instance to the initializer of the Subject. Why can´t I create it like: BehaviourSubject<Bool>()?
You need to give an initial value to behavior subject because of it's API. Indeed, it defines BehaviorSubject<T>.value() method, which returns a T. And it would not make sense to call value without a proper initial value. In the presented case, I think PublishSubject is a better representation of the task at hand. You can find more documentation on the available kinds of subjects on the reactivex website.
If you are only interested in the .next event of your subjects, you can do let loginSubject = PublishSubject<Void>() (using behavior subject, you could have written BehaviorSubject<Void>(value: ())) and will the be able to call loginSubject.onNext().
Note though that using any subject is often an anti-pattern. Indeed, subject are most of the time intended to bridge from the imperative to the reactive world and you can very often create things like loginEventObservable as a combination of other observables. For more information on this, I recommend reading To Use Subject Or Not To Use Subject?. It is written using the .Net implementation of Rx, but the theory stays the same.

Global model in spine.js application

I have web application written with Spine.js. It has 2 language translations. I want to store current application's translation in Spine Model.
My model:
class Translation extends Spine.Model
#configure "Translation", "lang"
#getLang: ->
Translation.all()
module.exports = Translation
I have function which changes translation in application and i save new translation to the model in this function:
changeLang: (locale) ->
lang = Translation.create({lang: locale})
lang.save()
But when i try to fetch data from Translation model from another controller i get empty result:
Translation = require("models/translation")
...
alert(Translation.getLang())
I got empty alert. How can i make it correctly?
Thank you.
The Translation.all() returns copies of all instances of Translation class. It seems, from snippets you provided, that when you call Translation.getLang() there are no such instances. You should make sure that changeLang has been called (I suppose that it is the only place where new instances of Translation are created) before calling alert(Translation.getLang()).