I am trying to map a supplier’s JSON payload to store it in a smart contract. The extraction is coming from a python script. I’m confused about how to connect the python script to daml smart contract that I will create using the Initiate script. How would I go about storing it in a smart contract to be archived? The input goes as follows:
Name of the company
The weight of the package
Temperature of the package
Location of pick up ( street number, street name, state, zip code)
Delivery of the pick-up (street number, street name, state, zip code)
Time of the delivery
I’m thinking that there need to be two templates:
Supplier Template
Driver Template where the Drive has a choice of accepting or declining the delivery
As long as there are no choices, you can treat templates as data to be permanently stored on the ledger. However,
A choice should, as a rule, change the state of the ledger. (That means it should at least archive or create a contract, and often do both, sometimes more than once.) So, considering this, what happens on the ledger when a Driver exercises the AcceptDelivery choice? What happens when a Driver exercises the DeclineDelivery choice?
Additionally, which drivers can exercise these choices? These are the cases where you have to start thinking about the signatories of your contracts, as well as the controllers who can exercise each choice.
I think it’s worth starting to write these things down in Daml, using Daml Studio. Define your templates to hold all the data you think they should hold, one or more signatory that should “own” contracts of each template, and the choices and what controller can exercise each one. You don’t need to work out the exact details of what each choice does, but having a note or two would help guide your development.
At that point, it becomes possible to discuss exactly what the Daml you have prototyped means, and how it might match or mismatch what you intend for it to do.
Stephen thanks for the quick reply. From what you explained this is what I have created and think that the contract should represent. The contract should not be archived unless it is accepted by the driver. If the driver does accept it, I can build a profile on the ones that he accepts by creating another smart contract and importing the manifest?
module Manifest where
import Daml.Script
template LoadMaster
with
issuer : Party
where
signatory issuer
nonconsuming choice Invite : ContractId LoadIssueProposal
with owner : Party
controller issuer
do create LoadIssueProposal
with workloadAgreement = WorkloadIssueAgreement with issue; owner
template LoadIssueProposal
with
workloadAgreement : WorkloadIssueAgreement
where
signatory workloadIssueAgreement.issuer
observer workloadIssueAgreement.owner
choice AcceptWorkloadProposal : ContractId WorkloadIssueAgreement
controller workloadIssueAgreement.owner
do create workloadAgreement
choice RejectWorkloadProposal : ContractId WorkloadIssueAgreement
controller workloadIssueAgreement.owner
do create workloadAgreement
with reason = "Workload proposal rejected"
template WorkloadIssueAgreement
with
issuer : Party
owner : Party
where
signatory issuer, owner
# if contract is accepted than archive the manifest details
nonconsuming choice Issue : ContractId Manifest
with amount : Decimal
controller issuer
do create Manifest with issuer; owner; amount; weight; tempature; pickup = []; dropOff = []
This looks more-or-less reasonable so far. A couple notes:
Every template has an Archive choice that can be exercised by all of the signatories. (Consider it this way: every signer can mutually agree to cancel a contract.) LoadIssueProposal can be archived by the issuer. I don’t think this harms your requirements at all (if an issuer withdraws the proposal before the owner can accept or reject it, has anything untoward happened?), but is worth remembering.
Does it make sense to be able to Issue more than once? That’s what can happen here.
Remember that anything that can be used as part of a template payload, can also be used as a choice argument. So Issue is where you might incorporate your Manifest data.
Note that you can express your intended workflow in a script test, so you can see how a set of parties might interact with your contracts and choices. This is also useful for determining whether your signatory declarations match your requirements.
I suggest another rule of thumb: “if the set of allowed choices is different, then the template should be different”. Does the WorkloadIssueAgreement that results from a RejectWorkloadProposal, practically speaking, offer the same set of choices that one from AcceptWorkloadProposal would offer?
I think I understand what you are getting at. To simplify it I decided to build three separate daml files that go as follows:
Driver profile → track the drivers record on trips
Gas Card - > fuel the driver is receiving
Manifest → number of loads that are being provided.
Right now I am focused on the Profile and have written the following code but having issue with testing it
module Profile where
import Daml.Script
template DriverProfile
with
dispatcher : Party -- dispatcher working with driver
driver : Party -- driver working with dispatcher
where
signatory driver
observer dispatcher
template DriverInformation
with
driverlicenseNumber : Text
driverlicenseExpiration : Date
driverlicenseState : Text
driverlicenseCountry : Text
driverlicenseIssuedBy : Text
driverlicenseIssuedByAddress : Text
driverlicenseEndorsements : Text
driverDOTnumbers : Text
where
signatory driver
observer dispatcher
template VehicleInformation
with
vehicleNumber : Text
vehicleMake : Text
vehicleModel : Text
vehicleYear : Text
vehicleColor : Text
vehicleLicensePlate : Text
vehicleLicensePlateState : Text
vehicleLicensePlateCountry : Text
vehicleLicensePlateExpiration : Date
where
signatory driver
observer dispatcher
---- Testing Logic ----
driver_test_1 = do
zavion <- allocateParty "Zavion" -- driver
mike <- allocateParty "Mike" -- dispatcher
-- create a driver profile
driver_1 <- DriverProfile `submit` do
createCmd dispatcher mike
The error I am receiving :
File: daml/Profile.daml
Hidden: no
Range: 48:3-49:32
Source: typecheck
Severity: DsError
Message:
daml/Profile.daml:48:3: error:
The last statement in a 'do' block must be an expression
driver_1 <- DriverProfile `submit` do createCmd dispatcher zavion
damlc: Error when running Shake build system:
BadDependency "GenerateDalf"
Two questions I have:
How do I test the logic such that I am able to fill in every parameter within the template that was created in the driver_1 variable?
Once I create the profile of a driver and I want to assign them a manifest should I import the profile in the manifest.daml or create a Main.daml then import the dependent scripts I created in that file and start building the workflow from there similar to C++?
Easy enough to fix put pure () as the last line in your script.
A payload must be complete in order for a contract to be created, and when you retrieve the payload of a contract ID, it is guaranteed to have all the fields. You don’t have to test this aspect, it is guaranteed by the Daml environment. Just make up nonsense for the fields, and that’s what will go in.
The only restriction is that you cannot have circular imports. Typically, templates that participate in a workflow will have choices that refer to other templates, so if there is a circularity there, all such templates must be in the same file. Otherwise, do whatever makes you feel most comfortable with your application.
Scripts, themselves, should never be referenced from templates; your own script demonstrates this, i.e. driver_test_1 refers to your templates, but not vice versa. So putting a script in its own file, importing all the templates it uses, is a way to split up your files that always works.