How to get the ContractId of contracts that are stored in a list

G-d willing

Continuing from my previous question regarding sorting, I would like to know how can I get the id of every contract.
I have a list of [ContractId TemplateA]
This template has a price field of type Decimal.
in order to sort the list by price, I had to fetch the contracts of TemplateA into a list, and then do the sorting. Which returns a list of [TemplateA] and not [ContractId TemplateA].
So, how can I get back the contract id of every TemplateA contract? I need that in order to exercise a choice of it.

Thanks,

1 Like

In this example, TemplateA is the type of a contract payload. It is no more than the product of the fields declared under the template TemplateA with part of your code; in other words there is no such thing as “the contract payload’s contract ID”.

When you are doing the forA to fetch your contracts, you need to keep the ID with the fetched contract payload. You can do that by changing fetch to

\id -> do
  payload <- fetch id
  pure (id, payload)

That will change your offers' type to [(ContractId TemplateA, TemplateA)]; you’ll need to adjust your sort function accordingly.

2 Likes

Thank you @Stephen for your response.
Well, here is my code, which I can’t get it to work:
offersAndIds ← forA offers (\offerId → do
offer ← fetch offerId
return (offerId, offer))
let sortedBids = sortBy comparator offersAndIds

And the code of the comparison function is:
comparator: (ContractId CustomerOffer, CustomerOffer) → (ContractId CustomerOffer, CustomerOffer) → Ordering
comparator a b =
do
let
offer1 = snd a
offer2 = snd b
if offer1.value < offer2.value then LT
else if offer1.value < offer2.value then GT
else EQ

When I log the 2 lists, I am getting the same results and the list is not sorted by the value.
Any idea?

Note that your comparator returns results that will confuse the sorter:

    if offer1.value < offer2.value then LT
    else if offer1.value < offer2.value then GT

This means that your comparator declares that there exist values o1, o2: Offer, such that (c1, o1) < (c2, o2) and (c2, o2) < (c1, o1).

I suggest using compare directly, instead; use

    compare offer1.value offer2.value

and you can skip all the if/else boilerplate.

(By the way, you can use the ``` lines to demarcate code samples; example over here.)

1 Like

Thanks a lot @Stephen

One final note, using sortOn instead of sortBy will be nicer; instead of comparator, you pass a function that just points to the sortable data:

keyFn : (ContractId CustomerOffer, CustomerOffer) -> Decimal
keyFn (_, offer) = offer.value

This is ideal because it is not possible to make the mistake of an invalid comparator function using this approach.

1 Like

nice information, thanks for sharing