Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ cardano-wasm/grpc-example/cardano-wasm.wasm
cardano-wasm/grpc-example/cardano-wasm.js
cardano-wasm/grpc-example/cardano-api.d.ts
cardano-wasm/grpc-example/cardano-api.js
cardano-wasm/grpc-example/node_grpc_web_pb.js
cardano-wasm/grpc-example/cardano_node_grpc_web_pb.js
cardano-wasm/example/cardano-wasm.wasm
cardano-wasm/example/cardano-wasm.js
cardano-wasm/example/cardano-api.d.ts
Expand Down
15 changes: 2 additions & 13 deletions cardano-wasm/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -239,19 +239,8 @@ To run the example in the `example` subfolder:
To run the example in the `grpc-example` subfolder:

1. Run an instance of the `cardano-node` with the GRPC server enabled and put the socket file for the GRPC server in the root folder of this repo with the name `rpc.socket`. (You can put it somewhere else, but you will have to update the `envoy-conf.yaml` function later.)
2. Generate the JS GRPC client bundle `node_grpc_web_pb.js` from the GRPC server proto files by either:
- Running `nix build .#proto-js-bundle`. (This will generate it under the `result` folder.)
- Or using `protoc`, `npm` and `browserify`:
```
protoc -I../../cardano-rpc/proto --js_out=import_style=commonjs,binary:./ --grpc-web_out=import_style=commonjs,mode=grpcwebtext:. ../../cardano-rpc/proto/cardano/rpc/node.proto

npm install grpc-web

npm install google-protobuf

browserify --standalone grpc cardano/rpc/node_grpc_web_pb.js > node_grpc_web_pb.js
```
3. Copy the generated `node_grpc_web_pb.js` file to the `grpc-example` subfolder.
2. Generate the JS GRPC client bundle `cardano_node_grpc_web_pb.js` from the GRPC server proto files by running `nix build .#proto-js-bundle`. (This will generate it under the `result` folder.)
3. Copy the generated `cardano_node_grpc_web_pb.js` file to the `grpc-example` subfolder.
4. Copy the generated `cardano-wasm.wasm` file to the `grpc-example` subfolder. You can find its location using:
```console
echo "$(env -u CABAL_CONFIG wasm32-wasi-cabal list-bin exe:cardano-wasm | tail -n1)"
Expand Down
4 changes: 2 additions & 2 deletions cardano-wasm/grpc-example/envoy-conf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,15 +93,15 @@ static_resources:
body:
filename: "./example.js"
- match:
path: "/node_grpc_web_pb.js"
path: "/cardano_node_grpc_web_pb.js"
response_headers_to_add:
- header:
key: "Content-Type"
value: "text/javascript"
direct_response:
status: 200
body:
filename: "./node_grpc_web_pb.js"
filename: "./cardano_node_grpc_web_pb.js"
http_filters:
- name: envoy.filters.http.grpc_web
typed_config:
Expand Down
2 changes: 1 addition & 1 deletion cardano-wasm/grpc-example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<title>cardano-wasm test</title>
</head>
<body>
<script type="module" src="./node_grpc_web_pb.js"></script>
<script type="module" src="./cardano_node_grpc_web_pb.js"></script>
<script type="module" src="./example.js"></script>
<h1>Test output</h1>
</body>
Expand Down
6 changes: 4 additions & 2 deletions cardano-wasm/src/Cardano/Wasm/Internal/JavaScript/GRPC.hs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@ module Cardano.Wasm.Internal.JavaScript.GRPC (js_newWebGrpcClient, js_getEra) wh
import GHC.Wasm.Prim

-- | Create a GRPC-web client for the Cardano API.
foreign import javascript safe "new grpc.NodePromiseClient($1, null, null)"
foreign import javascript safe "{ node: new cardano_node.node.NodePromiseClient($1, null, null), \
query: new cardano_node.query.QueryServicePromiseClient($1, null, null) \
}"
js_newWebGrpcClientImpl :: JSString -> IO JSVal

js_newWebGrpcClient :: String -> IO JSVal
js_newWebGrpcClient = js_newWebGrpcClientImpl . toJSString

-- | Get the era from the Cardano API using a GRPC-web client.
foreign import javascript safe "($1).getEra(new proto.Empty(), {})"
foreign import javascript safe "($1).node.getEra(new proto.Empty(), {})"
js_getEra :: JSVal -> IO Int

#endif
54 changes: 39 additions & 15 deletions nix/proto-to-js.nix
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ in pkgs.stdenv.mkDerivation {
mkdir -p "$GEN_JS_PATH"
mkdir -p "$BUNDLE_PATH"

echo "--- Compiling .proto file: $PROTO_FILE ---"
echo "--- Compiling .proto files in $PROTO_INCLUDE_PATH ---"

# Find all .proto files and compile them.
for PROTO_FILE in `find "$PROTO_INCLUDE_PATH" -type f -name "*.proto"`
do
protoc \
Expand All @@ -57,32 +58,55 @@ in pkgs.stdenv.mkDerivation {
echo "--- Compilation finished. Generated files are in $GEN_JS_PATH ---"
ls -R "$GEN_JS_PATH"

# Check if there are any files in the top-level generated directory
if [ ! "$(ls -1 "$GEN_JS_PATH" | head -n 1)" ]; then
echo "Error: protoc did not generate any gRPC-Web files!"
exit 1
fi
# Generate JS file that imports the generated files for Browserify
ENTRYPOINT_FILE=$GEN_JS_PATH/index.js
echo "--- Creating browserify entrypoint: $ENTRYPOINT_FILE ---"

# Ensure the entrypoint file is empty before we start.
rm -f $ENTRYPOINT_FILE
touch "$ENTRYPOINT_FILE"

# Find all *_grpc_web_pb.js files and build the entrypoint content.
for JS_FULLPATH in `find "$GEN_JS_PATH" -type f -name "*_grpc_web_pb.js"`
do
# Get the filename, e.g., "node_grpc_web_pb.js"
JS_FILENAME=$(basename "$JS_FULLPATH")

# Extract the module name by removing the suffix
MODULE_NAME=''${JS_FILENAME%_grpc_web_pb.js}

# Get the path relative to GEN_JS_PATH for the require() statement.
RELATIVE_PATH=''${JS_FULLPATH#$GEN_JS_PATH/}

echo "Adding module '$MODULE_NAME' from './$RELATIVE_PATH' to bundle."
# Append the export line to our entrypoint file.
# This creates the desired submodule structure.
echo "exports.$MODULE_NAME = require('./$RELATIVE_PATH');" >> "$ENTRYPOINT_FILE"
done

echo "--- Generated entrypoint content: ---"
cat "$ENTRYPOINT_FILE"

echo "--- Setting up node_modules for browserify ---"
ln -s ${node-deps}/node_modules ./node_modules

echo "--- Bundling generated JS with browserify ---"
echo "--- Bundling all generated JS gRPC modules with browserify ---"

for GENERATED_GRPC_FILE in `find "$GEN_JS_PATH" -type f -name "*.js"`
do
browserify --standalone grpc "$GENERATED_GRPC_FILE" > "$BUNDLE_PATH/$(basename $GENERATED_GRPC_FILE)"
done
# Bundle the entrypoint file into a single standalone module.
# The --standalone flag exposes the exports under the 'cardano_node' global variable.
browserify "$ENTRYPOINT_FILE" --standalone cardano_node > "$BUNDLE_PATH/cardano_node_grpc_web_pb.js"

echo "--- Bundling complete. Final files are in $BUNDLE_PATH ---"
ls "$BUNDLE_PATH"
echo "--- Bundling complete. Final file is in $BUNDLE_PATH ---"
ls -l "$BUNDLE_PATH"

runHook postBuild
'';

installPhase = ''
runHook preInstall
mkdir -p "$out"
cp ./bundled-js/*_grpc_web_pb.js "$out/"
mkdir -p $out
# Copy the final, correctly named bundle to the output directory.
cp ./bundled-js/cardano_node_grpc_web_pb.js $out/
runHook postInstall
'';

Expand Down
Loading