Skip to content

Instantly share code, notes, and snippets.

@matthewdowney
matthewdowney / load_class.clj
Created December 12, 2021 02:29
Load a java .class file from disk directly into Clojure ... at your own risk obviously
(ns load-class
(:import (java.lang.reflect Array)
(java.io FileInputStream)))
;; ClassLoader/defineClass is protected, and calling it from the proxy requires
;; reflection.
(def ^:private classloader-define-class
(let [primitive-bytes (.getClass (Array/newInstance Byte/TYPE 0))
args [String primitive-bytes Integer/TYPE Integer/TYPE]]
(doto
@matthewdowney
matthewdowney / web3.clj
Created August 28, 2021 00:18
Call a smart contract from Clojure to query data from the Ethereum blockchain.
(ns web3
"Call an Ethereum smart contract (Uniswap v2) from Clojure.
Requires https://github.com/clj-python/libpython-clj for python interop. Also
make sure to $ pip install web3."
(:require [libpython-clj2.python :as py]
[libpython-clj2.require :refer [require-python]]))
(comment ;; deps.edn
@matthewdowney
matthewdowney / elliptic-curve.clj
Last active January 23, 2021 00:46
Faster Clojure elliptic curve addition for affine points
(defn modular-multiplicative-inverse
"Find x in [0, p) such that (m * x) % p = n"
[n m p]
(let [n (biginteger n)
m (biginteger m)
p (biginteger p)]
(-> (.modInverse m p)
(.multiply n)
(.mod p))))
(ns user.ring-buffer
"A fast, mutable ring buffer, backed by a fixed Java array.
Prefer https://github.com/clj-commons/ring-buffer unless you have very
specific needs."
(:require [taoensso.tufte :as tufte])
(:import (clojure.lang IDeref)))
(defprotocol ^:private Cursor (get-cursor! [this]))
@matthewdowney
matthewdowney / crash.clj
Created November 1, 2020 00:14
The deterministic algorithm behind the casino game https://roobet.com/crash
(ns user.crash
"The deterministic algorithm behind the casino game https://roobet.com/crash.
Includes code to
- generate a crash point from a game hash
- generate all game hashes and crash points since the start of the game
- simulate betting strategies (n.b. this is just for fun, as there's no way
to make a bet with a positive expected value)"
(:require [pandect.algo.sha256 :as sha]))
@matthewdowney
matthewdowney / jvm-thread-dump.clj
Created September 13, 2020 01:03
Programmatic JVM Thread Dump in Clojure
(import '(java.lang.management ManagementFactory))
(defn thread-dump []
(with-out-str
(let [tmx-bean (ManagementFactory/getThreadMXBean)
tids (.getAllThreadIds tmx-bean)
max-stack-depth 100
tinfo (.getThreadInfo tmx-bean tids max-stack-depth)]
(doseq [tinf tinfo]
(println (str \" (.getThreadName tinf) \"))
@matthewdowney
matthewdowney / client-encrypt.clj
Last active May 17, 2020 20:46
Lightweight key management with client-side encryption in Clojure applications.
(ns client-encrypt
"Utilities to for encrypting credentials (chiefly API keys),
storing them on disk, and editing them."
(:require [buddy.core.codecs :as codecs]
[buddy.core.nonce :as nonce]
[buddy.core.crypto :as crypto]
[buddy.core.kdf :as kdf]
[clojure.java.io :as io]
[clojure.java.shell :as sh]
[clojure.pprint :as pprint]
@matthewdowney
matthewdowney / heap_dump.clj
Created March 27, 2020 23:56
Clojure snippet to cause a JVM heap dump programmatically
(import 'java.lang.management.ManagementFactory)
(import 'com.sun.management.HotSpotDiagnosticMXBean)
(let [server (ManagementFactory/getPlatformMBeanServer)
bean-name "com.sun.management:type=HotSpotDiagnostic"
bean (ManagementFactory/newPlatformMXBeanProxy server bean-name HotSpotDiagnosticMXBean)
live-objects-only? true]
(.dumpHeap bean "heapdump.hprof" live-objects-only?))
@matthewdowney
matthewdowney / edn2json
Last active March 27, 2020 18:49
Boot CLI for converting EDN to JSON. E.g. $ cat ledger.edn | ./edn2json
#!/usr/bin/env boot
(set-env! :dependencies '[[org.clojure/data.json "0.2.6"]
[org.clojure/clojure "1.8.0"]])
(require '[boot.cli :refer [defclifn]])
(require '[clojure.java.io :as io])
(require '[clojure.data.json :as json])
(defclifn -main
@matthewdowney
matthewdowney / merge-sort.clj
Created March 5, 2020 06:56
Lazy Clojure merge-sort that works on infinite sequences
(defn merge-sort [keyfn series]
(let [pop-next
(fn [keyfn series]
(let [serie+fst (map (juxt rest first) series)]
(when-let [next-item (first (sort-by keyfn (keep second serie+fst)))]
(reduce
(fn [[series returning] [serie fst]]
;; "pop" next-item from the first series we see whose first
;; item is equal to next-item (there might be multiple, and
;; we'll just take the first)