Mapping Json values

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:

  1. Name of the company
  2. The weight of the package
  3. Temperature of the package
  4. Location of pick up ( street number, street name, state, zip code)
  5. Delivery of the pick-up (street number, street name, state, zip code)
  6. Time of the delivery

I’m thinking that there need to be two templates:

  1. Supplier Template
  2. Driver Template where the Drive has a choice of accepting or declining the delivery

Any help would be greatly appreciated !!

1 Like

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:

  1. Driver profile → track the drivers record on trips
  2. Gas Card - > fuel the driver is receiving
  3. 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:

  1. 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?
  2. 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 :slight_smile: 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.

1 Like

Wow I get it thank you so much for the insight I got it to work !!!