Using the React bindings, is there a way to query the ledger with parameters other than the contract key?
I’m looking for a way to use the React bindings to query the ledger with the equivalent of this command:
SELECT * FROM Profiles
WHERE State = "TN"
We’re currently pulling the entire state of the ledger and filtering results locally, but hoping for a more scalable way to handle it.
Let me know if you need more details, thanks in advance!
Hi @liam_e!
You can use query function, see the documentation: https://docs.daml.com/app-dev/bindings-ts/daml-ledger/index.html#query
query makes a call to JSON API /v1/query endpoint: https://docs.daml.com/json-api/index.html#contract-search
Here is the query language specification: https://docs.daml.com/json-api/search-query-language.html
It does not support SQL syntax, but it allows to query active contracts.
If you’re using React, you can also use the useQuery hook or the corresponding streaming version useStreamQuery. They are implemented on top of the functions in @daml/ledger @Leonid_Shlyapnikov linked to.
The template looks like this:
template Profile with admin: Party state: Text city: Text eid: Text
We’re currently using useStreamQuery in the front end like this:
const allProfiles = useStreamQuery(Profile.Profile).contracts;
We want to be able to query it based on city and state. Right now we’ve only been able to retrieve all contracts. I see how to do it using the JSON API, but not the React bindings.
A little confused about the documentation and we’re getting errors when we try to pass in query parameters, could you give an example of how we would use this function?
Thanks!
useStreamQuery accepts a second argument, take a look at the type signature at https://docs.daml.com/app-dev/bindings-ts/daml-react/modules/defaultledgercontext.html#usequery. This is the query that will be sent to the JSON API. So you can use something like useStreamQuery(Profile.Profile, () => ({state: "yourstate", city: "yourcity"}), []) to filter down to contracts with state set to "yourstate" and city set to "yourcity".
When I try the following,
const result = useQuery(Profile.Profile, () => {state: "yourstate", city: "yourcity"})
I get this error:
No overload expects 2 arguments, but overloads do exist that expect either 1 or 3 arguments.
If I take out the second parameter and only write
const result = useQuery(Profile.Profile)
the error goes away.
If I add a third parameter:
const result = useQuery(Profile.Profile, () => {state: "yourstate", city: "yourcity"}, [])
I get this type error:
Argument of type '() => void' is not assignable to parameter of type '() => { admin?: string | undefined; name?: string | undefined; address?: string | undefined; city?: string | undefined; state?: string | undefined; phone?: string | undefined; eid?: string | undefined; ... 4 more ...; timestamp?: string | undefined; }'.
Type 'void' is not assignable to type '{ admin?: string | undefined; name?: string | undefined; address?: string | undefined; city?: string | undefined; state?: string | undefined; phone?: string | undefined; eid?: string | undefined; ... 4 more ...; timestamp?: string | undefined; }'.ts
Any thoughts? Thanks again.
Sorry my bad, I’ve fixed up the above example. There are two points:
- Wrap the query in parentheses. Otherwise it gets interpreted as a block instead of an object:
() => ({state: "yourstate", city: "yourcity"}). - Add the list of dependencies for the query at the end so react can retrigger as needed. You already did this.
Awesome, got it working now. Thank you!
A post was split to a new topic: Filtering nested objects via the typescript bindings
A post was split to a new topic: Disjunctive/OR queries via the typescript bindings