2

I am working through the tutorial where it says how to create a contract.

Here is their code:

function createFirstPing() {
    const request = {
        commands: {
            applicationId: 'PingPongApp',
            workflowId: `Ping-${sender}`,
            commandId: uuidv4(),
            ledgerEffectiveTime: { seconds: 0, nanoseconds: 0 },
            maximumRecordTime: { seconds: 5, nanoseconds: 0 },
            party: sender,
            list: [
                {
                    create: {
                        templateId: PING,
                        arguments: {
                            fields: {
                                sender: { party: sender },
                                receiver: { party: receiver },
                                count: { int64: 0 }
                            }
                        }
                    }
                }
            ]
        }
    };
    client.commandClient.submitAndWait(request, (error, _) => {
        if (error) throw error;
        console.log(`Created Ping contract from ${sender} to ${receiver}.`);
    });
}

I want to create a similar request for in my project that sends a field called 'datetime_added'. In my DAML code it is of type time. I cannot figure out the proper syntax for this request. For example:

arguments: {
      fields: {
        sender: { party: sender },
        receiver: { party: receiver },
        count: { int64: 0 },
        datetime_added: { time: '2019 Feb 19 00 00 00' }
      }
}

The format I am expressing the time is not what is causing the problem (although I acknowledge that it's also probably wrong). The error I'm seeing is the following:

Error: ! Validation error
▸ commands
  ▸ list
    ▸ 0
      ▸ create
        ▸ arguments
          ▸ fields
            ▸ datetime_added
              ✗ Unexpected key time found
    at CommandClient.exports.SimpleReporter [as reporter] (/home/vantage/damlprojects/loaner_car/node_modules/@da/daml-ledger/lib/data/reporting/simple_reporter.js:36:12)
    at Immediate.<anonymous> (/home/vantage/damlprojects/loaner_car/node_modules/@da/daml-ledger/lib/data/client/command_client.js:52:62)
    at runCallback (timers.js:705:18)
    at tryOnImmediate (timers.js:676:5)
    at processImmediate (timers.js:658:5)

I don't understand, is time not a valid DAML data type?


Edit

I tried switching time to timestamp as follows

datetime_added: {timestamp: { seconds: 0, nanoseconds: 0 }}

causing the following error:

/home/......../damlprojects/car/node_modules/google-protobuf/google-protobuf.js:98
goog.string.splitLimit=function(a,b,c){a=a.split(b);for(var d=[];0<c&&a.length;)d.push(a.shift()),c--;a.length&&d.push(a.join(b));return d};goog.string.editDistance=function(a,b){var c=[],d=[];if(a==b)return 0;if(!a.length||!b.length)return Math.max(a.length,b.length);for(var e=0;e<b.length+1;e++)c[e]=e;for(e=0;e<a.length;e++){d[0]=e+1;for(var f=0;f<b.length;f++)d[f+1]=Math.min(d[f]+1,c[f+1]+1,c[f]+Number(a[e]!=b[f]));for(f=0;f<c.length;f++)c[f]=d[f]}return d[b.length]};goog.asserts={};goog.asserts.ENABLE_ASSERTS=goog.DEBUG;goog.asserts.AssertionError=function(a,b){b.unshift(a);goog.debug.Error.call(this,goog.string.subs.apply(null,b));b.shift();this.messagePattern=a};goog.inherits(goog.asserts.AssertionError,goog.debug.Error);goog.asserts.AssertionError.prototype.name="AssertionError";goog.asserts.DEFAULT_ERROR_HANDLER=function(a){throw a;};goog.asserts.errorHandler_=goog.asserts.DEFAULT_ERROR_HANDLER;

AssertionError: Assertion failed
    at new goog.asserts.AssertionError (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:98:603)
    at Object.goog.asserts.doAssertFailure_ (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:99:126)
    at Object.goog.asserts.assert (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:99:385)
    at jspb.BinaryWriter.writeSfixed64 (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:338:80)
    at proto.com.digitalasset.ledger.api.v1.Value.serializeBinaryToWriter (/home/vantage/damlprojects/loaner_car/node_modules/@da/daml-ledger/lib/grpc/generated/com/digitalasset/ledger/api/v1/value_pb.js:289:12)
    at jspb.BinaryWriter.writeMessage (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:341:342)
    at proto.com.digitalasset.ledger.api.v1.RecordField.serializeBinaryToWriter (/home/vantage/damlprojects/loaner_car/node_modules/@da/daml-ledger/lib/grpc/generated/com/digitalasset/ledger/api/v1/value_pb.js:1024:12)
    at jspb.BinaryWriter.writeRepeatedMessage (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:350:385)
    at proto.com.digitalasset.ledger.api.v1.Record.serializeBinaryToWriter (/home/vantage/damlprojects/loaner_car/node_modules/@da/daml-ledger/lib/grpc/generated/com/digitalasset/ledger/api/v1/value_pb.js:822:12)
    at jspb.BinaryWriter.writeMessage (/home/vantage/damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:341:342)

In short, I need to know what type to use in my Node.js client for a DAML value of type time and how to express it.

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
Meyer Auslander
  • 349
  • 1
  • 10
  • From the stacktrace it looks like it's failing on this assertion when it's trying to write a number (probably either of the values within the timestamp): https://github.com/protocolbuffers/protobuf/blob/v3.6.1/js/binary/writer.js#L673-L674 If the code you shared is an exact match with the one you are running, though, I would not understand why that assertion would fail. – stefanobaghino Mar 07 '19 at 06:52
  • I think it is an exact match. – Meyer Auslander Mar 07 '19 at 16:31

1 Answers1

0

I would recommend using the reference documentation for the bindings (although, as of version 0.4.0, browsing through it to answer your question I noticed two mistakes). In the upper navigation bar of the page you can start from Classes > data.CommandClient and work your way down its only argument (SubmitAndWaitRequest) until, following the links to the different fields, you reach the documentation for the timestamp field, which, as the error suggests (despite the mistake in the documentation), should be a Timestamp, where seconds are expressed in epoch time (seconds since 1970).

Hence, to make the call you wanted this would be the shape of the object you ought to send:

arguments: {
  fields: {
    sender: { party: sender },
    receiver: { party: receiver },
    count: { int64: 0 }
    datetime_added: { timestamp: { seconds: 0, nanoseconds: 0 } }
  }
}

For your case in particular, I would probably make a small helper that uses the Date.parse function.

function parseTimestamp(string) {
  return { seconds: Date.parse(string) / 1000, nanoseconds: 0 };
}

That you can then use to pass in the time you mentioned in the example you made:

arguments: {
  fields: {
    sender: { party: sender },
    receiver: { party: receiver },
    count: { int64: 0 }
    datetime_added: { timestamp: parseTimestamp('2019-02-19') }
  }
}

As a closing note, I'd like to add that the Node.js bindings ship with typing files that provide auto-completion and contextual help on compatible editors (like Visual Studio Code). Using those will probably help you. Since the bindings are written in TypeScript, the typings are guaranteed to be always up to date with the API. Note that for the time being, the auto-completion works for the Ledger API itself but won't give you help for arbitrary records that target your DAML model (the fields object in this case).

stefanobaghino
  • 11,253
  • 4
  • 35
  • 63
  • I tried this and the following error resulted: `home/...../damlprojects/loaner_car/node_modules/google-protobuf/google-protobuf.js:98 goog.string.splitLimit=function(a,b,c){a=a.split(b);for(var d=[];0 – Meyer Auslander Mar 06 '19 at 17:52
  • The links to data.CommandClient , SubmitAndWaitRequest) , and Timestamp are not valid. – Meyer Auslander Mar 06 '19 at 17:55
  • 1
    You may want to edit the original question with the new details or create a new question, it's quite difficult to interpret a limited part of the error in the comments. – stefanobaghino Mar 06 '19 at 18:07
  • Have you changed the DAML model accordingly and loaded the new model with the new field on the sandbox? – stefanobaghino Mar 07 '19 at 17:22
  • The DAML model includes the variable 'datetime_added' with is of type 'time'. Sandbox is running on it. Then I ran `npm run fetch-template-ids`. This error occurs upon running `node index.js` – Meyer Auslander Mar 07 '19 at 17:56
  • I've been able to fully replicate the issue, it looks like a bug. I'll try to understand what the issue is. – stefanobaghino Mar 08 '19 at 10:05