I’m using Java sdk 1.18.1. My aim is to imitate the pingPongReactive behaviour so that my app will open an ongoing stream with the Ledger (not sandbox), detect if a certain contract exists and fetch it.
I created a contract on TPA identity and i’m trying to understand why the following filter doesn’t find it:
The template id (first argument in the filter) is a generated object
I verified that the id is the same on the Ledger (see screenshot), the template name is: “SE2.Notifications” and the entityName is: “PolicyPagesNotification”
What is the value of TPA_PARTY_ID? It should be the ledger party literal (ledger-party-SOME_LONG_UUID—from your example, it looks like ledger-party-79995d65-ab91-4e4d-82a0-e5fb8d72b71d) and notTPA, which is merely the display name.
I can’t fully reproduce given that you didn’t include the DAR and that I don’t know what data you created exactly (via the hub UI or some other way) to get to this state. However, a few suggestions:
Hi @cocreature , 10x for your eyes on the code. Off course you need the daml models and/or the dar. I’ll re-generate it and send it over.
Regarding #1 - totally right…coding in a hurry, no excuses. However, i suspect its still solid and the transaction list returned with content from the Ledger so identities aren’t the issue.
Regarding #2 I just wanted to verify that the transactions i fetch contains the one that i’m interested about and yes - all parties (beside default ones if exists) are manually created. Also contracts.
This is the same Ledger that i ran against the pingPongReactive app - so to be accurate - some of the templates there were creating by Alice and Bob.
My problem is in line number 88 that i call the equals method of Identity object with apparently two different objects. One (‘template’) is a Messages module and the other (‘policyPagesNotificationIdentifier’) is a Notification one.
Can you explain in short the relation between those entities? (in DAML hub context i mean)
My problem is in line number 88 that i call the equals method of Identity object with apparently two different objects. One (‘template’) is a Messages module and the other (‘policyPagesNotificationIdentifier’) is a Notification one.
Can you explain in short the relation between those entities? (in DAML hub context i mean)
I’m not quite following, you are filtering by template id so you should not receive events for any other template. I also don’t see a Messages module in your code. What is the full template identifier (package id, module name, entity name) you are observing?
@cocreature - Sorry for not being clear. Let me try again.
My end game is to subscribe to a contract stream and get notified whenever a certain contract (the one below in screenshot) exists in the Ledger under a certain party (called “TPA”):
I’m trying to compose pieces of code snippets to accomplish this goal.
The first step of finding the package id looks like passed successfully. Meaning that i looped over all listed packages in the Ledger and matched this DottedName
segments: "SE2" segments: "Notifications"
(see DownloadPolicyPagesFromLedger::containsPolicyPagesNotificationModule method):
By the way, I think i can skip this step since i already have a generated class holding this packageId but still i want to automatically detect it.
Than, after creating a Processor class, i try fetching all transactions given my party (“TPA”) and NoFilter.instance (see runIndefinitely() method)
This list is indeed populated with transactions! Here comes the part that i’m confused and i might be composing irrelevant pieces of code from the pingPongReactive app:
For each transaction i fetch its events of type “CreatedEvent” (“processEvent()” method that temporarily returns null).
I was hoping that from each event instance i would be able to fetch its contract but i only see contractId and contractKey getters:
getArguments gives you the contract payload/value which sounds like it’s what you’re looking for?
I strongly recommend against trying to detect it via the package service. There can be multiple templates with the same module & template name (but different package ids) so you cannot do this reliably.
I believe that i can fetch the contract simply and directly from the client like below code demonstrate.
But how do i subscribe to the stream that “notifies” me that such contract exists in the Ledger instead of pro-actively search for it like here:
Subscribing to the transaction stream should work for this. I don’t understand the issue you are encountering. You said you receive the transaction which has the created event inside is so which part is missing?
I deleted everything and started from scratch. Now i successfully perform the following:
Connect to the Ledger
Find the contract i need with the code i posted earlier (processActiveContracts method) given the module generated identifier (above called TEMPLATE_ID_IDENTIFIER) and the party’s ID (ADMIN_PARTY_ID).
How do i change the program to trigger the above method whenever such contract exists on the Ledger?
Meaning - How do i convert the program to subscribe to the contract stream so that given a certain contract created on the Ledger (with specific module id) my app will be notified via gRPC stream.
Off course i’ll convert the app to stay up always (using spring-boot mS)
I think I still don’t understand what exactly you are looking for. getTransactions will subscribe to the transaction stream and give you all incoming transactions (provided you don’t specify an end offset) and thereby the create events. That’s what the runIndefinitely method in your example is doing. In the original example, that’s used to see all creates of Ping and Pong contracts as they are created.
It sounds like you are looking for something different but I don’t understand in what way it should be different.
A transaction on the (flat) transaction stream (there is also a transaction tree stream which you don’t need here so I’ll ignore it) is a list of events with each event being either a create or an archive. It sounds like you primarily care about the create events here.
The three main values that you probably want to look at in the create event are the contract id, the template id and lastly the contract arguments. The contract arguments refer to the value you pass to create which I suspect is what you are looking for when you say you want to “fetch this contract from the transaction object”.
Thanks to your explanation @cocreature i realized that previouse code was indeed the correct path to solve it (beside your recommendation to avoid fetching transactions by packageId which i’ll refactor)
Can you refer me to a code example of how to fetch the contract from a given Create event?
This is what i see inside the event object that i retrieved from the transaction stream (processEvent method in my code)
I don’t have a code sample but it looks like you are already calling getArguments which is exactly the right thing to do. Is it missing some information that you are looking for?
OK, i’ve managed to assemble the contract using a helper method from the generated module object (see line above the TODO).
In order to avoid returning null i imitated the pingPongReactive behaviour and returned a stream of command of type ARCHIVE choice.
@cocreature My question is:
Is a real stream really opened under the hood here?
Meaning - If i’ll force the program to stay up and i’ll create such contract (that complies to the one i look for in the code) on the Ledger - will i suddenly get invoked? If yes - which method will be invoked?
I guess i’m asking that since i’m new also to the gRPC concept and i’m trying to compare it to a REST http endpoint (e.g Servlet) that listens to incoming HTTP requests and gets invoked once a client calls it.
gRPC streams work more like websockets than listening for gRPC requests. Every time a new transaction comes in the method you pass to transaction.forEach(method) will get invoked.