diff --git a/bindings/napi/BeaconStateView.zig b/bindings/napi/BeaconStateView.zig index 9cb30ad07..b9505b131 100644 --- a/bindings/napi/BeaconStateView.zig +++ b/bindings/napi/BeaconStateView.zig @@ -371,37 +371,39 @@ pub fn proposerLookahead(self: *const BeaconStateView) !js.Uint32Array { // pub fn BeaconStateView_getShufflingAtEpoch -pub fn previousDecisionRoot(self: *const BeaconStateView) !js.Uint8Array { +fn rootToHexString(root: *const [32]u8) !js.String { const env = js.env(); + var hex_buf: [66]u8 = undefined; + try @import("hex").rootIntoHex(&hex_buf, root); + return js_types.wrap(js.String, try env.createStringUtf8(&hex_buf)); +} + +pub fn previousDecisionRoot(self: *const BeaconStateView) !js.String { const cached_state = try self.requireState(); const root = cached_state.previousDecisionRoot(); - return js_types.wrap(js.Uint8Array, try sszValueToNapiValue(env, ct.primitive.Root, &root)); + return rootToHexString(&root); } -pub fn currentDecisionRoot(self: *const BeaconStateView) !js.Uint8Array { - const env = js.env(); +pub fn currentDecisionRoot(self: *const BeaconStateView) !js.String { const cached_state = try self.requireState(); const root = cached_state.currentDecisionRoot(); - return js_types.wrap(js.Uint8Array, try sszValueToNapiValue(env, ct.primitive.Root, &root)); + return rootToHexString(&root); } /// Get the next decision root for the state. -pub fn nextDecisionRoot(self: *const BeaconStateView) !js.Uint8Array { - const env = js.env(); +pub fn nextDecisionRoot(self: *const BeaconStateView) !js.String { const cached_state = try self.requireState(); const root = cached_state.nextDecisionRoot(); - return js_types.wrap(js.Uint8Array, try sszValueToNapiValue(env, ct.primitive.Root, &root)); + return rootToHexString(&root); } /// Get the shuffling decision root for a given epoch. -pub fn getShufflingDecisionRoot(self: *const BeaconStateView, epoch_arg: js.Number) !js.Uint8Array { - const env = js.env(); +pub fn getShufflingDecisionRoot(self: *const BeaconStateView, epoch_arg: js.Number) !js.String { const cached_state = try self.requireState(); - const epoch_value: u64 = @intCast(try epoch_arg.toI64()); - const root = st.calculateShufflingDecisionRoot(cached_state.state, epoch_value) catch { - return throwNullAs(js.Uint8Array, "STATE_ERROR", "Failed to calculate shuffling decision root"); + const root = st.calculateShufflingDecisionRoot(cached_state.state, try epoch_arg.toU32()) catch { + return throwNullAs(js.String, "STATE_ERROR", "Failed to calculate shuffling decision root"); }; - return js_types.wrap(js.Uint8Array, try sszValueToNapiValue(env, ct.primitive.Root, &root)); + return rootToHexString(&root); } pub fn previousProposers(self: *const BeaconStateView) !?js.Array { diff --git a/bindings/test/beaconStateView.test.ts b/bindings/test/beaconStateView.test.ts index 6189c07d7..aeb1f4a61 100644 --- a/bindings/test/beaconStateView.test.ts +++ b/bindings/test/beaconStateView.test.ts @@ -397,15 +397,15 @@ describe("BeaconStateView", () => { expect(proposer).toBeLessThan(state.validatorCount); }); - it("decision roots should be 32 bytes each", () => { - expect(state.previousDecisionRoot.length).toBe(32); - expect(state.currentDecisionRoot.length).toBe(32); - expect(state.nextDecisionRoot.length).toBe(32); + it("decision roots should be 66 bytes each", () => { + expect(state.previousDecisionRoot.length).toBe(66); + expect(state.currentDecisionRoot.length).toBe(66); + expect(state.nextDecisionRoot.length).toBe(66); }); - it("getShufflingDecisionRoot should return 32 bytes", () => { + it("getShufflingDecisionRoot should return 66 bytes", () => { const decisionRoot = state.getShufflingDecisionRoot(state.epoch); - expect(decisionRoot.length).toBe(32); + expect(decisionRoot.length).toBe(66); }); }); diff --git a/build.zig.zon b/build.zig.zon index 0563bf940..6bd2fef89 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -298,6 +298,7 @@ .imports = .{ .bls, .bls_options, + .hex, .persistent_merkle_tree, .ssz, .consensus_types,