Skip to content

Commit

Permalink
Validation for mina_requestPresentation (#3)
Browse files Browse the repository at this point in the history
* feat(providers): validation for presentation request

* chore(providers): add PresentationRequestReturnSchema

* chore(providers): export PresentationRequest type

* chore(utils): export types

* feat(docs): add test for presentation request

* chore(docs): add new sample credential

* feat(providers): validation for mina_signFieldsWithPassphrase

* chore(providers): rename

* feat(docs): add test for mina_signFieldsWithPassphrase

* chore(docs): sample data

* chore(docs): remove result stringify

* chore(docs and providers): change validation and add more sample data

* minor: import different sample credential

* fix(providers): fix validation and add sample data

* chore(docs): add sample request

* chore(utils): update validation

* fix(utils): PresentationRequestSchema claims

* chore(docs): update sample data

* chore(utils): add zkAppAccount to presentation request

* feat: use schemas from mina-credentials

* chore(providers): import mina-credentials/validation, bump mina-credentials

* chore(providers): remove signFieldsWithPassphrase schemas from RPC type

* chore(providers): remove signFieldsWithPassphraseRequest

* chore(providers and utils): remove unused
  • Loading branch information
martonmoro authored Jan 24, 2025
1 parent bb02936 commit a9d6774
Show file tree
Hide file tree
Showing 8 changed files with 1,510 additions and 234 deletions.
1,358 changes: 1,358 additions & 0 deletions apps/docs/src/components/sample-data.ts

Large diffs are not rendered by default.

139 changes: 110 additions & 29 deletions apps/docs/src/components/test-zkapp.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,16 @@ import { createStore } from "@mina-js/connect";
import { useLocalStorage, useObjectState } from "@uidotdev/usehooks";
import { clsx } from "clsx";
import { useState, useSyncExternalStore } from "react";
import {
sampleCredentialRecursiveUpdated,
samplePresentationRequestHttpsFromExampleUpdated,
} from "./sample-data";

const store = createStore();

const sampleCredential = {
version: "v0",
witness: {
type: "simple",
issuer: {
_type: "PublicKey",
value: "B62qqMxueXzenrchT5CKC5eCSmfcbHic9wJd9GEdHVcd9uCWrjPJjHS",
},
issuerSignature: {
_type: "Signature",
value: {
r: "27355434072539307953235904941558417174103383443074165997458891331674091021280",
s: "22156398191479529717864137276005168653180340733374387165875910835098679659803",
},
},
},
credential: {
owner: {
_type: "PublicKey",
value: "B62qqCMx9YvvjhMFVcRXBqHtAbjWWUhyA9HmgpYCehLHTGKgXsxiZpz",
},
data: {
age: {
_type: "Field",
value: "25",
},
},
},
const sampleSignFieldsWithPassphrase = {
fields: ["1", "2", "3"],
passphrase: "1234",
};

export const TestZkApp = () => {
Expand All @@ -42,8 +21,13 @@ export const TestZkApp = () => {
);
const [message, setMessage] = useState("A message to sign");
const [fields, setFields] = useState('["1", "2", "3"]');
const [signFieldsWithPassphraseInput, setSignFieldsWithPassphraseInput] =
useState(JSON.stringify(sampleSignFieldsWithPassphrase, null, 2));
const [credentialInput, setCredentialInput] = useState(
JSON.stringify(sampleCredential, null, 2),
JSON.stringify(sampleCredentialRecursiveUpdated, null, 2),
);
const [presentationRequest, setPresentationRequest] = useState(
JSON.stringify(samplePresentationRequestHttpsFromExampleUpdated, null, 2),
);
const [transactionBody, setTransactionBody] = useObjectState({
to: "B62qnVUL6A53E4ZaGd3qbTr6RCtEZYTu3kTijVrrquNpPo4d3MuJ3nb",
Expand All @@ -58,9 +42,11 @@ export const TestZkApp = () => {
mina_getBalance: "",
mina_sign: "",
mina_signFields: "",
mina_signFieldsWithPassphrase: "",
mina_signTransaction: "",
mina_switchChain: "",
mina_storePrivateCredential: "",
mina_requestPresentation: "",
});
const providers = useSyncExternalStore(store.subscribe, store.getProviders);
const provider = providers.find(
Expand All @@ -85,6 +71,24 @@ export const TestZkApp = () => {
}
};

const requestPresentation = async () => {
if (!provider) return;
try {
const parsedRequest = JSON.parse(presentationRequest);
const { result } = await provider.request({
method: "mina_requestPresentation",
params: [parsedRequest],
});
setResults(() => ({
mina_requestPresentation: result,
}));
} catch (error) {
setResults(() => ({
mina_requestPresentation: `Error: ${error.message}`,
}));
}
};

const fetchAccounts = async () => {
if (!provider) return;
const { result } = await provider.request({
Expand Down Expand Up @@ -132,6 +136,23 @@ export const TestZkApp = () => {
mina_signFields: JSON.stringify(result, undefined, "\t"),
}));
};
const signFieldsWithPassphrase = async () => {
if (!provider) return;
try {
const parsedInput = JSON.parse(signFieldsWithPassphraseInput);
const { result } = await provider.request({
method: "mina_signFieldsWithPassphrase",
params: [parsedInput],
});
setResults(() => ({
mina_signFieldsWithPassphrase: JSON.stringify(result, null, 2),
}));
} catch (error) {
setResults(() => ({
mina_signFieldsWithPassphrase: `Error: ${error.message}`,
}));
}
};
const createNullifier = async () => {
if (!provider) return;
const parsedFields = JSON.parse(fields);
Expand Down Expand Up @@ -479,6 +500,66 @@ export const TestZkApp = () => {
</div>
</div>
</section>
<section className="card bg-neutral">
<div className="card-body gap-4">
<h2 className="card-title">Request Presentation</h2>
<p>mina_requestPresentation</p>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-4">
<textarea
value={presentationRequest}
onChange={(event) => setPresentationRequest(event.target.value)}
className="textarea textarea-bordered h-48 font-mono text-sm"
placeholder="Enter presentation request JSON..."
/>
<button
type="button"
className="btn btn-primary"
onClick={requestPresentation}
>
Request Presentation
</button>
</div>
<label>Result</label>
<textarea
value={results.mina_requestPresentation}
readOnly
className="textarea textarea-bordered h-24 resize-none font-mono"
/>
</div>
</div>
</section>
<section className="card bg-neutral">
<div className="card-body gap-4">
<h2 className="card-title">Sign Fields With Passphrase</h2>
<p>mina_signFieldsWithPassphrase</p>
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-4">
<textarea
value={signFieldsWithPassphraseInput}
onChange={(event) =>
setSignFieldsWithPassphraseInput(event.target.value)
}
className="textarea textarea-bordered h-48 font-mono text-sm"
placeholder="Enter fields and passphrase JSON..."
/>
<button
type="button"
className="btn btn-primary"
onClick={signFieldsWithPassphrase}
>
Sign Fields With Passphrase
</button>
</div>
<label>Result</label>
<textarea
value={results.mina_signFieldsWithPassphrase}
readOnly
className="textarea textarea-bordered h-24 resize-none font-mono"
/>
</div>
</div>
</section>
</main>
);
};
Binary file modified bun.lockb
Binary file not shown.
5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,8 @@
"typescript": "5.5.4"
},
"workspaces": ["packages/*", "apps/*"],
"packageManager": "[email protected]"
"packageManager": "[email protected]",
"resolutions": {
"zod": "3.23.8"
}
}
3 changes: 3 additions & 0 deletions packages/providers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
"test": "bun test",
"cleanup": "rimraf dist .turbo"
},
"dependencies": {
"mina-credentials": "0.2.6"
},
"devDependencies": {
"@mina-js/utils": "workspace:*"
},
Expand Down
30 changes: 28 additions & 2 deletions packages/providers/src/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@ import {
SignedFieldsSchema,
SignedMessageSchema,
SignedTransactionSchema,
StoredCredentialSchema,
TransactionPayloadSchema,
TransactionReceiptSchema,
TypedSendableSchema,
ZkAppCommandPayload,
zkAppAccountSchema,
} from "@mina-js/utils";
import { z } from "zod";

import {
PresentationRequestSchema,
StoredCredentialSchema,
} from "mina-credentials/validation";

export const SwitchChainRequestParams = z
.object({
networkId: z.string(),
Expand Down Expand Up @@ -89,8 +94,21 @@ export const GetStateRequestParamsSchema = RequestWithContext.extend({
export const StorePrivateCredentialRequestParamsSchema =
RequestWithContext.extend({
method: z.literal("mina_storePrivateCredential"),
params: z.array(StoredCredentialSchema),
// biome-ignore lint/suspicious/noExplicitAny: nested types from mina-credentials
params: z.array(StoredCredentialSchema as z.ZodType<any>),
}).strict();
export const PresentationRequestParamsSchema = RequestWithContext.extend({
method: z.literal("mina_requestPresentation"),
params: z.array(
z
.object({
// biome-ignore lint/suspicious/noExplicitAny: nested types from mina-credentials
presentationRequest: PresentationRequestSchema as z.ZodType<any>,
zkAppAccount: zkAppAccountSchema.optional(),
})
.strict(),
),
}).strict();

// Returns
export const AccountsRequestReturnSchema = z
Expand Down Expand Up @@ -183,6 +201,12 @@ export const StorePrivateCredentialReturnSchema = z
result: z.object({ success: z.boolean() }).strict(),
})
.strict();
export const PresentationRequestReturnSchema = z
.object({
method: z.literal("mina_requestPresentation"),
result: z.object({ presentation: z.string() }).strict(),
})
.strict();

export const RpcReturnTypesUnion = z.discriminatedUnion("method", [
AccountsRequestReturnSchema,
Expand All @@ -200,6 +224,7 @@ export const RpcReturnTypesUnion = z.discriminatedUnion("method", [
SetStateRequestReturnSchema,
GetStateRequestReturnSchema,
StorePrivateCredentialReturnSchema,
PresentationRequestReturnSchema,
]);

export const ProviderRequestParamsUnion = z.discriminatedUnion("method", [
Expand All @@ -218,6 +243,7 @@ export const ProviderRequestParamsUnion = z.discriminatedUnion("method", [
SetStateRequestParamsSchema,
GetStateRequestParamsSchema,
StorePrivateCredentialRequestParamsSchema,
PresentationRequestParamsSchema,
]);
export type RpcReturnTypesUnionType = z.infer<typeof RpcReturnTypesUnion>;
export type ResultType<M extends string> = {
Expand Down
2 changes: 0 additions & 2 deletions packages/utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import type {
SignedFieldsSchema,
SignedMessageSchema,
SignedTransactionSchema,
StoredCredentialSchema,
TransactionBodySchema,
TransactionOrZkAppCommandSchema,
TransactionPayloadSchema,
Expand Down Expand Up @@ -57,4 +56,3 @@ export type KlesiaRpcResponseType = z.infer<typeof KlesiaRpcResponseSchema>;
/**
* Private Credential types
*/
export type StoredPrivateCredential = z.infer<typeof StoredCredentialSchema>;
Loading

0 comments on commit a9d6774

Please sign in to comment.