Skip to content

Commit

Permalink
🎧 Add Mina blockchain listener
Browse files Browse the repository at this point in the history
  • Loading branch information
KimlikDAO-bot committed May 22, 2024
1 parent 40118c0 commit 9adecc1
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 7 deletions.
25 changes: 25 additions & 0 deletions mina/MinaState.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { DurableObject } from "cloudflare:workers";

class MinaState extends DurableObject {
constructor(state, env) {
super(state, env);
/** @const {!cloudflare.DurableobjectStorage} */
this.storage = state.storage;
/** @type {number} */
this.height = 0;

state.blockConcurrencyWhile(() => state.storage.get("height")
.then((/** nummber */ height) => this.height = height));
}

getHeight() {
return this.height;
}

setHeight(height) {
this.height = height;
return this.storage.put("height", height);
}
}

export { MinaState };
77 changes: 70 additions & 7 deletions mina/mina.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,29 @@
import hex from "@kimlikdao/lib/util/hex";
import { MerkleTree } from "./MerkleTree";
import { MinaState } from "./MinaState";

const LEARN2EARN = "B62qnnFm3SEtrMgStoj4SRVxKSTERh8Ho3Y9jCCa8TvgBF1mqa97Sij";

/** @define {string} */
const NODE_URL = "mina.kimlikdao.org";
const KIMLIKDAO_NODE_URL = "https://mina.kimlikdao.org";

/** @const {string} */
const MINA_NODE_URL = "https://api.minascan.io/archive/devnet/v1/graphql";

/** @const {string} */
const EventsQuery = `{
events(input: { address: "B62qnnFm3SEtrMgStoj4SRVxKSTERh8Ho3Y9jCCa8TvgBF1mqa97Sij" }) {
blockInfo {
height
}
eventData {
transactionInfo {
status
}
data
}
}
}`;

/**
* @implements {cloudflare.ModuleWorker}
Expand All @@ -12,23 +33,65 @@ const MinaWorker = {
* @override
* @param {!Request} req
* @param {!MinaEnv} env
* @return {!Promise<!Response>}
*/
async fetch(req, env) {
fetch(req, env) {
/** @const {string} */
const pathname = req.url.slice(NODE_URL.length + 8);
const pathname = req.url.slice(KIMLIKDAO_NODE_URL.length);

if (pathname.startsWith("/witness")) {
const address = pathname.slice("/witness/".length, "/witness/".length + 55);
const index = hex.toBin(pathname.slice("/witness/".length + 56));
const index = hex.toBin(pathname.slice("/witness/".length + 56)).padStart(32, "0");

/** @const {!MerkleTree} */
const merkleTree = /** @type {!MerkleTree} */(
const merkleTree = /** @type {!MerkleTree} */ (
env.MerkleTree.get(env.MerkleTree.idFromName(address)));

return merkleTree.getWitness(index).then(Response.json);
}
}
},

/**
* TODO(KimlikDAO-bot): Implement a robust Mina synchronizer.
*
* A very simple and error prone Mina sychronization method.
* Will not survive forks.
*/
async scheduled(event, env) {
/** @const {!MerkleTree} */
const merkleTree = env.MerkleTree.get(env.MerkleTree.idFromName(LEARN2EARN));
/** @const {!MinaState} */
const minaState = env.MinaState.get(env.MinaState.idFromName(""));
/** @const */
const lastHeight = minaState.getHeight();

let events = await fetch(MINA_NODE_URL, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({ query: EventsQuery }),
})
.then((res) => res.json())
.then((data) => data["data"]["events"].filter((e) =>
e.eventData[0].transactionInfo.status == "applied" &&
e.blockInfo.height > lastHeight
));
events.sort((x, y) => x.blockInfo.height - y.blockInfo.height);

for (const e of events) {
const [type, val] = e.eventData[0].data;
switch (type) {
case "1":
await merkleTree.setHeight(+val);
break;
case "0": await merkleTree.setLeaf(
hex.toBin(BigInt(val).toString(16) & 0xffffffffn)).padStart(32, "0");
break;
}
}

await minaState.setHeight(events[events.length - 1].blockInfo.height);
},
};

export default MinaWorker;
export { MerkleTree };
export { MerkleTree, MinaState };
3 changes: 3 additions & 0 deletions mina/prod.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,6 @@ class_name = "MerkleTree"
[[migrations]]
tag = "v1"
new_classes = ["MerkleTree"]

[triggers]
crons = ["* * * * *"]

0 comments on commit 9adecc1

Please sign in to comment.