Skip to content

Commit

Permalink
Merge pull request #70 from NillionNetwork/feat/signature-examples
Browse files Browse the repository at this point in the history
chore: add signatures examples.
  • Loading branch information
pablojhl authored Jan 22, 2025
2 parents 9717ba9 + a7aac2a commit c7367cc
Show file tree
Hide file tree
Showing 10 changed files with 217 additions and 12 deletions.
2 changes: 1 addition & 1 deletion client-react-hooks/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "@nillion/client-react-hooks",
"license": "MIT",
"author": "[email protected]",
"version": "0.3.0-rc.0",
"version": "0.3.0-rc.1",
"homepage": "https://nillion.pub/client-ts",
"repository": {
"type": "git",
Expand Down
3 changes: 2 additions & 1 deletion client-react-hooks/src/use-nil-update-permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useMutation } from "@tanstack/react-query";
import { type UseNilHook, nilHookBaseResult } from "./nil-hook-base";

interface ExecuteArgs {
id?: Uuid;
permissions: UpdatePermissionsBuilder;
}
type ExecuteResult = Uuid;
Expand All @@ -11,7 +12,7 @@ type useNilUpdatePermissions = UseNilHook<ExecuteArgs, ExecuteResult>;

export const useNilUpdatePermissions = (): useNilUpdatePermissions => {
const mutationFn = async (args: ExecuteArgs): Promise<ExecuteResult> => {
return args.permissions.build().invoke();
return args.permissions.valuesId(args.id).build().invoke();
};

const mutate = useMutation({
Expand Down
14 changes: 9 additions & 5 deletions client-vms/tests/signature.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
type Uuid,
ValuesPermissionsBuilder,
} from "#/types";
import { type VmClient, VmClientBuilder } from "#/vm";
import { UpdatePermissionsBuilder, type VmClient, VmClientBuilder } from "#/vm";
import { Env, PrivateKeyPerSuite } from "./helpers";

describe("Signature", () => {
Expand Down Expand Up @@ -44,19 +44,23 @@ describe("Signature", () => {

let privateKeyStoreId: Uuid;
it("store private key", async () => {
const permissions = ValuesPermissionsBuilder.defaultOwner(client.id)
.grantCompute(client.id, tecdsaProgramId)
.build();
privateKeyStoreId = await client
.storeValues()
.ttl(1)
.value(tecdsaKeyName, NadaValue.new_ecdsa_private_key(privateKey))
.permissions(permissions)
.build()
.invoke();
expect(privateKeyStoreId).toHaveLength(36);
});

it("update private key permissions", async () => {
const permissions = UpdatePermissionsBuilder.init(client)
.valuesId(privateKeyStoreId)
.grantCompute(client.id, tecdsaProgramId)
.build();
await permissions.invoke();
});

it("retrieve private key", async () => {
const data = await client
.retrieveValues()
Expand Down
57 changes: 57 additions & 0 deletions examples-nextjs/app/components/ecdsa-sign.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
"use client";

import { useNilInvokeCompute, useNillion } from "@nillion/client-react-hooks";
import { Uuid } from "@nillion/client-vms";
import { type ChangeEvent, type FC, useState } from "react";

export const EcdsaSign: FC = () => {
const { client } = useNillion();
const mutation = useNilInvokeCompute();
const [id, setId] = useState("");
const isValidUuid = Uuid.safeParse(id).success;

const tecdsaProgramId = "builtin/tecdsa_sign";

function handleChange(event: ChangeEvent<HTMLInputElement>): void {
setId(event.target.value);
}

function handleClick(): void {
// Assumes addition_division.py
const options = {
programId: tecdsaProgramId,
inputBindings: [
{ party: "tecdsa_key_party", user: client.id },
{ party: "tecdsa_digest_message_party", user: client.id },
],
outputBindings: [{ party: "tecdsa_output_party", users: [client.id] }],
valueIds: [id],
computeTimeValues: [],
};
mutation.execute(options);
}

let resultId = "";
if (mutation.isSuccess) {
resultId = mutation.data;
} else if (mutation.isError) {
resultId = mutation.error.message;
}

return (
<div>
<h2>Invoke Compute</h2>
<ol>
<li>Status: {mutation.status}</li>
<li> Program id: {tecdsaProgramId}</li>
<li>
Id: <input type="text" value={id} onChange={handleChange} />
</li>
<li>Compute result id: {resultId}</li>
</ol>
<button type="button" disabled={!isValidUuid} onClick={handleClick}>
Execute
</button>
</div>
);
};
7 changes: 6 additions & 1 deletion examples-nextjs/app/components/retrieve-values.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { useNilRetrieveValues } from "@nillion/client-react-hooks";
import { Uuid } from "@nillion/client-vms";
import { bytesToHex } from "@noble/hashes/utils";
import { type ChangeEvent, type FC, useState } from "react";

export const RetrieveValues: FC = () => {
Expand All @@ -15,7 +16,11 @@ export const RetrieveValues: FC = () => {
if (mutation.isSuccess) {
// stringify cannot handle BigInts
data = data = JSON.stringify(mutation.data, (_, v) =>
typeof v === "bigint" ? v.toString() : v,
typeof v === "bigint"
? v.toString()
: v instanceof Uint8Array
? bytesToHex(v)
: v,
);
} else if (mutation.isError) {
data = mutation.error.message;
Expand Down
65 changes: 65 additions & 0 deletions examples-nextjs/app/components/store-ecdsa-values.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
"use client";

import { useNilStoreValues } from "@nillion/client-react-hooks";
import { NadaValue } from "@nillion/client-vms";
import { secp256k1 } from "@noble/curves/secp256k1";
import { sha256 } from "@noble/hashes/sha2";
import { bytesToHex } from "@noble/hashes/utils";
import type { FC } from "react";

export const StoreSignatureValues: FC = () => {
const storeValuesMutation = useNilStoreValues();

let id = "";
if (storeValuesMutation.isSuccess) {
id = storeValuesMutation.data;
} else if (storeValuesMutation.isError) {
id = storeValuesMutation.error.message;
}

const privateKey: Uint8Array = secp256k1.utils.randomPrivateKey();
const digestMessage = sha256("A deep message with a deep number: 42");

const options = {
values: [
{
name: "tecdsa_private_key",
value: NadaValue.new_ecdsa_private_key(privateKey),
},
{
name: "tecdsa_digest_message",
value: NadaValue.new_ecdsa_digest_message(digestMessage),
},
],
ttl: 1,
};

const stringifiedOptions = JSON.stringify({
...options,
values: options.values.map(({ name, value }) => ({
name,
value: {
type: value.type_name(),
value: bytesToHex(value.to_byte_array()),
},
})),
});

function handleClick(): void {
storeValuesMutation.execute(options);
}

return (
<div>
<h2>Store Signature Values</h2>
<ol>
<li>Status: {storeValuesMutation.status}</li>
<li>Options: {stringifiedOptions}</li>
<li>Store Id: {id}</li>
</ol>
<button type="button" onClick={handleClick}>
Execute
</button>
</div>
);
};
49 changes: 49 additions & 0 deletions examples-nextjs/app/components/update-ecdsa-permissions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"use client";

import {
useNilUpdatePermissions,
useNillion,
} from "@nillion/client-react-hooks";
import { UpdatePermissionsBuilder, Uuid } from "@nillion/client-vms";
import { type ChangeEvent, type FC, useMemo, useState } from "react";

export const UpdateEcdsaPermissions: FC = () => {
const { client } = useNillion();
const mutation = useNilUpdatePermissions();
const [id, setId] = useState("");
const isValidUuid = Uuid.safeParse(id).success;

const tecdsaProgramId = "builtin/tecdsa_sign";

const permissions = useMemo(() => {
return UpdatePermissionsBuilder.init(client).grantCompute(
client.id,
tecdsaProgramId,
);
}, [client.id]);

function handleChange(event: ChangeEvent<HTMLInputElement>): void {
setId(event.target.value);
}

function handleClick(): void {
const options = { id, permissions };
mutation.execute(options);
}

return (
<div>
<h2>Update ECDSA Sign Permissions</h2>
<ol>
<li>Status: {mutation.status}</li>
<li>New permissions: {JSON.stringify(permissions.toObject())}</li>
<li>
Id: <input type="text" value={id} onChange={handleChange} />
</li>
</ol>
<button type="button" disabled={!isValidUuid} onClick={handleClick}>
Execute
</button>
</div>
);
};
6 changes: 6 additions & 0 deletions examples-nextjs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@ import { useEffect, useState } from "react";
import { AccountBalance } from "#/components/account-balance";
import { AddFunds } from "#/components/add-funds";
import { DeleteValues } from "#/components/delete-values";
import { EcdsaSign } from "#/components/ecdsa-sign";
import { InvokeCompute } from "#/components/invoke-compute";
import { OverwritePermissions } from "#/components/overwrite-permissions";
import { PoolStatus } from "#/components/pool-status";
import { RetrieveComputeResults } from "#/components/retrieve-compute-results";
import { RetrievePermissions } from "#/components/retrieve-permissions";
import { RetrieveValues } from "#/components/retrieve-values";
import { StoreSignatureValues } from "#/components/store-ecdsa-values";
import { StoreProgram } from "#/components/store-program";
import { StoreValues } from "#/components/store-values";
import { UpdateEcdsaPermissions } from "#/components/update-ecdsa-permissions";
import { UpdatePermissions } from "#/components/update-permissions";
import { UpdateValues } from "#/components/update-values";

Expand Down Expand Up @@ -55,6 +58,9 @@ export default function Home() {
<StoreProgram />
<InvokeCompute />
<RetrieveComputeResults />
<StoreSignatureValues />
<UpdateEcdsaPermissions />
<EcdsaSign />
</NillionProvider>
);
}
5 changes: 4 additions & 1 deletion examples-nextjs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nillion/examples-nextjs",
"version": "0.3.0",
"version": "0.3.1",
"private": true,
"scripts": {
"dev": "next dev",
Expand All @@ -12,6 +12,9 @@
"dependencies": {
"@nillion/client-react-hooks": "workspace:*",
"@nillion/client-vms": "workspace:*",
"@noble/curves": "^1.6.0",
"@noble/hashes": "^1.5.0",
"@noble/secp256k1": "^2.1.0",
"next": "^15.0.3",
"react": "^18.3.1",
"react-dom": "^18.3.1"
Expand Down
21 changes: 18 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit c7367cc

Please sign in to comment.