From fdb1786d9bf7fc6c7c46127b620a7f847566fb9a Mon Sep 17 00:00:00 2001 From: Tomek Marciniak Date: Mon, 4 Nov 2024 13:45:19 +0100 Subject: [PATCH] feat(klesia sdk): slim down --- .github/workflows/ci.yml | 2 +- apps/klesia/docs/index.txt | 5 -- apps/klesia/docs/rpc.txt | 45 ------------ apps/klesia/package.json | 10 +-- apps/klesia/src/index.ts | 69 +++++++++--------- apps/klesia/src/schema.ts | 105 --------------------------- apps/klesia/src/utils/node.ts | 2 +- bun.lockb | Bin 337760 -> 338024 bytes packages/klesia-sdk/package.json | 4 +- packages/klesia-sdk/src/client.ts | 10 +-- packages/providers/package.json | 5 +- packages/providers/src/validation.ts | 4 +- packages/utils/package.json | 4 +- packages/utils/src/types.ts | 10 +++ packages/utils/src/validation.ts | 95 ++++++++++++++++++++++++ 15 files changed, 161 insertions(+), 209 deletions(-) delete mode 100644 apps/klesia/docs/index.txt delete mode 100644 apps/klesia/docs/rpc.txt delete mode 100644 apps/klesia/src/schema.ts diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4271f3..fecb90c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,4 +12,4 @@ jobs: - run: bun i --no-save - run: bun run build - run: bun run test - - run: bunx pkg-pr-new publish './packages/klesia-sdk' './packages/accounts' './packages/connect' './packages/providers' './packages/utils' './apps/klesia' + - run: bunx pkg-pr-new publish './packages/klesia-sdk' './packages/accounts' './packages/connect' './packages/providers' './packages/utils' diff --git a/apps/klesia/docs/index.txt b/apps/klesia/docs/index.txt deleted file mode 100644 index d26e16d..0000000 --- a/apps/klesia/docs/index.txt +++ /dev/null @@ -1,5 +0,0 @@ -Klesia RPC is a JSON-RPC 2.0 wrapper over common Mina Protocol tools and services. The intention is to provide an outstanding Developer Experience for Mina Protocol's zkApp Developers. - -## TypeScript SDK - -There is a TypeScript SDK available for Klesia RPC. It is available on npm as `@mina-js/klesia-sdk`. diff --git a/apps/klesia/docs/rpc.txt b/apps/klesia/docs/rpc.txt deleted file mode 100644 index d332161..0000000 --- a/apps/klesia/docs/rpc.txt +++ /dev/null @@ -1,45 +0,0 @@ -## Methods - -### mina_getTransactionCount - -Returns the number of transactions sent from an address. Usually you may want to use this number to determine the nonce for the next transaction. - -#### Parameters - -Array of strings: -- `publicKey` - Address to check for transaction count. - ---- - -### mina_getBalance - -Returns the balance of the account of given address. - -#### Parameters - -Array of strings: -- `publicKey` - Address to check for transaction count. - ---- - -### mina_blockHash - -Returns the hash of the most recent block. - ---- - -### mina_chainId - -Returns the currently configured chain ID. - ---- - -### mina_sendTransaction - -Broadcasts a signed transaction to the network. - -#### Parameters - -Array of strings: -- `input` - Signed transaction or zkApp input. -- `type` - Transaction type. Can be `payment`, `delegation`, or `zkapp`. diff --git a/apps/klesia/package.json b/apps/klesia/package.json index 82b894b..b89a720 100644 --- a/apps/klesia/package.json +++ b/apps/klesia/package.json @@ -5,10 +5,6 @@ "module": "dist/index.js", "types": "dist/index.d.ts", "exports": { - "./schema": { - "types": "./dist/schema.d.ts", - "default": "./dist/schema.js" - }, ".": { "types": "./dist/index.d.ts", "default": "./dist/index.js" @@ -21,15 +17,17 @@ "test": "bun test --rerun-each 3", "cleanup": "rimraf dist .turbo node_modules" }, + "devDependencies": { + "@mina-js/utils": "workspace:*" + }, "dependencies": { "@hono/node-server": "^1.12.2", "@hono/zod-openapi": "^0.16.0", - "@mina-js/utils": "workspace:*", "@urql/core": "^5.0.6", "bigint-quantile": "^0.0.2", "dayjs": "^1.11.13", "dotenv": "^16.4.5", - "hono": "^4.5.10", + "hono": "4.6.9", "hono-rate-limiter": "^0.4.0", "nanoid": "^5.0.7", "ofetch": "^1.3.4", diff --git a/apps/klesia/src/index.ts b/apps/klesia/src/index.ts index dcc199f..6d8d1ad 100644 --- a/apps/klesia/src/index.ts +++ b/apps/klesia/src/index.ts @@ -1,15 +1,17 @@ import { getConnInfo } from "@hono/node-server/conninfo"; import { OpenAPIHono, createRoute } from "@hono/zod-openapi"; -import { PublicKeySchema } from "@mina-js/utils"; +import { + KlesiaRpcMethod, + KlesiaRpcMethodSchema, + KlesiaRpcResponseSchema, + PublicKeySchema, +} from "@mina-js/utils"; import { rateLimiter } from "hono-rate-limiter"; import { cors } from "hono/cors"; import { logger } from "hono/logger"; import { nanoid } from "nanoid"; import { match } from "ts-pattern"; -import mainDocs from "../docs/index.txt"; -import rpcDocs from "../docs/rpc.txt"; import { mina } from "./methods/mina"; -import { RpcMethod, RpcMethodSchema, RpcResponseSchema } from "./schema"; import { buildResponse } from "./utils/build-response"; export const api = new OpenAPIHono(); @@ -35,22 +37,22 @@ api.doc("/api/openapi", { info: { version: "1.0.0", title: "Klesia RPC", - description: mainDocs, }, }); const rpcRoute = createRoute({ method: "post", path: "/api", - description: rpcDocs, request: { - body: { content: { "application/json": { schema: RpcMethodSchema } } }, + body: { + content: { "application/json": { schema: KlesiaRpcMethodSchema } }, + }, }, responses: { 200: { content: { "application/json": { - schema: RpcResponseSchema, + schema: KlesiaRpcResponseSchema, }, }, description: "JSON-RPC response.", @@ -59,10 +61,10 @@ const rpcRoute = createRoute({ }); export const klesiaRpcRoute = api.openapi(rpcRoute, async ({ req, json }) => { - const body = req.valid("json"); + const body = KlesiaRpcMethodSchema.parse(await req.json()); return match(body) .with( - { method: RpcMethod.enum.mina_getTransactionCount }, + { method: KlesiaRpcMethod.enum.mina_getTransactionCount }, async ({ params }) => { const [publicKey] = params; const result = await mina.getTransactionCount({ @@ -76,14 +78,17 @@ export const klesiaRpcRoute = api.openapi(rpcRoute, async ({ req, json }) => { ); }, ) - .with({ method: RpcMethod.enum.mina_getBalance }, async ({ params }) => { - const [publicKey] = params; - const result = await mina.getBalance({ - publicKey: PublicKeySchema.parse(publicKey), - }); - return json(buildResponse({ result }), 200); - }) - .with({ method: RpcMethod.enum.mina_blockHash }, async () => { + .with( + { method: KlesiaRpcMethod.enum.mina_getBalance }, + async ({ params }) => { + const [publicKey] = params; + const result = await mina.getBalance({ + publicKey: PublicKeySchema.parse(publicKey), + }); + return json(buildResponse({ result }), 200); + }, + ) + .with({ method: KlesiaRpcMethod.enum.mina_blockHash }, async () => { if (process.env.MINA_NETWORK === "zeko_devnet") { return json( buildResponse({ @@ -98,12 +103,12 @@ export const klesiaRpcRoute = api.openapi(rpcRoute, async ({ req, json }) => { const result = await mina.blockHash(); return json(buildResponse({ result }), 200); }) - .with({ method: RpcMethod.enum.mina_chainId }, async () => { + .with({ method: KlesiaRpcMethod.enum.mina_chainId }, async () => { const result = await mina.chainId(); return json(buildResponse({ result }), 200); }) .with( - { method: RpcMethod.enum.mina_sendTransaction }, + { method: KlesiaRpcMethod.enum.mina_sendTransaction }, async ({ params }) => { const [signedTransaction, type] = params; const result = await mina.sendTransaction({ signedTransaction, type }); @@ -115,21 +120,17 @@ export const klesiaRpcRoute = api.openapi(rpcRoute, async ({ req, json }) => { ); }, ) - .with({ method: RpcMethod.enum.mina_getAccount }, async ({ params }) => { - const [publicKey] = params; - const result = await mina.getAccount({ - publicKey: PublicKeySchema.parse(publicKey), - }); - return json(buildResponse({ result }), 200); - }) + .with( + { method: KlesiaRpcMethod.enum.mina_getAccount }, + async ({ params }) => { + const [publicKey] = params; + const result = await mina.getAccount({ + publicKey: PublicKeySchema.parse(publicKey), + }); + return json(buildResponse({ result }), 200); + }, + ) .exhaustive(); }); export type KlesiaRpc = typeof klesiaRpcRoute; -export { - KlesiaNetwork, - RpcMethod, - type RpcMethodType, - type RpcResponseType, - type RpcErrorType, -} from "./schema"; diff --git a/apps/klesia/src/schema.ts b/apps/klesia/src/schema.ts deleted file mode 100644 index 9f2070a..0000000 --- a/apps/klesia/src/schema.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { PublicKeySchema } from "@mina-js/utils"; -import { z } from "zod"; - -export const KlesiaNetwork = z.enum(["devnet", "mainnet", "zeko_devnet"]); -export const PublicKeyParamsSchema = z.array(PublicKeySchema).length(1); -export const EmptyParamsSchema = z.array(z.string()).length(0).optional(); -export const SignatureSchema = z.union([ - z.object({ - rawSignature: z.string(), - }), - z.object({ field: z.string(), scalar: z.string() }), -]); -export const SendTransactionSchema = z.tuple([ - z.any(), - z.enum(["payment", "delegation", "zkapp"]), -]); - -export const RpcMethod = z.enum([ - "mina_getTransactionCount", - "mina_getBalance", - "mina_blockHash", - "mina_chainId", - "mina_sendTransaction", - "mina_getAccount", -]); -export type RpcMethodType = z.infer; - -export const RpcMethodSchema = z.discriminatedUnion("method", [ - z.object({ - method: z.literal(RpcMethod.enum.mina_getTransactionCount), - params: PublicKeyParamsSchema, - }), - z.object({ - method: z.literal(RpcMethod.enum.mina_getBalance), - params: PublicKeyParamsSchema, - }), - z.object({ - method: z.literal(RpcMethod.enum.mina_blockHash), - params: EmptyParamsSchema, - }), - z.object({ - method: z.literal(RpcMethod.enum.mina_chainId), - params: EmptyParamsSchema, - }), - z.object({ - method: z.literal(RpcMethod.enum.mina_sendTransaction), - params: SendTransactionSchema, - }), - z.object({ - method: z.literal(RpcMethod.enum.mina_getAccount), - params: PublicKeyParamsSchema, - }), -]); - -export type RpcRequestType = z.infer; - -export const JsonRpcResponse = z.object({ - jsonrpc: z.literal("2.0"), -}); - -export const RpcError = z.object({ - code: z.number(), - message: z.string(), -}); - -export type RpcErrorType = z.infer; - -export const ErrorSchema = JsonRpcResponse.extend({ - error: RpcError, -}); - -export const RpcResponseSchema = z.union([ - z.discriminatedUnion("method", [ - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_getTransactionCount), - result: z.string(), - }), - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_getBalance), - result: z.string(), - }), - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_blockHash), - result: z.string(), - }), - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_chainId), - result: z.string(), - }), - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_sendTransaction), - result: z.string(), - }), - JsonRpcResponse.extend({ - method: z.literal(RpcMethod.enum.mina_getAccount), - result: z.object({ - nonce: z.string(), - balance: z.string(), - }), - }), - ]), - ErrorSchema, -]); - -export type RpcResponseType = z.infer; diff --git a/apps/klesia/src/utils/node.ts b/apps/klesia/src/utils/node.ts index 0125a87..889a62a 100644 --- a/apps/klesia/src/utils/node.ts +++ b/apps/klesia/src/utils/node.ts @@ -1,7 +1,7 @@ +import { KlesiaNetwork } from "@mina-js/utils"; import { Client, cacheExchange, fetchExchange } from "@urql/core"; import { match } from "ts-pattern"; import { z } from "zod"; -import { KlesiaNetwork } from "../schema"; const MINA_NETWORK = KlesiaNetwork.parse(process.env.MINA_NETWORK ?? "devnet"); const NODE_API_DEVNET = z diff --git a/bun.lockb b/bun.lockb index 4b2b59cf8bd1192e9c21ba9577853278636425f1..34fa9dcede2412839ede072257482bd01c4606af 100755 GIT binary patch delta 48257 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 delta 48171 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 { ) .exhaustive(); const rpc = jsonrpc(net, baseUrl); - const request = async (req: RpcRequestType) => { + const request = async (req: KlesiaRpcRequestType) => { const params = req.params ?? []; - const json: Extract["result"] = + const json: Extract["result"] = await rpc.call(req.method, ...params); return json; }; diff --git a/packages/providers/package.json b/packages/providers/package.json index aeeef38..e5c9f36 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -16,9 +16,8 @@ "test": "bun test", "cleanup": "rimraf dist .turbo" }, - "dependencies": { - "@mina-js/utils": "workspace:*", - "zod": "3.23.8" + "devDependencies": { + "@mina-js/utils": "workspace:*" }, "peerDependencies": { "typescript": "^5.0.0" diff --git a/packages/providers/src/validation.ts b/packages/providers/src/validation.ts index a8834f7..9fe3175 100644 --- a/packages/providers/src/validation.ts +++ b/packages/providers/src/validation.ts @@ -4,12 +4,12 @@ import { NetworkId, NullifierSchema, PublicKeySchema, - SendableSchema, SignedFieldsSchema, SignedMessageSchema, SignedTransactionSchema, TransactionPayloadSchema, TransactionReceiptSchema, + TypedSendableSchema, ZkAppCommandPayload, } from "@mina-js/utils"; import { z } from "zod"; @@ -63,7 +63,7 @@ export const SignTransactionRequestParamsSchema = RequestWithContext.extend({ }).strict(); export const SendTransactionRequestParamsSchema = RequestWithContext.extend({ method: z.literal("mina_sendTransaction"), - params: z.tuple([SendableSchema, z.enum(["payment", "delegation", "zkapp"])]), + params: TypedSendableSchema, }).strict(); export const CreateNullifierRequestParamsSchema = RequestWithContext.extend({ method: z.literal("mina_createNullifier"), diff --git a/packages/utils/package.json b/packages/utils/package.json index 89e1d75..c363571 100644 --- a/packages/utils/package.json +++ b/packages/utils/package.json @@ -17,7 +17,9 @@ "cleanup": "rimraf dist .turbo" }, "dependencies": { - "mina-signer": "3.0.7", + "mina-signer": "3.0.7" + }, + "devDependencies": { "zod": "3.23.8" }, "peerDependencies": { diff --git a/packages/utils/src/types.ts b/packages/utils/src/types.ts index c43f005..b523f96 100644 --- a/packages/utils/src/types.ts +++ b/packages/utils/src/types.ts @@ -1,5 +1,8 @@ import type { z } from "zod"; import type { + KlesiaRpcMethod, + KlesiaRpcMethodSchema, + KlesiaRpcResponseSchema, LiteralSchema, NullifierSchema, PartialTransactionSchema, @@ -38,3 +41,10 @@ export type SignedFields = z.infer; export type Nullifier = z.infer; export type SignedTransaction = z.infer; export type TransactionReceipt = z.infer; + +/** + * Klesia RPC types + */ +export type KlesiaRpcMethodType = z.infer; +export type KlesiaRpcRequestType = z.infer; +export type KlesiaRpcResponseType = z.infer; diff --git a/packages/utils/src/validation.ts b/packages/utils/src/validation.ts index 3872518..64bc7b1 100644 --- a/packages/utils/src/validation.ts +++ b/packages/utils/src/validation.ts @@ -31,6 +31,8 @@ export const PrivateKeySchema = z.string().length(52); export const NetworkId = z.string().regex(networkPattern); +export const KlesiaNetwork = z.enum(["devnet", "mainnet", "zeko_devnet"]); + export const FeePayerSchema = z .object({ feePayer: PublicKeySchema, @@ -145,3 +147,96 @@ export const SendableSchema = z.union([ SendTransactionBodySchema, SendZkAppBodySchema, ]); + +export const TypedSendableSchema = z.tuple([ + SendableSchema, + z.enum(["payment", "delegation", "zkapp"]), +]); + +export const KlesiaRpcMethod = z.enum([ + "mina_getTransactionCount", + "mina_getBalance", + "mina_blockHash", + "mina_chainId", + "mina_sendTransaction", + "mina_getAccount", +]); + +export const PublicKeyParamsSchema = z.tuple([PublicKeySchema]); + +export const EmptyParamsSchema = z.tuple([]).optional(); + +export const KlesiaRpcMethodSchema = z.discriminatedUnion("method", [ + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_getTransactionCount), + params: PublicKeyParamsSchema, + }), + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_getBalance), + params: PublicKeyParamsSchema, + }), + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_blockHash), + params: EmptyParamsSchema, + }), + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_chainId), + params: EmptyParamsSchema, + }), + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_sendTransaction), + params: TypedSendableSchema, + }), + z.object({ + method: z.literal(KlesiaRpcMethod.enum.mina_getAccount), + params: PublicKeyParamsSchema, + }), +]); + +export const JsonRpcResponse = z.object({ + jsonrpc: z.literal("2.0"), +}); + +export const RpcError = z.object({ + code: z.number(), + message: z.string(), +}); + +export type RpcErrorType = z.infer; + +export const ErrorSchema = JsonRpcResponse.extend({ + error: RpcError, +}); + +export const KlesiaRpcResponseSchema = z.union([ + z.discriminatedUnion("method", [ + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_getTransactionCount), + result: z.string(), + }), + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_getBalance), + result: z.string(), + }), + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_blockHash), + result: z.string(), + }), + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_chainId), + result: z.string(), + }), + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_sendTransaction), + result: z.string(), + }), + JsonRpcResponse.extend({ + method: z.literal(KlesiaRpcMethod.enum.mina_getAccount), + result: z.object({ + nonce: z.string(), + balance: z.string(), + }), + }), + ]), + ErrorSchema, +]);