(defn stock-check
[company-id item]
{:result (crux/q (crux/db node)
{:find '[name funds stock]
:where ['[e :company-name name]
'[e :credits funds]
['e item 'stock]]
:args [{'e company-id}]})
:item item})
(defn format-stock-check
[{:keys [result item] :as stock-check}]
(for [[name funds commod] result]
(str "Name: " name ", Funds: " funds ", " item " " commod)))
Crux Saturn Assignment: Match Transactions

Introduction
This is the match
installment of the Crux tutorial.
We shall assume you have a Crux standalone node set up locally and are now comfortable with put
operations and basic Datalog queries.
If this is not the case, you can find all you need to know on Earth, Pluto and Mercury. Click on a destination above to take you there.
Arrival on Saturn
As you pass through the innermost ring of Saturn, A warning light appears on your communications panel. You open the message. It’s from Space Customs and reads:
We extend you the warmest welcome.
We must check papers before we can give you permission to land.
They are asking to see your flight manifest.
Space Port
As you prepare to land you open your Crux manual to the page on match
.
Currently there are only four transaction operations in Crux:
put
,delete
,match
andevict
.
Transaction Description
put
Writes a version of a document
delete
Deletes a version of a document
match
Stops a transaction if the doc does not match the doc for the given
:crux.db/id
.
evict
Removes a document entirely
match:
match
checks the current state of an entity - if the entity doesn’t match the provided doc, the transaction will not continue. You can also passnil
to check that the entity doesn’t exist prior to your transaction.A
match
transaction takes the entity id, along with an expected document. Optionally you can provide a valid time.Time in Crux is denoted
#inst "yyyy-MM-ddThh:mm:ss".
For example, 9:30 pm on January 2nd 1999 would be written:#inst "1999-01-02T21:30:00"
.
- A complete
match
transaction has the form:
[:crux.tx/match entity-id expected-doc valid-time]
Read More
Assignment
As you land on the surface of Saturn the job ticket for this assignment is unlocked.
Task |
|
Company |
|
Contact |
|
Submitted |
|
Additional information |
|
Attachments |
The next shuttle to the CMT office leaves in 5 Earth minutes. While you wait you use your easy ingest function you created on Pluto to put the example data into your system. You also decide to make some Clojure functions so you can easily show Ubuku the stock and fund levels after the trades.
Just as you are finishing off your shuttle arrives.
After a short journey through the icy lower clouds of Saturn you are met by a friendly faced Ubuku.
Hello friend.
We have been using Crux for a short time now and think it is great. The problem is a human one. Occasionally we process trades without checking that are enough funds in the buyers account.
I know there is a way that we can stop this happening in Crux.
I sent you some example data in the job ticket for you to use, did you find it alright?
CMT
Choose your path
"Yes, I’m ready to fix your problem." | "No, I seem to have missed that." |
---|

You explain to Ubuku that all they need to do to solve their problem is to use the match
operation along with put
when they are processing their trades.
You show Ubuku the match
operation for a valid transaction.
You move 10 units of Methane (:units/CH4
) each at the cost of 100 credits to Blue Energy:
(crux/submit-tx
node
[[:crux.tx/match
:blue-energy
{:crux.db/id :blue-energy
:seller? false
:buyer? true
:company-name "Blue Energy"
:credits 1000}]
[:crux.tx/put
{:crux.db/id :blue-energy
:seller? false
:buyer? true
:company-name "Blue Energy"
:credits 900
:units/CH4 10}]
[:crux.tx/match
:tombaugh-resources
{:crux.db/id :tombaugh-resources
:company-name "Tombaugh Resources Ltd."
:seller? true
:buyer? false
:units/Pu 50
:units/N 3
:units/CH4 92
:credits 51}]
[:crux.tx/put
{:crux.db/id :tombaugh-resources
:company-name "Tombaugh Resources Ltd."
:seller? true
:buyer? false
:units/Pu 50
:units/N 3
:units/CH4 82
:credits 151}]])
;;=> #:crux.tx{:tx-id 0, :tx-time #inst "2020-06-18T15:37:20.271-00:00"}
You explain that because the provided doc is as expected for both the buyer and the seller that the transaction goes through.
You show Ubuku the result of the trade using the function you created earlier:
(format-stock-check (stock-check :tombaugh-resources :units/CH4))
;;=> ("Name: Tombaugh Resources Ltd., Funds: 151, :units/CH4 82")
(format-stock-check (stock-check :blue-energy :units/CH4))
;;=> ("Name: Blue Energy, Funds: 900, :units/CH4 10")
They are happy that this works as he sees the 1000 credits move from Blue energy to Tombaugh Resources Ltd. and 10 units of Methane the other way.
Ubuku asks if you can show them what would happen if there was not enough funds in the account of a buyer. You show him a trade where the old doc is not as expected for Encompass trade, to buy 10,000 units of Gold from Gold Harmony.
(crux/submit-tx
node
[[:crux.tx/match
:gold-harmony
{:crux.db/id :gold-harmony
:company-name "Gold Harmony"
:seller? true
:buyer? false
:units/Au 10211
:credits 51}]
[:crux.tx/put
{:crux.db/id :gold-harmony
:company-name "Gold Harmony"
:seller? true
:buyer? false
:units/Au 211
:credits 51}]
[:crux.tx/match
:encompass-trade
{:crux.db/id :encompass-trade
:company-name "Encompass Trade"
:seller? true
:buyer? true
:units/Au 10
:units/Pu 5
:units/CH4 211
:credits 100002}]
[:crux.tx/put
{:crux.db/id :encompass-trade
:company-name "Encompass Trade"
:seller? true
:buyer? true
:units/Au 10010
:units/Pu 5
:units/CH4 211
:credits 1002}]])
;;=> #:crux.tx{:tx-id 1, :tx-time #inst "2020-06-18T15:23:38.540-00:00"}
(format-stock-check (stock-check :gold-harmony :units/Au))
;;=> ("Name: Gold Harmony, Funds: 51, :units/Au 10211")
(format-stock-check (stock-check :encompass-trade :units/Au))
;;=> ("Name: Encompass Trade, Funds: 1002, :units/Au 10")
You explain to Ubuku that this time, because you have both match
operations in the same transaction, the trade does not go through.
The accounts remain the same, even though the failing match
was the second operation.
Ubuku thanks you. This is just what they are looking for. You head back to the space station to see if there is another assignment waiting for you.
Space Port
Back at the spaceship there is a light waiting for you on your communications panel.
Well done, you’ve had a productive week. We have one final task for you to do before you finish for the week
You need to go to Jupiter and meet Kaarlang, it’s his last day working for us and he needs to delete his trade clients from his personal Crux node for data protection.
Update Manifest
You update your manifest with your most recent badge.
(crux/submit-tx
node [[:crux.tx/put
(assoc manifest
:badges ["SETUP" "PUT" "DATALOG-QUERIES" "BITEMP" "MATCH"])]])
;;=> #:crux.tx{:tx-id 3, :tx-time #inst "2020-06-18T15:24:39.037-00:00"}
As you do so, you check to see if you still have the note that the porter gave you for Kaarlang back on Earth.
(crux/q (crux/db node)
{:find '[belongings]
:where '[[e :cargo belongings]]
:args [{'belongings "secret note"}]})
;;=> #{["secret note"]}
Feeling a bit apprehensive, you enter countdown for lift off to Jupiter. See you soon.
Click on Jupiter to take you to your next assignment.