For SnarkJS (https://github.com/iden3/snarkjs), there's an HTML example showing how to consume their ES6 javascript library:
<!doctype html>
<html>
<body>
<script src="snarkjs.min.js"> </script>
<script>
async function calculateProof() {
const { proof, publicSignals } =
await snarkjs.groth16.fullProve( { a: 3, b: 11}, "circuit.wasm", "circuit_final.zkey");
</script>
</body>
</html>
This call to snarkjs.groth16.fullProve works perfectly in the browser.
In Blazor, I load snarkjs.min.js into an IJSObjectReference (myJSmodule), but I don't know how to emulate the snarkjs.groth16.fullProve call from Blazor to the module. Something like:
await myJSmodule.InvokeVoidAsync("snarkjs.groth16.fullProve", args...)
but that produces
Could not find 'snarkjs.groth16.fullProve'...'snarkjs' was undefined
EDIT: In the end, I had two problems:
Chrome was caching my embedded javascript (not the dynamically loaded modules) so running the app would result in it using outdated cached javascript. Solution was to long-click on the Chrome refresh button, and choosing "Empty Cache and Hard Reload". Though I'm not sure if this bodes well for deployed consumer-facing websites.
Dimitris' answer below took care of the second problem.
You can create a helper js module that exports the calculateProof
function:
snarkJsInteropHelper.js
export async function calculateProof() {
const { proof, publicSignals } =
await snarkjs.groth16.fullProve({ a: 3, b: 11 }, "circuit.wasm", "circuit_final.zkey");
}
Then in blazor component:
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
var module = await JS.InvokeAsync<IJSObjectReference>(
"import", "./snarkJsInteropHelper.js");
await module.InvokeVoidAsync("calculateProof");
}
}