From 5b2f0c99d58277d349f3242dca2cb4e3c0ed00f5 Mon Sep 17 00:00:00 2001 From: Tomasz Marciniak Date: Sun, 1 Dec 2024 10:26:57 +0100 Subject: [PATCH] feat(accounts): add zkapp command signing --- .../private-key-to-account.spec.ts.snap | 29 +++++++++++++++++++ .../accounts/private-key-to-account.spec.ts | 29 +++++++++++++++++++ .../src/accounts/private-key-to-account.ts | 9 ++++-- packages/accounts/src/types.ts | 5 ++-- packages/utils/src/types.ts | 4 +++ packages/utils/src/validation.ts | 7 ++++- 6 files changed, 77 insertions(+), 6 deletions(-) diff --git a/packages/accounts/src/accounts/__snapshots__/private-key-to-account.spec.ts.snap b/packages/accounts/src/accounts/__snapshots__/private-key-to-account.spec.ts.snap index 4abf2ea..605ab98 100644 --- a/packages/accounts/src/accounts/__snapshots__/private-key-to-account.spec.ts.snap +++ b/packages/accounts/src/accounts/__snapshots__/private-key-to-account.spec.ts.snap @@ -53,3 +53,32 @@ exports[`signs fields 1`] = ` "signature": "7mXCUvhLhFvG9ptrdfNceCrpThkCUyg1ct2z8uwY7eQbKz7UNmhv33TbuDjTznaypJtXRiMJyQWDnf27TH1FSXG7uJHTKAd9", } `; + +exports[`signs a zkapp command 1`] = ` +{ + "data": { + "feePayer": { + "fee": "100000000", + "feePayer": "B62qmWKtvNQTtUqo1LxfEEDLyWMg59cp6U7c4uDC7aqgaCEijSc3Hx5", + "memo": "Test", + "nonce": "0", + "validUntil": "null", + }, + "zkappCommand": { + "accountUpdates": [], + "feePayer": { + "authorization": "7mXWqNfmqMTM5uSCS2xLfsRBLTjGZKTtpEakdsrdQz1EUgYXogSvKxxtfGbBkqQ2mZRMA3uPAM8riaCF56pkqpZBLr2kNBLa", + "body": { + "fee": "100000000", + "nonce": "0", + "publicKey": "B62qmWKtvNQTtUqo1LxfEEDLyWMg59cp6U7c4uDC7aqgaCEijSc3Hx5", + "validUntil": null, + }, + }, + "memo": "E4YVT4x3A9rUhmjkjGn8ZYBLZn7zK4cfvnMtBYZFdWkg37n2s3nrP", + }, + }, + "publicKey": "B62qmWKtvNQTtUqo1LxfEEDLyWMg59cp6U7c4uDC7aqgaCEijSc3Hx5", + "signature": "7mXWqNfmqMTM5uSCS2xLfsRBLTjGZKTtpEakdsrdQz1EUgYXogSvKxxtfGbBkqQ2mZRMA3uPAM8riaCF56pkqpZBLr2kNBLa", +} +`; diff --git a/packages/accounts/src/accounts/private-key-to-account.spec.ts b/packages/accounts/src/accounts/private-key-to-account.spec.ts index 7ed0724..f370925 100644 --- a/packages/accounts/src/accounts/private-key-to-account.spec.ts +++ b/packages/accounts/src/accounts/private-key-to-account.spec.ts @@ -33,6 +33,35 @@ it("signs a transaction", async () => { expect(signedTransaction).toMatchSnapshot(); }); +it("signs a zkapp command", async () => { + const account = privateKeyToAccount({ + privateKey: Test.accounts[0].privateKey, + }); + const command = { + zkappCommand: { + accountUpdates: [], + memo: "E4YM2vTHhWEg66xpj52JErHUBU4pZ1yageL4TVDDpTTSsv8mK6YaH", + feePayer: { + body: { + publicKey: "B62qmWKtvNQTtUqo1LxfEEDLyWMg59cp6U7c4uDC7aqgaCEijSc3Hx5", + fee: "100000000", + validUntil: "100000", + nonce: "1", + }, + authorization: "", + }, + }, + feePayer: { + feePayer: "B62qmWKtvNQTtUqo1LxfEEDLyWMg59cp6U7c4uDC7aqgaCEijSc3Hx5", + fee: "100000000", + nonce: "0", + memo: "Test", + }, + }; + const signedTransaction = await account.signTransaction({ command }); + expect(signedTransaction).toMatchSnapshot(); +}); + it("creates a nullifier", async () => { const account = privateKeyToAccount({ privateKey: Test.accounts[0].privateKey, diff --git a/packages/accounts/src/accounts/private-key-to-account.ts b/packages/accounts/src/accounts/private-key-to-account.ts index 6d3ccb6..c276eb2 100644 --- a/packages/accounts/src/accounts/private-key-to-account.ts +++ b/packages/accounts/src/accounts/private-key-to-account.ts @@ -29,9 +29,14 @@ export function privateKeyToAccount({ async signMessage({ message }) { return SignedMessageSchema.parse(client.signMessage(message, privateKey)); }, - async signTransaction({ transaction }) { + async signTransaction(signable) { + if ("transaction" in signable) { + return SignedTransactionSchema.parse( + client.signTransaction(signable.transaction, privateKey), + ); + } return SignedTransactionSchema.parse( - client.signTransaction(transaction, privateKey), + client.signTransaction(signable.command as never, privateKey), ); }, async createNullifier({ message }) { diff --git a/packages/accounts/src/types.ts b/packages/accounts/src/types.ts index bc23ebc..f8f2be0 100644 --- a/packages/accounts/src/types.ts +++ b/packages/accounts/src/types.ts @@ -4,6 +4,7 @@ import type { SignedFields, SignedMessage, SignedTransaction, + TransactionOrZkAppCommandProperties, } from "@mina-js/utils"; import type { HDKey } from "@scure/bip32"; import type { Simplify } from "type-fest"; @@ -12,7 +13,6 @@ import type { CreateNullifierParamsSchema, SignFieldsParamsSchema, SignMessageParamsSchema, - SignTransactionParamsSchema, } from "./validation"; export enum MinaKeyConst { @@ -81,7 +81,6 @@ export type { HDKey }; export type SignFieldsParams = z.infer; export type SignMessageParams = z.infer; export type CreateNullifierParams = z.infer; -export type SignTransactionParams = z.infer; /** * Signer methods @@ -92,5 +91,5 @@ export type CreateNullifier = ( params: CreateNullifierParams, ) => Promise; export type SignTransaction = ( - params: SignTransactionParams, + params: TransactionOrZkAppCommandProperties, ) => Promise; diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index ff76188..fc71c49 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -14,6 +14,7 @@ import type { SignedTransactionSchema, StoredCredentialSchema, TransactionBodySchema, + TransactionOrZkAppCommandSchema, TransactionPayloadSchema, TransactionReceiptSchema, ZkAppCommandBodySchema, @@ -32,6 +33,9 @@ export type TransactionPayload = z.infer; export type PartialTransaction = z.infer; export type ZkAppCommandBody = z.infer; export type ZkAppCommandProperties = z.infer; +export type TransactionOrZkAppCommandProperties = z.infer< + typeof TransactionOrZkAppCommandSchema +>; export type Sendable = z.infer; /** diff --git a/packages/utils/src/validation.ts b/packages/utils/src/validation.ts index b3cf68a..44d2188 100644 --- a/packages/utils/src/validation.ts +++ b/packages/utils/src/validation.ts @@ -79,6 +79,11 @@ export const ZkAppCommandPayload = z }) .strict(); +export const TransactionOrZkAppCommandSchema = z.union([ + TransactionPayloadSchema, + ZkAppCommandPayload, +]); + /** * Return type schemas */ @@ -122,7 +127,7 @@ export const NullifierSchema = z export const SignedTransactionSchema = z .object({ - signature: SignatureSchema, + signature: z.union([SignatureSchema, z.string()]), publicKey: PublicKeySchema, data: z.union([TransactionBodySchema, ZkAppCommandBodySchema]), })