Skip to content

Instantly share code, notes, and snippets.

@jparklev
Last active August 27, 2024 19:07
Show Gist options
  • Save jparklev/7621a7d36422ebb0d09c7e597b599309 to your computer and use it in GitHub Desktop.
Save jparklev/7621a7d36422ebb0d09c7e597b599309 to your computer and use it in GitHub Desktop.
Rumpel Merklization
import { Address, encodePacked, keccak256 } from "viem";
import { MerkleTree } from "merkletreejs";
const solidityKeccak256 = (types: string[], values: any[]) => {
return keccak256(encodePacked(types, values));
};
export type Distribution = {
[user: Address]: {
[pointsId: `0x${string}`]: {
accumulatingPoints: bigint;
};
};
};
export type MerklizedDistribution = Distribution & {
[user: Address]: {
[pointsId: `0x${string}`]: {
proof: string[];
};
};
root: string;
};
export function merklizeDistribution(
distribution: Distribution
): MerklizedDistribution {
const leaves = Object.entries(distribution).flatMap(([user, pointsIds]) =>
Object.entries(pointsIds).map(([pointsId, { accumulatingPoints }]) =>
solidityKeccak256(
["address", "bytes32", "uint256"],
[user, pointsId, accumulatingPoints]
)
)
);
if (leaves.length === 0) {
return { root: "0x", ...distribution };
} else if (leaves.length === 1) {
leaves.push(leaves[0]);
}
const tree = new MerkleTree(leaves, keccak256, { sortPairs: true });
const root = tree.getHexRoot();
for (const [user, pointsIds] of Object.entries(distribution)) {
for (const [pointsId, userPoints] of Object.entries(pointsIds)) {
const leaf = solidityKeccak256(
["address", "bytes32", "uint256"],
[user, pointsId, userPoints.accumulatingPoints]
);
// @ts-ignore
userPoints.proof = tree.getHexProof(leaf);
}
}
return { root, ...distribution };
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment