diff --git a/apps/extension/index.html b/apps/extension/index.html index 2209e775..fa6e8467 100644 --- a/apps/extension/index.html +++ b/apps/extension/index.html @@ -22,6 +22,7 @@ +
diff --git a/apps/extension/manifest.ts b/apps/extension/manifest.ts index fe576768..37c2798d 100644 --- a/apps/extension/manifest.ts +++ b/apps/extension/manifest.ts @@ -32,10 +32,13 @@ export const manifest: chrome.runtime.ManifestV3 = { ], web_accessible_resources: [ { - resources: ["rpc.js"], + resources: ["rpc.js", "sandbox.html", "sandbox.js"], matches: rpcMatches, }, ], + sandbox: { + pages: ["sandbox.html"], + }, host_permissions: ["https://*/*"], commands: { _execute_action: { @@ -48,4 +51,14 @@ export const manifest: chrome.runtime.ManifestV3 = { description: "Open the Pallad extension", }, }, + content_security_policy: { + sandbox: + "sandbox allow-scripts allow-forms allow-popups allow-modals; script-src 'self' 'unsafe-eval' 'wasm-unsafe-eval'; worker-src blob: 'self'; child-src blob: 'self'", + }, + cross_origin_embedder_policy: { + value: "require-corp", + }, + cross_origin_opener_policy: { + value: "same-origin", + }, } diff --git a/apps/extension/package.json b/apps/extension/package.json index 3a1969ff..f38d0efa 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -15,30 +15,28 @@ "test:e2e:ui": "playwright test --ui" }, "dependencies": { - "@mina-js/providers": "https://pkg.pr.new/palladians/mina-js/@mina-js/providers@a51d3b4", - "@palladxyz/common": "workspace:*", - "@palladxyz/features": "workspace:*", - "@palladxyz/key-management": "workspace:*", - "@palladxyz/vault": "workspace:*", - "@palladxyz/web-provider": "workspace:*", + "@mina-js/providers": "https://pkg.pr.new/palladians/mina-js/@mina-js/providers@3", + "@palladco/common": "workspace:*", + "@palladco/features": "workspace:*", + "@palladco/key-management": "workspace:*", + "@palladco/vault": "workspace:*", + "@palladco/web-provider": "workspace:*", "@plasmohq/messaging": "0.6.2", "buffer": "6.0.3", + "mina-credentials": "^0.2.7", "mitt": "3.0.1", "next-themes": "0.3.0", + "o1js": "2.2.0", "p-debounce": "4.0.0", "react": "18.3.1", "react-dom": "18.3.1", "serialize-error": "11.0.3", - "tailwindcss-animate": "1.0.7", - "vite-plugin-node-stdlib-browser": "0.2.1", + "ts-pattern": "^5.5.0", "webext-bridge": "6.0.1", "webextension-polyfill": "0.12.0", "zod": "3.23.8" }, "devDependencies": { - "@esbuild-plugins/node-globals-polyfill": "0.2.3", - "@esbuild-plugins/node-modules-polyfill": "0.2.2", - "@originjs/vite-plugin-commonjs": "1.0.3", "@playwright/test": "1.45.3", "@total-typescript/ts-reset": "0.5.1", "@tsconfig/vite-react": "3.0.2", @@ -47,20 +45,10 @@ "@types/react-dom": "18.3.0", "@types/webextension-polyfill": "0.10.7", "@vitejs/plugin-react-swc": "3.7.0", - "dedent": "1.5.3", - "path": "0.12.7", - "rollup-plugin-node-polyfills": "0.2.1", - "rollup-plugin-polyfill-node": "0.13.0", - "type-fest": "4.23.0", "vite": "5.3.5", - "vite-plugin-commonjs": "0.10.1", "vite-plugin-node-polyfills": "0.17.0", - "vite-plugin-require-transform": "1.0.21", "vite-plugin-svgr": "4.2.0", - "vite-plugin-top-level-await": "1.4.2", - "vite-plugin-wasm": "3.3.0", "vite-plugin-web-extension": "4.1.6", - "web-ext": "8.2.0", - "write-json-file": "6.0.0" + "web-ext": "8.2.0" } } diff --git a/apps/extension/postcss.config.mjs b/apps/extension/postcss.config.mjs index 8e0202ee..917debfd 100644 --- a/apps/extension/postcss.config.mjs +++ b/apps/extension/postcss.config.mjs @@ -1,3 +1,3 @@ -import postcssConfig from "@palladxyz/features/postcss.config.mjs" +import postcssConfig from "@palladco/features/postcss.config.mjs" export default postcssConfig diff --git a/apps/extension/prompt.html b/apps/extension/prompt.html index da43c9b4..046b1d82 100644 --- a/apps/extension/prompt.html +++ b/apps/extension/prompt.html @@ -18,6 +18,7 @@ +
diff --git a/apps/extension/sandbox.html b/apps/extension/sandbox.html new file mode 100644 index 00000000..3896516c --- /dev/null +++ b/apps/extension/sandbox.html @@ -0,0 +1,13 @@ + + + + + + Pallad + + + +
+ + + diff --git a/apps/extension/src/app.tsx b/apps/extension/src/app.tsx index 2f460632..77eeeda4 100644 --- a/apps/extension/src/app.tsx +++ b/apps/extension/src/app.tsx @@ -1,7 +1,7 @@ -import "@palladxyz/features/dist/index.css" +import "@palladco/features/dist/index.css" import "./assets/app.css" -import { Router } from "@palladxyz/features" +import { Router } from "@palladco/features" import { ThemeProvider } from "next-themes" import { useEffect } from "react" diff --git a/apps/extension/src/background/handlers/wallet.ts b/apps/extension/src/background/handlers/wallet.ts index cc4ec202..d76225d6 100644 --- a/apps/extension/src/background/handlers/wallet.ts +++ b/apps/extension/src/background/handlers/wallet.ts @@ -1,6 +1,6 @@ -import { useVault } from "@palladxyz/vault" -import type { NetworkId } from "@palladxyz/vault" -import { createMinaProvider } from "@palladxyz/web-provider" +import { useVault } from "@palladco/vault" +import type { NetworkId } from "@palladco/vault" +import { createMinaProvider } from "@palladco/web-provider" import { serializeError } from "serialize-error" import type { Handler } from "./" diff --git a/apps/extension/src/background/handlers/web-provider.ts b/apps/extension/src/background/handlers/web-provider.ts index 74109615..e09407fb 100644 --- a/apps/extension/src/background/handlers/web-provider.ts +++ b/apps/extension/src/background/handlers/web-provider.ts @@ -5,15 +5,18 @@ import { GetBalanceRequestParamsSchema, GetStateRequestParamsSchema, NetworkIdRequestParamsSchema, + PresentationRequestParamsSchema, RequestAccountsRequestParamsSchema, SendTransactionRequestParamsSchema, SetStateRequestParamsSchema, SignFieldsRequestParamsSchema, SignRequestParamsSchema, SignTransactionRequestParamsSchema, + StorePrivateCredentialRequestParamsSchema, SwitchChainRequestParamsSchema, + signFieldsWithPassphraseRequestParamsSchema, } from "@mina-js/providers" -import { createMinaProvider } from "@palladxyz/web-provider" +import { createMinaProvider } from "@palladco/web-provider" import { serializeError } from "serialize-error" import { z } from "zod" import type { Handler } from "." @@ -146,6 +149,21 @@ export const minaSignFields: Handler = async ({ data }) => { } } +export const minaSignFieldsWithPassphrase: Handler = async ({ data }) => { + try { + const provider = await createMinaProvider() + const payload = signFieldsWithPassphraseRequestParamsSchema.parse({ + method: "mina_signFieldsWithPassphrase", + params: data.params, + context: data.context, + }) + const response = await provider.request(payload) + return response + } catch (error: unknown) { + return { error: serializeError(error) } + } +} + export const minaSignTransaction: Handler = async ({ data }) => { try { const provider = await createMinaProvider() @@ -200,3 +218,31 @@ export const minaSendTransaction: Handler = async ({ data }) => { return { error: serializeError(error) } } } + +export const minaStorePrivateCredential: Handler = async ({ data }) => { + try { + const provider = await createMinaProvider() + const payload = StorePrivateCredentialRequestParamsSchema.parse({ + method: "mina_storePrivateCredential", + params: data.params, + context: data.context, + }) + return await provider.request(payload) + } catch (error: unknown) { + return { error: serializeError(error) } + } +} + +export const minaRequestPresentation: Handler = async ({ data }) => { + try { + const provider = await createMinaProvider() + const payload = PresentationRequestParamsSchema.parse({ + method: "mina_requestPresentation", + params: data.params, + context: data.context, + }) + return await provider.request(payload) + } catch (error: unknown) { + return { error: serializeError(error) } + } +} diff --git a/apps/extension/src/background/index.ts b/apps/extension/src/background/index.ts index 3d2f7768..e1a06748 100644 --- a/apps/extension/src/background/index.ts +++ b/apps/extension/src/background/index.ts @@ -1,4 +1,4 @@ -import { createMinaProvider } from "@palladxyz/web-provider" +import { createMinaProvider } from "@palladco/web-provider" import { onMessage, sendMessage } from "webext-bridge/background" import { runtime, tabs } from "webextension-polyfill" import { @@ -10,11 +10,14 @@ import { minaNetworkId, minaRequestAccounts, minaRequestNetwork, + minaRequestPresentation, minaSendTransaction, minaSetState, minaSign, minaSignFields, + minaSignFieldsWithPassphrase, minaSignTransaction, + minaStorePrivateCredential, minaSwitchChain, palladConnected, palladSidePanel, @@ -40,6 +43,9 @@ onMessage("mina_signTransaction", minaSignTransaction) onMessage("mina_getBalance", minaGetBalance) onMessage("mina_createNullifier", minaCreateNullifier) onMessage("mina_sendTransaction", minaSendTransaction) +onMessage("mina_storePrivateCredential", minaStorePrivateCredential) +onMessage("mina_requestPresentation", minaRequestPresentation) +onMessage("mina_signFieldsWithPassphrase", minaSignFieldsWithPassphrase) /** * Wallet handlers diff --git a/apps/extension/src/prompt.tsx b/apps/extension/src/prompt.tsx index 2344de3d..b121a73d 100644 --- a/apps/extension/src/prompt.tsx +++ b/apps/extension/src/prompt.tsx @@ -1,7 +1,7 @@ -import "@palladxyz/features/dist/index.css" +import "@palladco/features/dist/index.css" import "@total-typescript/ts-reset" -import { WebConnectorRoute } from "@palladxyz/features" +import { WebConnectorRoute } from "@palladco/features" import { ThemeProvider } from "next-themes" import React from "react" import ReactDOM from "react-dom/client" diff --git a/apps/extension/src/sandbox/index.ts b/apps/extension/src/sandbox/index.ts new file mode 100644 index 00000000..9071f963 --- /dev/null +++ b/apps/extension/src/sandbox/index.ts @@ -0,0 +1,180 @@ +import { Credential, Presentation, PresentationRequest } from "mina-credentials" +import { Signature } from "o1js" +import { serializeError } from "serialize-error" +import { match } from "ts-pattern" +import { z } from "zod" + +const MessageSchema = z.discriminatedUnion("type", [ + z.object({ + type: z.literal("run"), + contract: z.enum(["validate-credential", "presentation"]), + payload: z.string(), + }), + z.object({ + type: z.literal("presentation-signature"), + signature: z.string(), + }), + z.object({ + type: z.literal("presentation-signature-error"), + error: z.string(), + }), +]) + +type Result = { + type: string + result?: string + error?: string +} + +type PresentationRequestPayload = { + presentationRequest: PresentationRequest + selectedCredentials: string[] + verifierIdentity: + | string + | { + address: string + tokenId: string + network: "devnet" | "mainnet" + } +} + +let presentationSignaturePromise: { + resolve: (value: any) => void + reject: (reason: any) => void +} | null = null + +window.addEventListener("message", async (event) => { + const message = MessageSchema.parse(event.data) + + if (message.type === "presentation-signature") { + if (presentationSignaturePromise) { + presentationSignaturePromise.resolve(message.signature) + presentationSignaturePromise = null + } + return + } + + if (message.type === "presentation-signature-error") { + if (presentationSignaturePromise) { + presentationSignaturePromise.reject(new Error(message.error)) + presentationSignaturePromise = null + } + return + } + + return match(message) + .with({ type: "run" }, async (msg) => { + return match(msg.contract) + .with("validate-credential", async () => { + try { + const payload = msg.payload + const credentialDeserialized = await Credential.fromJSON(payload) + + await Credential.validate(credentialDeserialized) + + const result: Result = { + type: "validate-credential-result", + result: Credential.toJSON(credentialDeserialized), + } + window.parent.postMessage(result, "*") + } catch (error: any) { + const result: Result = { + type: "validate-credential-result", + error: serializeError(error), + } + window.parent.postMessage(result, "*") + } + }) + .with("presentation", async () => { + try { + // get back original payload + const payload = msg.payload + + // parse payload as PresentationRequestPayload + const parsedPayload = JSON.parse( + payload, + ) as PresentationRequestPayload + + const { + presentationRequest, + selectedCredentials, + verifierIdentity, + } = parsedPayload + + const stringifiedPresentationRequest = + JSON.stringify(presentationRequest) + + // create mina-credentials StoredCredential[] from selectedCredentials + const storedCredentials = [] + for (const credential of selectedCredentials) { + const stored = await Credential.fromJSON( + JSON.stringify(credential), + ) + storedCredentials.push(stored) + } + + // deserialize presentation request + const deserialized = PresentationRequest.fromJSON( + presentationRequest.type, + stringifiedPresentationRequest, + ) + + // format verifierIdentity + const verifierIdentityString = + presentationRequest.type === "zk-app" + ? JSON.stringify(verifierIdentity) + : (verifierIdentity as string) + + // TODO: cache compiled presentation request? + + // prepare presentation request and get fields to sign + const prepared = await Presentation.prepare({ + request: deserialized, + credentials: storedCredentials, + context: { verifierIdentity: verifierIdentityString }, + }) + + // ask wallet to sign fields + window.parent.postMessage( + { + type: "presentation-signing-request", + fields: prepared.messageFields, + }, + "*", + ) + + // get signature from wallet + const signature = (await new Promise((resolve, reject) => { + presentationSignaturePromise = { resolve, reject } + })) as string + + // get o1js Signature type signature + const ownerSignature = Signature.fromBase58(signature) + + // finalize presentation + const presentation = await Presentation.finalize( + deserialized, + ownerSignature, + prepared, + ) + + // serialize presentation + const serializedPresentation = Presentation.toJSON(presentation) + + const result: Result = { + type: "presentation-result", + result: serializedPresentation, + } + window.parent.postMessage(result, "*") + } catch (error: any) { + const result: Result = { + type: "presentation-result", + error: serializeError(error), + } + window.parent.postMessage(result, "*") + } + }) + .exhaustive() + }) + .exhaustive() +}) diff --git a/apps/extension/tailwind.config.mjs b/apps/extension/tailwind.config.mjs index 49263ede..9e11954a 100644 --- a/apps/extension/tailwind.config.mjs +++ b/apps/extension/tailwind.config.mjs @@ -1,4 +1,4 @@ -import tailwindConfig from "@palladxyz/features/tailwind.config.mjs" +import tailwindConfig from "@palladco/features/tailwind.config.mjs" export default { content: [ diff --git a/apps/extension/vite.config.ts b/apps/extension/vite.config.ts index 0aefa25e..c5e5c26e 100644 --- a/apps/extension/vite.config.ts +++ b/apps/extension/vite.config.ts @@ -10,7 +10,7 @@ export default defineConfig(() => { plugins: [ react(), webExtension({ - additionalInputs: ["prompt.html"], + additionalInputs: ["prompt.html", "sandbox.html"], manifest: () => manifest, }), svgr(), @@ -24,5 +24,11 @@ export default defineConfig(() => { chunkSizeWarningLimit: 5000, emptyOutDir: true, }, + server: { + headers: { + "Cross-Origin-Embedder-Policy": "require-corp", + "Cross-Origin-Opener-Policy": "same-origin", + }, + }, } }) diff --git a/bun.lockb b/bun.lockb index 1405fd00..af2a3e0d 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index b9874596..616a5d77 100644 --- a/package.json +++ b/package.json @@ -7,14 +7,14 @@ "scripts": { "build": "turbo run build", "b": "bun run build", - "build:extension": "turbo run build --filter=@palladxyz/extension...", - "build:features": "turbo run build --filter=@palladxyz/features...", - "story:features": "turbo run story:build --filter=@palladxyz/features", + "build:extension": "turbo run build --filter=@palladco/extension...", + "build:features": "turbo run build --filter=@palladco/features...", + "story:features": "turbo run story:build --filter=@palladco/features", "dev:extension": "turbowatch extension.turbowatch.ts", "lint": "bunx biome check .", "lint:fix": "bun run lint --write", "test:unit": "turbo run test:unit", - "test:e2e:extension": "turbo run test:e2e --filter=@palladxyz/extension", + "test:e2e:extension": "turbo run test:e2e --filter=@palladco/extension", "format": "bunx biome check --write --unsafe .", "f": "bun run format", "cleanup": "turbo run cleanup && rimraf node_modules .turbo", @@ -24,17 +24,17 @@ "devDependencies": { "@biomejs/biome": "1.8.3", "@happy-dom/global-registrator": "^15.11.0", - "@mina-js/utils": "https://pkg.pr.new/palladians/mina-js/@mina-js/utils@a51d3b4", "@testing-library/react": "16.0.1", "@tsconfig/strictest": "2.0.5", "@turbo/gen": "2.0.9", + "@vitest/coverage-v8": "2.0.5", + "@mina-js/utils": "https://pkg.pr.new/palladians/mina-js/@mina-js/utils@3", "@types/bun": "^1.1.13", "autoprefixer": "10.4.19", "happy-dom": "14.12.3", "husky": "9.1.4", "postcss": "8.4.40", "rimraf": "6.0.1", - "tailwind-merge": "2.4.0", "tailwindcss": "3.4.7", "tailwindcss-animate": "1.0.7", "tsup": "8.2.3", diff --git a/packages/_template/README.md b/packages/_template/README.md index 7758a55c..25c7c733 100644 --- a/packages/_template/README.md +++ b/packages/_template/README.md @@ -1,3 +1,3 @@ -# @palladxyz/template +# @palladco/template This is a boilerplate for creating new modules of the wallet. diff --git a/packages/_template/package.json b/packages/_template/package.json index 1617426d..e263fbc4 100644 --- a/packages/_template/package.json +++ b/packages/_template/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/template", + "name": "@palladco/template", "description": "Module template for new packages", "version": "1.0.0", "type": "module", @@ -18,6 +18,6 @@ "cleanup": "rimraf node_modules dist .turbo" }, "devDependencies": { - "@palladxyz/common": "workspace:*" + "@palladco/common": "workspace:*" } } diff --git a/packages/_template/tsconfig.json b/packages/_template/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/_template/tsconfig.json +++ b/packages/_template/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/_template/tsup.config.ts b/packages/_template/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/_template/tsup.config.ts +++ b/packages/_template/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/common/README.md b/packages/common/README.md index 0717aaf0..e0b6e7fa 100644 --- a/packages/common/README.md +++ b/packages/common/README.md @@ -1,3 +1,3 @@ -# @palladxyz/common +# @palladco/common The proto-package for shareable common configuration. diff --git a/packages/common/package.json b/packages/common/package.json index aebb59c1..4299e1c0 100644 --- a/packages/common/package.json +++ b/packages/common/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/common", + "name": "@palladco/common", "description": "The proto package for shareable common configuration.", "version": "1.0.0", "type": "module", diff --git a/packages/contracts/package.json b/packages/contracts/package.json new file mode 100644 index 00000000..880fac64 --- /dev/null +++ b/packages/contracts/package.json @@ -0,0 +1,25 @@ +{ + "name": "@palladco/contracts", + "version": "0.0.1", + "type": "module", + "module": "dist/index.js", + "types": "dist/index.d.ts", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "default": "./dist/index.js" + } + }, + "scripts": { + "build": "bunx --bun tsc", + "test:unit": "bun test", + "coverage": "bun test --coverage", + "cleanup": "bunx --bun rimraf node_modules dist .turbo" + }, + "dependencies": { + "o1js": "2.2.0" + }, + "devDependencies": { + "@palladco/common": "workspace:*" + } +} diff --git a/packages/contracts/src/add/add.spec.ts b/packages/contracts/src/add/add.spec.ts new file mode 100644 index 00000000..1ddfb4f8 --- /dev/null +++ b/packages/contracts/src/add/add.spec.ts @@ -0,0 +1,26 @@ +import { beforeAll, describe, expect, it } from "bun:test" +import { AccountUpdate, Field, Mina, PrivateKey } from "o1js" +import { Add } from "./add" + +describe("Add", () => { + beforeAll(async () => { + await Add.compile() + }) + + it("works lol", async () => { + const Local = await Mina.LocalBlockchain({ proofsEnabled: true }) + Mina.setActiveInstance(Local) + const [deployerAccount] = Local.testAccounts + const zkAppPrivateKey = PrivateKey.random() + const zkAppAddress = zkAppPrivateKey.toPublicKey() + const zkApp = new Add(zkAppAddress) + const txn = await Mina.transaction(deployerAccount, async () => { + AccountUpdate.fundNewAccount(deployerAccount) + await zkApp.deploy() + }) + await txn.prove() + await txn.sign([deployerAccount.key, zkAppPrivateKey]).send() + const num = zkApp.num.get() + expect(num).toEqual(Field(1)) + }) +}) diff --git a/packages/contracts/src/add/add.ts b/packages/contracts/src/add/add.ts new file mode 100644 index 00000000..3e5f2567 --- /dev/null +++ b/packages/contracts/src/add/add.ts @@ -0,0 +1,25 @@ +import { Field, SmartContract, State, method, state } from "o1js" + +/** + * Basic Example + * See https://docs.minaprotocol.com/zkapps for more info. + * + * The Add contract initializes the state variable 'num' to be a Field(1) value by default when deployed. + * When the 'update' method is called, the Add contract adds Field(2) to its 'num' contract state. + * + * This file is safe to delete and replace with your own contract. + */ +export class Add extends SmartContract { + @state(Field) num = State() + + init() { + super.init() + this.num.set(Field(1)) + } + + @method async update() { + const currentState = this.num.getAndRequireEquals() + const newState = currentState.add(2) + this.num.set(newState) + } +} diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts new file mode 100644 index 00000000..7ab1c15e --- /dev/null +++ b/packages/contracts/src/index.ts @@ -0,0 +1 @@ +export { Add } from "./add/add" diff --git a/packages/contracts/tsconfig.json b/packages/contracts/tsconfig.json new file mode 100644 index 00000000..c27e5d1d --- /dev/null +++ b/packages/contracts/tsconfig.json @@ -0,0 +1,29 @@ +{ + "extends": "@palladco/common/tsconfig.json", + "compilerOptions": { + // "experimentalDecorators": true, + // "noImplicitOverride": false, + // "strictPropertyInitialization": false, + // "skipLibCheck": true, + // "emitDecoratorMetadata": true, + // "useDefineForClassFields": false, + "target": "es2020", + "module": "es2022", + "strictPropertyInitialization": false, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "esModuleInterop": true, + "moduleResolution": "node", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "allowJs": true, + "declaration": true, + "sourceMap": true, + "noFallthroughCasesInSwitch": true, + "allowSyntheticDefaultImports": true, + "useDefineForClassFields": false, + "noImplicitOverride": false, + "outDir": "dist" + }, + "include": ["src"] +} diff --git a/packages/contracts/tsup.config.ts b/packages/contracts/tsup.config.ts new file mode 100644 index 00000000..10fb07d9 --- /dev/null +++ b/packages/contracts/tsup.config.ts @@ -0,0 +1,12 @@ +import { baseTsupConfig } from "@palladco/common" +import { defineConfig } from "tsup" + +import packageJson from "./package.json" + +export default defineConfig([ + { + ...baseTsupConfig, + name: packageJson.name, + splitting: false, + }, +]) diff --git a/packages/features/.ladle/components.tsx b/packages/features/.ladle/components.tsx index ed9e58a1..bf95c25e 100644 --- a/packages/features/.ladle/components.tsx +++ b/packages/features/.ladle/components.tsx @@ -8,7 +8,9 @@ import { import { ThemeProvider } from "next-themes" import React, { useEffect } from "react" import { ErrorBoundary } from "react-error-boundary" +import { I18nextProvider } from "react-i18next" import { MemoryRouter } from "react-router-dom" +import { i18n } from "../src/lib/i18n" export const Provider: GlobalProvider = ({ children }) => { const { dispatch } = useLadleContext() @@ -17,18 +19,20 @@ export const Provider: GlobalProvider = ({ children }) => { dispatch({ type: ActionType.UpdateTheme, value: ThemeState.Dark }) }, []) return ( - - - ( -
- {JSON.stringify(error, Object.getOwnPropertyNames(error))} -
- )} - > - {children} -
-
-
+ + + + ( +
+ {JSON.stringify(error, Object.getOwnPropertyNames(error))} +
+ )} + > + {children} +
+
+
+
) } diff --git a/packages/features/.ladle/config.mjs b/packages/features/.ladle/config.mjs index 44d7d7a8..4b3e8c5f 100644 --- a/packages/features/.ladle/config.mjs +++ b/packages/features/.ladle/config.mjs @@ -6,16 +6,15 @@ export default { width: { enabled: true, options: { - xsmall: 370, + xsmall: 480, small: 640, medium: 768, large: 1024, }, - defaultState: 370, + defaultState: 480, }, }, appendToHead: ``, } diff --git a/packages/features/.ladle/vite.config.ts b/packages/features/.ladle/vite.config.ts index 420a920a..0291ebe2 100644 --- a/packages/features/.ladle/vite.config.ts +++ b/packages/features/.ladle/vite.config.ts @@ -1,7 +1,6 @@ import { defineConfig } from "vite" import { nodePolyfills } from "vite-plugin-node-polyfills" import svgr from "vite-plugin-svgr" -import topLevelAwait from "vite-plugin-top-level-await" const env = (import.meta as any).env @@ -12,7 +11,6 @@ export default defineConfig({ "process.env": {}, }, plugins: [ - topLevelAwait(), svgr(), nodePolyfills({ protocolImports: true, globals: { Buffer: true } }), ], diff --git a/packages/features/package.json b/packages/features/package.json index 1007b886..fd186494 100644 --- a/packages/features/package.json +++ b/packages/features/package.json @@ -37,35 +37,28 @@ "@headlessui/react": "2.1.2", "@hookform/resolvers": "3.9.0", "@noble/hashes": "1.4.0", - "@palladxyz/key-management": "workspace:*", - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/offchain-data": "workspace:*", - "@palladxyz/pallad-core": "workspace:*", - "@palladxyz/vault": "workspace:*", + "@palladco/key-management": "workspace:*", + "@palladco/mina-core": "workspace:*", + "@palladco/offchain-data": "workspace:*", + "@palladco/pallad-core": "workspace:*", + "@palladco/vault": "workspace:*", + "@palladco/web-provider": "workspace:*", "@total-typescript/ts-reset": "0.5.1", "@zxcvbn-ts/core": "3.0.4", "array-shuffle": "3.0.0", - "class-variance-authority": "0.7.0", "clsx": "2.1.1", - "cmdk": "1.0.0", "dayjs": "1.11.12", "easy-mesh-gradient": "0.0.5", "i18next": "^23.16.0", "i18next-browser-languagedetector": "^8.0.0", "immer": "10.1.1", - "js-beautify": "1.15.1", - "lucide-react": "0.417.0", + "lucide-react": "0.418.0", "match-sorter": "6.3.4", - "merge-refs": "1.3.0", "next-themes": "0.3.0", "rambda": "9.2.1", - "react": "18.3.1", - "react-day-picker": "9.0.4", - "react-dom": "18.3.1", "react-error-boundary": "4.0.13", "react-hook-form": "7.52.1", "react-i18next": "^15.0.3", - "react-mixpanel-browser": "4.1.0", "react-qr-code": "2.0.15", "react-router": "6.25.1", "react-router-dom": "6.25.1", @@ -73,24 +66,18 @@ "react-twc": "1.4.1", "recharts": "2.12.7", "sonner": "1.5.0", - "superjson": "2.2.1", - "tailwind-merge": "2.4.0", "tailwindcss-animate": "1.0.7", "webext-bridge": "6.0.1", "webextension-polyfill": "0.12.0", "xss": "1.0.15", - "yaml": "2.5.0", + "yaml": "2.6.0", "zustand": "4.5.4" }, "devDependencies": { "@ladle/react": "4.1.0", - "@palladxyz/common": "workspace:*", - "@svgr/rollup": "8.1.0", - "@trpc/server": "10.45.2", - "@tsconfig/recommended": "1.0.7", + "@palladco/common": "workspace:*", "@tsconfig/vite-react": "3.0.2", "@types/chrome": "0.0.269", - "@types/js-beautify": "1.14.3", "@types/react": "18.3.3", "@types/react-dom": "18.3.0", "@types/webextension-polyfill": "0.10.7", @@ -98,7 +85,6 @@ "esbuild-plugin-polyfill-node": "0.3.0", "esbuild-plugin-svgr": "2.1.0", "graphql-request": "7.1.0", - "mina-signer": "3.0.7", "swr": "2.2.5", "vite": "5.3.5", "vite-plugin-node-polyfills": "0.17.0", @@ -107,7 +93,7 @@ "zod": "3.23.8" }, "peerDependencies": { - "react": "18.2.0", - "react-dom": "18.2.0" + "react": "18.3.1", + "react-dom": "18.3.1" } } diff --git a/packages/features/src/@types/i18next.d.ts b/packages/features/src/@types/i18next.d.ts deleted file mode 100644 index 18292a02..00000000 --- a/packages/features/src/@types/i18next.d.ts +++ /dev/null @@ -1,9 +0,0 @@ -import "i18next" -import resources from "./resources" -const { ns1, ns2 } = resources - -declare module "i18next" { - interface CustomTypeOptions { - defaultNS: "ns1" - } -} diff --git a/packages/features/src/@types/resources.ts b/packages/features/src/@types/resources.ts deleted file mode 100644 index f2aa9c24..00000000 --- a/packages/features/src/@types/resources.ts +++ /dev/null @@ -1,9 +0,0 @@ -import ns1 from "../i18n/locales/en/en.json" -import ns2 from "../i18n/locales/tr/tr.json" - -const resources = { - ns1, - ns2, -} as const - -export default resources diff --git a/packages/features/src/common/hooks/use-account.ts b/packages/features/src/common/hooks/use-account.ts index 41e3949b..9cc6028f 100644 --- a/packages/features/src/common/hooks/use-account.ts +++ b/packages/features/src/common/hooks/use-account.ts @@ -1,6 +1,6 @@ -import { Network, getAccountProperties } from "@palladxyz/pallad-core" -import { sessionPersistence } from "@palladxyz/vault" -import { getPublicKey, isDelegated, useVault } from "@palladxyz/vault" +import { Network, getAccountProperties } from "@palladco/pallad-core" +import { sessionPersistence } from "@palladco/vault" +import { getPublicKey, isDelegated, useVault } from "@palladco/vault" import easyMeshGradient from "easy-mesh-gradient" import { useMemo } from "react" import { useNavigate } from "react-router-dom" diff --git a/packages/features/src/common/hooks/use-transaction.ts b/packages/features/src/common/hooks/use-transaction.ts index 97357511..99803e65 100644 --- a/packages/features/src/common/hooks/use-transaction.ts +++ b/packages/features/src/common/hooks/use-transaction.ts @@ -1,4 +1,4 @@ -import { getPublicKey, useVault } from "@palladxyz/vault" +import { getPublicKey, useVault } from "@palladco/vault" import useSWR from "swr" export const useTransaction = ({ hash }: { hash: string }) => { diff --git a/packages/features/src/common/hooks/use-transactions.ts b/packages/features/src/common/hooks/use-transactions.ts index 9247255b..6deb7aaf 100644 --- a/packages/features/src/common/hooks/use-transactions.ts +++ b/packages/features/src/common/hooks/use-transactions.ts @@ -1,5 +1,5 @@ -import type { Mina } from "@palladxyz/mina-core" -import { getPublicKey, useVault } from "@palladxyz/vault" +import type { Mina } from "@palladco/mina-core" +import { getPublicKey, useVault } from "@palladco/vault" import useSWR from "swr" export const useTransactions = () => { diff --git a/packages/features/src/common/lib/tx.ts b/packages/features/src/common/lib/tx.ts index 0adabc46..e2237a09 100644 --- a/packages/features/src/common/lib/tx.ts +++ b/packages/features/src/common/lib/tx.ts @@ -1,4 +1,4 @@ -import { Mina } from "@palladxyz/mina-core" +import { Mina } from "@palladco/mina-core" type TxSide = "outgoing" | "incoming" diff --git a/packages/features/src/common/store/address-book.ts b/packages/features/src/common/store/address-book.ts index 058047d4..11ee3aaf 100644 --- a/packages/features/src/common/store/address-book.ts +++ b/packages/features/src/common/store/address-book.ts @@ -1,4 +1,4 @@ -import { localPersistence } from "@palladxyz/vault" +import { localPersistence } from "@palladco/vault" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" diff --git a/packages/features/src/common/store/app.ts b/packages/features/src/common/store/app.ts index 84874172..fb46e795 100644 --- a/packages/features/src/common/store/app.ts +++ b/packages/features/src/common/store/app.ts @@ -1,4 +1,4 @@ -import { localPersistence } from "@palladxyz/vault" +import { localPersistence } from "@palladco/vault" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" diff --git a/packages/features/src/common/store/transaction.ts b/packages/features/src/common/store/transaction.ts index 14857466..a2258118 100644 --- a/packages/features/src/common/store/transaction.ts +++ b/packages/features/src/common/store/transaction.ts @@ -1,4 +1,4 @@ -import { Mina } from "@palladxyz/mina-core" +import { Mina } from "@palladco/mina-core" import { create } from "zustand" import type { OutgoingTransaction } from "../types" diff --git a/packages/features/src/common/types.ts b/packages/features/src/common/types.ts index ed077cf9..d70f74f0 100644 --- a/packages/features/src/common/types.ts +++ b/packages/features/src/common/types.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" type TokenId = number type Nonce = number diff --git a/packages/features/src/components/address-dropdown.tsx b/packages/features/src/components/address-dropdown.tsx index ee6ec023..a8da80d2 100644 --- a/packages/features/src/components/address-dropdown.tsx +++ b/packages/features/src/components/address-dropdown.tsx @@ -1,5 +1,5 @@ import { truncateString } from "@/common/lib/string" -import { useVault } from "@palladxyz/vault" +import { useVault } from "@palladco/vault" import clsx from "clsx" import { CopyIcon, ExternalLinkIcon, UserPlusIcon } from "lucide-react" import { Link } from "react-router-dom" diff --git a/packages/features/src/components/hash-dropdown.tsx b/packages/features/src/components/hash-dropdown.tsx index f4754612..8633f454 100644 --- a/packages/features/src/components/hash-dropdown.tsx +++ b/packages/features/src/components/hash-dropdown.tsx @@ -1,4 +1,4 @@ -import { useVault } from "@palladxyz/vault" +import { useVault } from "@palladco/vault" import clsx from "clsx" import { CopyIcon, ExternalLinkIcon } from "lucide-react" import { toast } from "sonner" diff --git a/packages/features/src/components/menu-drawer.tsx b/packages/features/src/components/menu-drawer.tsx index 6044a8e7..9d238500 100644 --- a/packages/features/src/components/menu-drawer.tsx +++ b/packages/features/src/components/menu-drawer.tsx @@ -1,6 +1,6 @@ import Logo from "@/common/assets/logo.svg?react" import MenuIcon from "@/common/assets/menu.svg?react" -import { useVault } from "@palladxyz/vault" +import { useVault } from "@palladco/vault" import { ChevronDownIcon, XIcon } from "lucide-react" import { Link, useNavigate } from "react-router-dom" @@ -86,6 +86,14 @@ export const MenuDrawer = () => { > {t("components.staking")} + + + + ) +} diff --git a/packages/features/src/credentials/views/credentials.tsx b/packages/features/src/credentials/views/credentials.tsx new file mode 100644 index 00000000..768f8c73 --- /dev/null +++ b/packages/features/src/credentials/views/credentials.tsx @@ -0,0 +1,38 @@ +import { AppLayout } from "@/components/app-layout" +import { MenuBar } from "@/components/menu-bar" +import type { Json } from "@mina-js/utils" +import { IdCard } from "lucide-react" +import { useTranslation } from "react-i18next" +import { Link } from "react-router-dom" + +type CredentialsViewProps = { + credentials: [string, Json][] +} + +export const CredentialsView = ({ credentials }: CredentialsViewProps) => { + const { t } = useTranslation() + return ( + + +
+

{t("credentials.credentials")}

+
+ {credentials.map(([id]) => ( + +
+ +
+
+

{id}

+
+ + ))} +
+
+
+ ) +} diff --git a/packages/features/src/error-renderer/views/error.tsx b/packages/features/src/error-renderer/views/error.tsx index 8ddffef4..8699891e 100644 --- a/packages/features/src/error-renderer/views/error.tsx +++ b/packages/features/src/error-renderer/views/error.tsx @@ -1,6 +1,5 @@ import type { FallbackProps } from "react-error-boundary" import { useTranslation } from "react-i18next" -//import { useMixpanel } from "react-mixpanel-browser" export const ErrorView = ({ error, resetErrorBoundary }: FallbackProps) => { const stringifiedError = JSON.stringify( diff --git a/packages/features/src/i18n/index.ts b/packages/features/src/i18n/index.ts deleted file mode 100644 index 73e50353..00000000 --- a/packages/features/src/i18n/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -import i18next from "i18next" -import LanguageDetector from "i18next-browser-languagedetector" -import { initReactI18next } from "react-i18next" -import ns1 from "./locales/en/en.json" -import ns2 from "./locales/tr/tr.json" - -const defaultNS = "ns1" - -const resources = { - en: { - ns1, - }, - tr: { - ns2, - }, -} - -i18next - .use(LanguageDetector) - .use(initReactI18next) - .init({ - debug: false, - fallbackLng: ["en", "tr"], - resources: resources, - defaultNS, - }) diff --git a/packages/features/src/index.ts b/packages/features/src/index.ts index 17a3ca55..5fac75db 100644 --- a/packages/features/src/index.ts +++ b/packages/features/src/index.ts @@ -3,9 +3,9 @@ import "@total-typescript/ts-reset" import type {} from "graphql-request" import type {} from "swr" export { useAppStore } from "./common/store/app" -export { usePendingTransactionStore } from "@palladxyz/vault" +export { usePendingTransactionStore } from "@palladco/vault" export { Router } from "./router" export { WebConnectorRoute } from "./web-connector/routes/web-connector" export * as Icons from "lucide-react" -import "./i18n" +export { i18n } from "./lib/i18n" import "./globals.css" diff --git a/packages/features/src/lib/i18n.ts b/packages/features/src/lib/i18n.ts new file mode 100644 index 00000000..9d5ff578 --- /dev/null +++ b/packages/features/src/lib/i18n.ts @@ -0,0 +1,23 @@ +import i18n from "i18next" +import LanguageDetector from "i18next-browser-languagedetector" +import { initReactI18next } from "react-i18next" +import en from "./locales/en/en.json" +import tr from "./locales/tr/tr.json" + +const resources = { + en: { translation: en }, + tr: { translation: tr }, +} + +i18n + .use(LanguageDetector) + .use(initReactI18next) + .init({ + fallbackLng: "en", + resources, + interpolation: { + escapeValue: false, + }, + }) + +export { i18n } diff --git a/packages/features/src/i18n/locales/en/en.json b/packages/features/src/lib/locales/en/en.json similarity index 98% rename from packages/features/src/i18n/locales/en/en.json rename to packages/features/src/lib/locales/en/en.json index a6849b9a..6a65c342 100644 --- a/packages/features/src/i18n/locales/en/en.json +++ b/packages/features/src/lib/locales/en/en.json @@ -147,5 +147,9 @@ "deny": "Deny", "sign": "Sign", "reject": "Reject" + }, + "credentials": { + "credentials": "Credentials", + "delete": "Delete" } } diff --git a/packages/features/src/i18n/locales/tr/tr.json b/packages/features/src/lib/locales/tr/tr.json similarity index 98% rename from packages/features/src/i18n/locales/tr/tr.json rename to packages/features/src/lib/locales/tr/tr.json index 0ea06df2..b2b58507 100644 --- a/packages/features/src/i18n/locales/tr/tr.json +++ b/packages/features/src/lib/locales/tr/tr.json @@ -147,5 +147,9 @@ "deny": "Reddet", "sign": "İmzala", "reject": "Reddet" + }, + "credentials": { + "credentials": "Kimlik", + "delete": "Silmek" } } diff --git a/packages/features/src/lock/routes/unlock-wallet.tsx b/packages/features/src/lock/routes/unlock-wallet.tsx index 8a317284..d022cd22 100644 --- a/packages/features/src/lock/routes/unlock-wallet.tsx +++ b/packages/features/src/lock/routes/unlock-wallet.tsx @@ -1,6 +1,6 @@ import { zodResolver } from "@hookform/resolvers/zod" -import { securePersistence, sessionPersistence } from "@palladxyz/vault" -import { useVault } from "@palladxyz/vault" +import { securePersistence, sessionPersistence } from "@palladco/vault" +import { useVault } from "@palladco/vault" import { type FormEvent, useEffect, useState } from "react" import { useForm } from "react-hook-form" import { useNavigate } from "react-router-dom" diff --git a/packages/features/src/onboarding/routes/create-wallet.tsx b/packages/features/src/onboarding/routes/create-wallet.tsx index b6190b65..9fee221f 100644 --- a/packages/features/src/onboarding/routes/create-wallet.tsx +++ b/packages/features/src/onboarding/routes/create-wallet.tsx @@ -1,4 +1,4 @@ -import { generateMnemonicWords } from "@palladxyz/key-management" +import { generateMnemonicWords } from "@palladco/key-management" import { useNavigate } from "react-router-dom" import { shallow } from "zustand/shallow" diff --git a/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx b/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx index 8470ba0e..e15e6faa 100644 --- a/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx +++ b/packages/features/src/onboarding/routes/seed-backup-confirmation.tsx @@ -1,8 +1,8 @@ import { utf8ToBytes } from "@noble/hashes/utils" -import type { ChainDerivationArgs } from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" -import { sessionPersistence } from "@palladxyz/vault" -import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladxyz/vault" +import type { ChainDerivationArgs } from "@palladco/key-management" +import { Network } from "@palladco/pallad-core" +import { sessionPersistence } from "@palladco/vault" +import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladco/vault" import { useMemo, useState } from "react" import { useForm } from "react-hook-form" import { useNavigate } from "react-router-dom" diff --git a/packages/features/src/onboarding/routes/seed-import.tsx b/packages/features/src/onboarding/routes/seed-import.tsx index f8324ce3..8743214d 100644 --- a/packages/features/src/onboarding/routes/seed-import.tsx +++ b/packages/features/src/onboarding/routes/seed-import.tsx @@ -1,8 +1,8 @@ -import { validateMnemonic, wordlist } from "@palladxyz/key-management" -import type { ChainDerivationArgs } from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" -import { sessionPersistence } from "@palladxyz/vault" -import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladxyz/vault" +import { validateMnemonic, wordlist } from "@palladco/key-management" +import type { ChainDerivationArgs } from "@palladco/key-management" +import { Network } from "@palladco/pallad-core" +import { sessionPersistence } from "@palladco/vault" +import { DEFAULT_NETWORK, KeyAgents, useVault } from "@palladco/vault" import { useState } from "react" import { type SubmitHandler, useForm } from "react-hook-form" import { useNavigate } from "react-router-dom" diff --git a/packages/features/src/onboarding/routes/start.tsx b/packages/features/src/onboarding/routes/start.tsx index 1afe132f..f824065d 100644 --- a/packages/features/src/onboarding/routes/start.tsx +++ b/packages/features/src/onboarding/routes/start.tsx @@ -1,4 +1,4 @@ -import { securePersistence, sessionPersistence } from "@palladxyz/vault" +import { securePersistence, sessionPersistence } from "@palladco/vault" import { useEffect, useState } from "react" import { useNavigate } from "react-router-dom" diff --git a/packages/features/src/onboarding/views/seed-import.tsx b/packages/features/src/onboarding/views/seed-import.tsx index 9261c5de..b09fdbf8 100644 --- a/packages/features/src/onboarding/views/seed-import.tsx +++ b/packages/features/src/onboarding/views/seed-import.tsx @@ -1,4 +1,4 @@ -import { wordlist } from "@palladxyz/key-management" +import { wordlist } from "@palladco/key-management" import { Loader2Icon } from "lucide-react" import type { UseFormReturn } from "react-hook-form" diff --git a/packages/features/src/router.tsx b/packages/features/src/router.tsx index f98bb0f1..f7d7b795 100644 --- a/packages/features/src/router.tsx +++ b/packages/features/src/router.tsx @@ -3,10 +3,14 @@ import { MemoryRouter, Outlet, Route, Routes } from "react-router-dom" import dayjs from "dayjs" import relativeTime from "dayjs/plugin/relativeTime" import { ErrorBoundary } from "react-error-boundary" +import { I18nextProvider } from "react-i18next" import { Toaster } from "sonner" import { AddressBookRoute } from "./address-book/routes/address-book" import { NewAddressRoute } from "./address-book/routes/new-address" +import { CredentialDetailsRoute } from "./credentials/routes/credential-details" +import { CredentialsRoute } from "./credentials/routes/credentials" import { ErrorView } from "./error-renderer/views/error" +import { i18n } from "./lib/i18n" import { UnlockWalletRoute } from "./lock/routes/unlock-wallet" import { NotFoundRoute } from "./not-found/routes/not-found" import { CreateWalletRoute } from "./onboarding/routes/create-wallet" @@ -44,85 +48,91 @@ dayjs.extend(relativeTime) export const Router = () => { return ( - -
- - - - } /> - } /> - } /> - } /> - } /> - } - /> - } - /> - } - /> - } - /> - } /> - } /> - } /> - } - /> - }> - } /> - } /> - - }> - } /> - } /> - } /> + + +
+ + + + } /> + } /> + } /> + } /> + } /> } + path="/transactions/summary" + element={} /> - } /> } + path="/transactions/success" + element={} /> } + path="/transactions/error" + element={} /> - } /> - - } /> - }> - } /> - }> - } /> - } /> - } /> - - }> - } /> - } /> - } /> - } + path="/transactions/:hash" + element={} + /> + } /> + } /> + } /> + } /> - } /> - - } /> - - -
-
+ }> + } /> + } /> + + }> + } /> + } /> + } /> + } + /> + } /> + } + /> + } + /> + } /> + + } /> + }> + } /> + }> + } /> + } /> + } /> + + }> + } /> + } /> + } /> + + } + /> + } /> + + }> + } /> + } /> + + } /> +
+
+
+
+ ) } diff --git a/packages/features/src/send/components/send-form.tsx b/packages/features/src/send/components/send-form.tsx index d9f63bda..01fbaba4 100644 --- a/packages/features/src/send/components/send-form.tsx +++ b/packages/features/src/send/components/send-form.tsx @@ -10,7 +10,7 @@ import { FormError } from "@/components/form-error" import MinaIcon from "@/common/assets/mina.svg?react" import { formatCurrency } from "@/common/lib/currency" import { FeePicker, TransactionFeeShort } from "@/components/fee-picker" -import { TransactionType } from "@palladxyz/mina-core" +import { TransactionType } from "@palladco/mina-core" import { ChevronRightIcon, SearchIcon } from "lucide-react" import { SendFormSchema, type SendFormSchemaProps } from "./send-form.schema" diff --git a/packages/features/src/send/hooks/use-transaction-confirmation.tsx b/packages/features/src/send/hooks/use-transaction-confirmation.tsx index 2e5f8ff6..99822740 100644 --- a/packages/features/src/send/hooks/use-transaction-confirmation.tsx +++ b/packages/features/src/send/hooks/use-transaction-confirmation.tsx @@ -1,6 +1,6 @@ -import type { ChainOperationArgs } from "@palladxyz/key-management" -import { TransactionType } from "@palladxyz/mina-core" -import { useVault } from "@palladxyz/vault" +import type { ChainOperationArgs } from "@palladco/key-management" +import { TransactionType } from "@palladco/mina-core" +import { useVault } from "@palladco/vault" import dayjs from "dayjs" import type { SubmitHandler, UseFormReturn } from "react-hook-form" import { useNavigate } from "react-router-dom" @@ -8,7 +8,7 @@ import type { z } from "zod" import { useAccount } from "@/common/hooks/use-account" import { useTransactionStore } from "@/common/store/transaction" -import { usePendingTransactionStore } from "@palladxyz/vault" +import { usePendingTransactionStore } from "@palladco/vault" import type { SignedTransaction, TransactionBody } from "@mina-js/utils" import { utf8ToBytes } from "@noble/hashes/utils" diff --git a/packages/features/src/send/routes/send.tsx b/packages/features/src/send/routes/send.tsx index d49f32eb..bccbada4 100644 --- a/packages/features/src/send/routes/send.tsx +++ b/packages/features/src/send/routes/send.tsx @@ -1,7 +1,7 @@ import { useNavigate } from "react-router-dom" import { useAccount } from "@/common/hooks/use-account" -import { useFiatPrice } from "@palladxyz/offchain-data" +import { useFiatPrice } from "@palladco/offchain-data" import { useState } from "react" import { SendView } from "../views/send" diff --git a/packages/features/src/staking/components/delegate-form.tsx b/packages/features/src/staking/components/delegate-form.tsx index f8eb3cf7..75007be8 100644 --- a/packages/features/src/staking/components/delegate-form.tsx +++ b/packages/features/src/staking/components/delegate-form.tsx @@ -9,7 +9,7 @@ import { FormError } from "@/components/form-error" import { FeePicker, TransactionFeeShort } from "@/components/fee-picker" import type { SendFormSchemaProps } from "@/send/components/send-form.schema" -import { TransactionType } from "@palladxyz/mina-core" +import { TransactionType } from "@palladco/mina-core" import { ExternalLinkIcon } from "lucide-react" import { useTranslation } from "react-i18next" import { DelegateFormSchema } from "./delegate-form.schema" diff --git a/packages/features/src/transactions/components/tx-tile.tsx b/packages/features/src/transactions/components/tx-tile.tsx index aeef294b..01e8fca7 100644 --- a/packages/features/src/transactions/components/tx-tile.tsx +++ b/packages/features/src/transactions/components/tx-tile.tsx @@ -1,6 +1,6 @@ import { getTxKind } from "@/common/lib/tx" import { TxIcon } from "@/components/tx-icon" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { clsx } from "clsx" import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" diff --git a/packages/features/src/transactions/index.stories.tsx b/packages/features/src/transactions/index.stories.tsx index c9070049..e23027d2 100644 --- a/packages/features/src/transactions/index.stories.tsx +++ b/packages/features/src/transactions/index.stories.tsx @@ -1,5 +1,5 @@ import { type StoryDefault, action } from "@ladle/react" -import { Mina } from "@palladxyz/mina-core" +import { Mina } from "@palladco/mina-core" import { TransactionDetailsView } from "./views/transaction-details" import { TransactionsView } from "./views/transactions" diff --git a/packages/features/src/transactions/routes/transactions.tsx b/packages/features/src/transactions/routes/transactions.tsx index 34bbc9fb..7d535b89 100644 --- a/packages/features/src/transactions/routes/transactions.tsx +++ b/packages/features/src/transactions/routes/transactions.tsx @@ -2,9 +2,9 @@ import { useEffect } from "react" import { useAccount } from "@/common/hooks/use-account" import { useTransactions } from "@/common/hooks/use-transactions" -import { usePendingTransactionStore, useVault } from "@palladxyz/vault" +import { usePendingTransactionStore, useVault } from "@palladco/vault" -import { useFiatPrice } from "@palladxyz/offchain-data" +import { useFiatPrice } from "@palladco/offchain-data" import { TransactionsView } from "../views/transactions" export const TransactionsRoute = () => { diff --git a/packages/features/src/transactions/utils/structurize-transactions.ts b/packages/features/src/transactions/utils/structurize-transactions.ts index 7161f635..504a5e6f 100644 --- a/packages/features/src/transactions/utils/structurize-transactions.ts +++ b/packages/features/src/transactions/utils/structurize-transactions.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import dayjs from "dayjs" import { groupBy, map, pipe } from "rambda" diff --git a/packages/features/src/transactions/views/transaction-details.tsx b/packages/features/src/transactions/views/transaction-details.tsx index 38c7bd53..15b19f0e 100644 --- a/packages/features/src/transactions/views/transaction-details.tsx +++ b/packages/features/src/transactions/views/transaction-details.tsx @@ -1,4 +1,4 @@ -import { Mina } from "@palladxyz/mina-core" +import { Mina } from "@palladco/mina-core" import { AppLayout } from "@/components/app-layout" import dayjs from "dayjs" diff --git a/packages/features/src/transactions/views/transactions.tsx b/packages/features/src/transactions/views/transactions.tsx index a6ca034b..eb083d8e 100644 --- a/packages/features/src/transactions/views/transactions.tsx +++ b/packages/features/src/transactions/views/transactions.tsx @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { Filter, X } from "lucide-react" import { groupBy } from "rambda" import { Link } from "react-router-dom" diff --git a/packages/features/src/wallet/routes/networks.tsx b/packages/features/src/wallet/routes/networks.tsx index 267ebc28..b4a28889 100644 --- a/packages/features/src/wallet/routes/networks.tsx +++ b/packages/features/src/wallet/routes/networks.tsx @@ -1,5 +1,5 @@ import { useAccount } from "@/common/hooks/use-account" -import { useVault } from "@palladxyz/vault" +import { useVault } from "@palladco/vault" import { useNavigate } from "react-router-dom" import { sendMessage } from "webext-bridge/popup" import { NetworksView } from "../views/networks" diff --git a/packages/features/src/wallet/routes/overview.tsx b/packages/features/src/wallet/routes/overview.tsx index 5df3530b..0520d307 100644 --- a/packages/features/src/wallet/routes/overview.tsx +++ b/packages/features/src/wallet/routes/overview.tsx @@ -1,4 +1,4 @@ -import { useFiatPrice } from "@palladxyz/offchain-data" +import { useFiatPrice } from "@palladco/offchain-data" import { useAccount } from "@/common/hooks/use-account" import { useTransactions } from "@/common/hooks/use-transactions" diff --git a/packages/features/src/wallet/views/overview.tsx b/packages/features/src/wallet/views/overview.tsx index c5c32d9f..2b06031a 100644 --- a/packages/features/src/wallet/views/overview.tsx +++ b/packages/features/src/wallet/views/overview.tsx @@ -2,7 +2,7 @@ import ArrowRightIcon from "@/common/assets/arrow-right.svg?react" import { AppLayout } from "@/components/app-layout" import { MenuBar } from "@/components/menu-bar" import { Skeleton } from "@/components/skeleton" -import type { Tx } from "@palladxyz/pallad-core" +import type { Tx } from "@palladco/pallad-core" import { useTranslation } from "react-i18next" import { Link } from "react-router-dom" import SlotCounter from "react-slot-counter" diff --git a/packages/features/src/web-connector/components/credential-selection-form.tsx b/packages/features/src/web-connector/components/credential-selection-form.tsx new file mode 100644 index 00000000..aa2704a4 --- /dev/null +++ b/packages/features/src/web-connector/components/credential-selection-form.tsx @@ -0,0 +1,372 @@ +import { createCredentialHash } from "@palladco/web-provider" +import React, { useState } from "react" +import { useTranslation } from "react-i18next" +import yaml from "yaml" + +type SelectionFormProps = { + onSubmit: (selectedCredentials: string) => void + onReject: () => void + submitButtonLabel?: string + rejectButtonLabel?: string + payload: string + loading: boolean +} + +interface PayloadWithPresentation { + storedCredentials: any[] + presentationRequest: { + spec: { + inputs: Record< + string, + { + type: string + credentialType?: string + data?: + | Record + | { + _type: "Struct" + properties: Record + } + | { + _type: "DynamicRecord" + maxEntries: number + knownShape: Record + } + } + > + } + } +} + +const simplifyCredentialData = ( + data: Record, +): Record => { + const simplified: Record = {} + for (const [key, value] of Object.entries(data)) { + if (typeof value === "object" && value !== null) { + if ("bytes" in value) { + simplified[key] = value.bytes + .map((b: { value: string }) => b.value) + .join("") + } else if ("value" in value) { + simplified[key] = value.value + } else { + simplified[key] = value + } + } else { + simplified[key] = value + } + } + return simplified +} + +export const recoverOriginalPayload = (sanitizedPayload: string) => { + const parsedYaml = yaml.parse(sanitizedPayload) + return JSON.stringify(parsedYaml) +} + +const isPayloadWithPresentation = ( + payload: unknown, +): payload is PayloadWithPresentation => { + return ( + typeof payload === "object" && + payload !== null && + "storedCredentials" in payload && + Array.isArray((payload as PayloadWithPresentation).storedCredentials) && + "presentationRequest" in payload && + typeof (payload as PayloadWithPresentation).presentationRequest === + "object" && + (payload as PayloadWithPresentation).presentationRequest !== null && + "spec" in (payload as PayloadWithPresentation).presentationRequest && + typeof (payload as PayloadWithPresentation).presentationRequest.spec === + "object" && + (payload as PayloadWithPresentation).presentationRequest.spec !== null && + "inputs" in (payload as PayloadWithPresentation).presentationRequest.spec + ) +} + +// Extract data fields from input data which could be direct, nested in properties, or in knownShape +const extractDataFields = (data: any): string[] => { + if (!data) return [] + + // Handle Struct type with properties + if (data._type === "Struct" && data.properties) { + return Object.keys(data.properties) + } + + // Handle DynamicRecord with knownShape + if (data._type === "DynamicRecord" && data.knownShape) { + return Object.keys(data.knownShape) + } + + // Handle direct data fields + return Object.keys(data) +} + +// Get all credential requirements from presentation request +const getCredentialRequirements = ( + presentationRequest: PayloadWithPresentation["presentationRequest"], +) => { + const requirements: Array<{ + inputKey: string + type: string + dataFields: string[] + }> = [] + + for (const [key, input] of Object.entries(presentationRequest.spec.inputs)) { + if (input.type === "credential" && input.credentialType && input.data) { + requirements.push({ + inputKey: key, + type: input.credentialType, + dataFields: extractDataFields(input.data), + }) + } + } + + return requirements +} + +// Get credential data keys accounting for both simple and recursive/struct credentials +const getCredentialDataKeys = (credential: any): string[] => { + const data = credential.credential.value?.data || credential.credential.data + return data ? Object.keys(data) : [] +} + +// Check if credential matches a specific requirement +const credentialMatchesRequirement = ( + credential: any, + requirement: { + type: string + dataFields: string[] + }, +): boolean => { + if (credential.witness?.type !== requirement.type) { + return false + } + + const credentialFields = getCredentialDataKeys(credential) + return requirement.dataFields.every((field) => + credentialFields.includes(field), + ) +} + +// Find all requirements that a credential can satisfy +const findMatchingRequirements = ( + credential: any, + requirements: Array<{ + inputKey: string + type: string + dataFields: string[] + }>, +) => { + return requirements.filter((req) => + credentialMatchesRequirement(credential, req), + ) +} + +const CredentialDisplay = ({ + credential, + matchingRequirements, +}: { + credential: any + matchingRequirements: Array<{ + inputKey: string + type: string + dataFields: string[] + }> +}) => { + const witnessType = credential.witness?.type || "unknown" + const credentialData = + credential.credential.value?.data || credential.credential.data + const simplifiedData = simplifyCredentialData(credentialData) + const description = credential.metadata?.description + + return ( +
+ {description &&

{description}

} +
+        {JSON.stringify(simplifiedData, null, 2)}
+      
+
+ + Type: {witnessType} + + + Can be used for:{" "} + {matchingRequirements.map((r) => r.inputKey).join(", ")} + +
+
+ ) +} + +export const SelectionForm = ({ + onSubmit, + onReject, + submitButtonLabel, + rejectButtonLabel, + payload, + loading, +}: SelectionFormProps) => { + const { t } = useTranslation() + const [selectedCredentials, setSelectedCredentials] = useState< + Map + >(new Map()) + + const { credentials, requirements } = React.useMemo(() => { + try { + const originalPayload = recoverOriginalPayload(payload) + const parsedPayload = JSON.parse(originalPayload) + + if (!isPayloadWithPresentation(parsedPayload)) { + throw new Error( + "Invalid payload format: Expected PayloadWithPresentation", + ) + } + + const credentialRequirements = getCredentialRequirements( + parsedPayload.presentationRequest, + ) + + const validCredentials = parsedPayload.storedCredentials + .filter( + (credential: any) => + findMatchingRequirements(credential, credentialRequirements) + .length > 0, + ) + .map((credential: any) => ({ + id: createCredentialHash(credential), + credential, + matchingRequirements: findMatchingRequirements( + credential, + credentialRequirements, + ), + })) + + return { + credentials: validCredentials, + requirements: credentialRequirements, + } + } catch (error: any) { + error.message = `Issue with parsing: ${error.message}: ${payload}` + throw error + } + }, [payload]) + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault() + // Create an array of credentials in the same order as the requirements + const orderedCredentials = requirements + .map((req) => { + const selected = selectedCredentials.get(req.inputKey) + return selected?.credential + }) + .filter(Boolean) + + onSubmit(JSON.stringify(orderedCredentials)) + } + + const handleCredentialSelect = (credentialData: any, inputKey: string) => { + setSelectedCredentials((prev) => { + const newMap = new Map(prev) + + // Update or add the selection for this input + newMap.set(inputKey, { + credential: credentialData.credential, + credentialId: credentialData.id, + }) + + return newMap + }) + } + + const isSelectedFor = (credentialId: string, inputKey: string) => { + const selection = selectedCredentials.get(inputKey) + return selection?.credentialId === credentialId + } + + const allRequirementsMet = requirements.every((req) => + selectedCredentials.has(req.inputKey), + ) + + return ( +
+
+ {requirements.map((requirement) => { + const matchingCredentials = credentials.filter((cred) => + cred.matchingRequirements.some( + (req) => req.inputKey === requirement.inputKey, + ), + ) + + return ( +
+

+ Select credential for {requirement.inputKey}: +

+
+ {matchingCredentials.length > 0 ? ( + matchingCredentials.map((credentialData) => ( + + )) + ) : ( +
+ No matching credentials found for this input +
+ )} +
+
+ ) + })} +
+ + + + +
+ ) +} + +export default SelectionForm diff --git a/packages/features/src/web-connector/routes/web-connector.tsx b/packages/features/src/web-connector/routes/web-connector.tsx index 6d1dc230..db64c40b 100644 --- a/packages/features/src/web-connector/routes/web-connector.tsx +++ b/packages/features/src/web-connector/routes/web-connector.tsx @@ -1,3 +1,4 @@ +import type { Json } from "@mina-js/utils" import { useEffect, useState } from "react" import type { SubmitHandler } from "react-hook-form" import { MemoryRouter } from "react-router-dom" @@ -8,42 +9,151 @@ import yaml from "yaml" import type { UserInputForm } from "../types" import { WebConnectorView } from "../views/web-connector" -const sanitizePayload = async (payload: string) => { +type ContractResult = { + type?: string + result?: string + error?: string +} + +type SignedFieldsResponse = { + data: string[] + publicKey: string + signature: string +} + +export const sanitizePayload = async (payload: string) => { const parsedPayload = JSON.parse(payload) as Record const yamlPayload = yaml.stringify(parsedPayload) return xss(yamlPayload) } +const sendSandboxMessage = (payload: Json) => { + const sandbox = document.querySelector( + "#o1sandbox", + ) as HTMLIFrameElement | null + if (!sandbox) return + return sandbox.contentWindow?.postMessage(payload, "*") +} + type ActionRequest = { title: string submitButtonLabel?: string rejectButtonLabel?: string payload: string - inputType: "text" | "password" | "confirmation" - loading: boolean + inputType: "text" | "password" | "confirmation" | "selection" + contract: string | undefined emitConnected: boolean } export const WebConnectorRoute = () => { + const [loading, setLoading] = useState(true) + const [loadingMessage, setLoadingMessage] = useState() const [request, setRequest] = useState({ title: "", payload: "", inputType: "confirmation", - loading: true, + contract: undefined, emitConnected: false, }) - const onSubmit: SubmitHandler = async ({ userInput }) => { + const startSubmitting: SubmitHandler = async ({ + userInput, + }) => { + if (!request.contract) return onSubmit({ userInput }) + setLoading(true) + try { + // For presentation contract, set up message handler for signing request + if (request.contract === "presentation") { + setLoadingMessage("Creating presentation...") + const messageHandler = async (event: MessageEvent) => { + if (event.data.type === "presentation-signing-request") { + try { + // Use the passphrase we already have to sign fields + const response = (await sendMessage( + "mina_signFieldsWithPassphrase", + { + params: [ + { + fields: event.data.fields as string[], + passphrase: userInput, + }, + ], + context: { + origin: `chrome-extension://${chrome.runtime.id}`, + }, + }, + "background", + )) as SignedFieldsResponse + + if (!response || !response.signature) { + throw new Error( + `Failed to sign fields; response: ${JSON.stringify(response)}`, + ) + } + + // Send signature back to sandbox + sendSandboxMessage({ + type: "presentation-signature", + signature: response.signature, + }) + } catch (error) { + console.error("Error signing fields:", error) + sendSandboxMessage({ + type: "presentation-signature-error", + error: error instanceof Error ? error.message : "Unknown error", + }) + } + } + } + + window.addEventListener("message", messageHandler) + } + return sendSandboxMessage({ + type: "run", + contract: request.contract, + payload: request.payload, + userInput, + }) + } catch (error) { + setLoading(false) + setLoadingMessage(undefined) + throw error + } + } + const onSubmit: SubmitHandler< + UserInputForm & { result?: ContractResult } + > = async ({ userInput, result }) => { const { id } = await windows.getCurrent() await runtime.sendMessage({ + type: "onSubmit", userInput, + result, windowId: id, }) window.close() } - const confirm = async () => { + const startConfirming = async () => { + if (!request.contract) return confirm({}) + setLoading(true) + if (request.contract === "validate-credential") { + setLoadingMessage("Validating credential...") + } + try { + return sendSandboxMessage({ + type: "run", + contract: request.contract, + payload: request.payload, + }) + } catch (error) { + setLoading(false) + setLoadingMessage(undefined) + throw error + } + } + const confirm = async ({ result }: { result?: ContractResult }) => { const { id } = await windows.getCurrent() await runtime.sendMessage({ userConfirmed: true, + result, windowId: id, }) if (request.emitConnected) { @@ -67,18 +177,59 @@ export const WebConnectorRoute = () => { }) window.close() } + const eventListener = async (event: MessageEvent) => { + if (event.data.type === "presentation-result") { + const { id } = await windows.getCurrent() + await runtime.sendMessage({ + type: "presentation-result", + userInput: "passphrase", + result: { + type: event.data.type, + result: event.data.result, + error: event.data.error, + }, + windowId: id, + }) + setLoading(false) + setLoadingMessage(undefined) + window.close() + } + if (event.data.type === "validate-credential-result") { + setLoading(false) + setLoadingMessage(undefined) + return confirm({ + result: { + type: event.data.type, + result: event.data.result, + error: event.data.error, + }, + }) + } + } + // biome-ignore lint/correctness/useExhaustiveDependencies: wontdo + useEffect(() => { + window.addEventListener("message", eventListener) + return () => { + window.removeEventListener("message", eventListener) + } + }, [request.inputType]) useEffect(() => { runtime.onMessage.addListener(async (message) => { + const payload = message.params.contract + ? message.params.payload + : await sanitizePayload(message.params.payload) if (message.type === "action_request") { setRequest({ title: message.params.title, submitButtonLabel: message.params.submitButtonLabel, rejectButtonLabel: message.params.rejectButtonLabel, - payload: await sanitizePayload(message.params.payload), + payload: payload, + contract: message.params.contract, inputType: message.params.inputType, - loading: false, emitConnected: message.params.emitConnected, }) + setLoading(false) + setLoadingMessage(undefined) } }) }, []) @@ -86,15 +237,16 @@ export const WebConnectorRoute = () => { ) diff --git a/packages/features/src/web-connector/utils/render-payload.tsx b/packages/features/src/web-connector/utils/render-payload.tsx new file mode 100644 index 00000000..13fbf819 --- /dev/null +++ b/packages/features/src/web-connector/utils/render-payload.tsx @@ -0,0 +1,376 @@ +import xss from "xss" +import { recoverOriginalPayload } from "../components/credential-selection-form" + +const handleRenderError = (error: Error) => { + const sanitizedError = xss(error.message) + + return ( +
+      {`Error: ${sanitizedError}`}
+    
+ ) +} + +type LogicNode = { + type: string + inputs?: LogicNode[] + left?: LogicNode + right?: LogicNode + key?: string + inner?: LogicNode + data?: Record + credentialKey?: string + input?: LogicNode + options?: LogicNode[] | LogicNode + condition?: LogicNode + thenNode?: LogicNode + elseNode?: LogicNode +} + +const extractCredentialFields = (data: any): string[] => { + if (!data) return [] + + if (data._type === "Struct" && data.properties) { + return Object.keys(data.properties) + } + + if (data._type === "DynamicRecord" && data.knownShape) { + return Object.keys(data.knownShape) + } + + return Object.keys(data) +} + +const buildPropertyPath = (node: LogicNode): string => { + const parts: string[] = [] + let currentNode: LogicNode | undefined = node + + while (currentNode?.type === "property") { + if (!currentNode.key) { + throw Error("PROPERTY node must have 'key'") + } + parts.unshift(currentNode.key) + currentNode = currentNode.inner + } + + return parts.join(".") +} + +const formatLogicNode = (node: LogicNode, level = 0): string => { + const indent = " ".repeat(level) + + switch (node.type) { + case "and": + if (!node.inputs) { + throw Error("AND node must have 'inputs' array") + } + if (node.inputs.length === 0) { + throw Error("AND node must have at least one input") + } + return `${indent}All of these conditions must be true:\n${node.inputs + .map((n) => `${indent}- ${formatLogicNode(n, level + 1)}`) + .join("\n")}` + + case "or": + if (!node.left || !node.right) { + throw Error("OR node must have both 'left' and 'right' nodes") + } + return `${indent}Either:\n${indent}- ${formatLogicNode(node.left, level + 1)}\n${indent}Or:\n${indent}- ${formatLogicNode(node.right, level + 1)}` + + case "equals": + if (!node.left || !node.right) { + throw Error("EQUALS node must have both 'left' and 'right' nodes") + } + return `${formatLogicNode(node.left)} equals ${formatLogicNode(node.right)}` + + case "equalsOneOf": { + if (!node.input) { + throw Error("EQUALS_ONE_OF node must have 'input' node") + } + if (!node.options) { + throw Error("EQUALS_ONE_OF node must have 'options'") + } + const input = formatLogicNode(node.input, level) + const options = Array.isArray(node.options) + ? node.options.map((o) => formatLogicNode(o, level)).join(", ") + : formatLogicNode(node.options, level) + return `${options} contains ${input}` + } + + case "lessThan": + if (!node.left || !node.right) { + throw Error("LESS_THAN node must have both 'left' and 'right' nodes") + } + return `${formatLogicNode(node.left)} < ${formatLogicNode(node.right)}` + + case "lessThanEq": + if (!node.left || !node.right) { + throw Error("LESS_THAN_EQ node must have both 'left' and 'right' nodes") + } + return `${formatLogicNode(node.left)} ≤ ${formatLogicNode(node.right)}` + + case "property": { + if (!node.key) { + throw Error("PROPERTY node must have 'key'") + } + + // If this is the root property, just return the path + if (node.inner?.type === "root") { + return node.key + } + + // For nested properties, build the complete path + return buildPropertyPath(node) + } + + case "root": + return "" + + case "hash": + if (!node.inputs) { + throw Error("HASH node must have 'inputs' array") + } + return `hash(${node.inputs.map((n) => formatLogicNode(n, level)).join(", ")})` + + case "issuer": + if (!node.credentialKey) { + throw Error("ISSUER node must have 'credentialKey'") + } + return `issuer(${node.credentialKey})` + + case "not": + if (!node.inner) { + throw Error("NOT node must have 'inner' node") + } + return `not(${formatLogicNode(node.inner, level)})` + + case "add": + if (!node.left || !node.right) { + throw Error("ADD node must have both 'left' and 'right' nodes") + } + return `(${formatLogicNode(node.left)} + ${formatLogicNode(node.right)})` + + case "sub": + if (!node.left || !node.right) { + throw Error("SUB node must have both 'left' and 'right' nodes") + } + return `(${formatLogicNode(node.left)} - ${formatLogicNode(node.right)})` + + case "mul": + if (!node.left || !node.right) { + throw Error("MUL node must have both 'left' and 'right' nodes") + } + return `(${formatLogicNode(node.left)} x ${formatLogicNode(node.right)})` + + case "div": + if (!node.left || !node.right) { + throw Error("DIV node must have both 'left' and 'right' nodes") + } + return `(${formatLogicNode(node.left)} ÷ ${formatLogicNode(node.right)})` + + case "record": { + if (!node.data) { + throw Error("RECORD node must have 'data' object") + } + if (Object.keys(node.data).length === 0) { + throw Error("RECORD node must have at least one data field") + } + return Object.entries(node.data) + .map(([key, value]) => `${key}: ${formatLogicNode(value, level)}`) + .join(`\n${indent}`) + } + case "constant": { + if (!node.data || typeof node.data !== "object") { + throw Error("CONSTANT node must have 'data' object") + } + if (node.data._type === "Undefined") { + return "undefined" + } + return JSON.stringify(node.data.value) + } + case "ifThenElse": + if (!node.condition || !node.thenNode || !node.elseNode) { + throw Error( + "IF_THEN_ELSE node must have 'condition', 'thenNode', and 'elseNode'", + ) + } + return `${indent}If this condition is true:\n${indent}- ${formatLogicNode(node.condition, level + 1)}\n${indent}Then:\n${indent}- ${formatLogicNode(node.thenNode, level + 1)}\n${indent}Otherwise:\n${indent}- ${formatLogicNode(node.elseNode, level + 1)}` + + default: + throw Error(`Unknown node type: ${node.type}`) + } +} + +const formatInputsHumanReadable = (inputs: Record): string => { + const sections: string[] = [] + + // Handle credentials + const credentials = Object.entries(inputs).filter( + ([_, input]) => input.type === "credential", + ) + if (credentials.length > 0) { + sections.push("Required credentials:") + for (const [key, input] of credentials) { + const fields = extractCredentialFields(input.data) + const wrappedFields = fields.reduce((acc, field, i) => { + if (i === fields.length - 1) return acc + field + return `${acc + field}, ` + }, "") + sections.push( + `- ${key} (type: ${input.credentialType}):\n Contains: ${wrappedFields}`, + ) + } + } + + // Handle claims + const claims = Object.entries(inputs).filter( + ([_, input]) => input.type === "claim", + ) + if (claims.length > 0) { + sections.push("\nClaims:") + for (const [key, input] of claims) { + sections.push(`- ${key}: ${input.data._type}`) + } + } + + // Handle constants + const constants = Object.entries(inputs).filter( + ([_, input]) => input.type === "constant", + ) + if (constants.length > 0) { + sections.push("\nConstants:") + for (const [key, input] of constants) { + sections.push(`- ${key}: ${input.data._type} = ${input.value}`) + } + } + + return sections.join("\n") +} + +const formatClaimsHumanReadable = (claims: Record): string => { + const sections = ["\nClaimed values:"] + + for (const [key, claim] of Object.entries(claims)) { + if (claim._type === "DynamicArray" && claim.value) { + const values = claim.value.map((v: any) => v.value).join(", ") + sections.push(`- ${key}:\n ${values}`) + } else { + sections.push(`- ${key}: ${claim.value}`) + } + } + + return sections.join("\n") +} + +const containsPresentationRequest = ( + value: unknown, +): value is { + presentationRequest: any + verifierIdentity: + | string + | { address: string; tokenId: string; network: "devnet" | "mainnet" } +} => { + if (typeof value !== "object" || value === null) return false + return "presentationRequest" in value +} + +const isCredential = (value: unknown): value is Record => { + if (typeof value !== "object" || value === null) return false + return "credential" in value +} + +const simplifyCredentialData = ( + data: Record, +): Record => { + const simplified: Record = {} + for (const [key, value] of Object.entries(data)) { + if (typeof value === "object" && value !== null) { + if ("bytes" in value) { + simplified[key] = value.bytes + .map((b: { value: string }) => b.value) + .join("") + } else if ("value" in value) { + simplified[key] = value.value + } else { + simplified[key] = value + } + } else { + simplified[key] = value + } + } + return simplified +} + +export const renderPayload = (payload: string) => { + try { + const originalPayload = recoverOriginalPayload(payload) + const parsedPayload = JSON.parse(originalPayload) + + // Handle presentation request format + if (containsPresentationRequest(parsedPayload)) { + const request = parsedPayload.presentationRequest + + // Construct verifierUrl if it's a zk-app request and verifierIdentity is a zkAppAccount + const verifierUrl = + request.type === "zk-app" && + typeof parsedPayload.verifierIdentity === "object" + ? `minascan.io/${parsedPayload.verifierIdentity.network}/account/${parsedPayload.verifierIdentity.address}` + : undefined + + const formatted = [ + `Type: ${request.type}`, + "", + formatInputsHumanReadable(request.spec.inputs), + "", + `Requirements:\n${formatLogicNode(request.spec.logic.assert, 0)}`, + "", + `Output:\n${formatLogicNode(request.spec.logic.outputClaim, 0)}`, + formatClaimsHumanReadable(request.claims), + request.inputContext + ? `\nContext:\n- Type: ${request.inputContext.type}\n- Action: ${typeof request.inputContext.action === "string" ? request.inputContext.action : request.inputContext.action.value}\n- Server Nonce: ${request.inputContext.serverNonce.value}` + : "", + "origin" in parsedPayload ? `\nOrigin: ${parsedPayload.origin}` : "", + parsedPayload.verifierIdentity + ? `\nVerifier Identity: ${ + request.type === "zk-app" + ? JSON.stringify(parsedPayload.verifierIdentity, null, 2) + : parsedPayload.verifierIdentity + }` + : "", + verifierUrl ? `\nSee verifier on Minascan: https://${verifierUrl}` : "", + ].join("\n") + + return
{formatted}
+ } + + // Handle credential format + if (isCredential(parsedPayload)) { + const credentialData = + parsedPayload.credential.value?.data || parsedPayload.credential.data + const simplifiedData = simplifyCredentialData(credentialData) + const description = parsedPayload.metadata?.description + + return ( +
+ {description &&

{description}

} +
+            {JSON.stringify(simplifiedData, null, 2)}
+          
+
+ ) + } + + // Default fallback + return
{payload}
+ } catch (error) { + if (error instanceof Error) { + return handleRenderError(error) + } + // This case should never occur given the error sources + return ( +
+        Error: Unexpected render error
+      
+ ) + } +} diff --git a/packages/features/src/web-connector/views/web-connector.tsx b/packages/features/src/web-connector/views/web-connector.tsx index 8e94110c..2ff51e0e 100644 --- a/packages/features/src/web-connector/views/web-connector.tsx +++ b/packages/features/src/web-connector/views/web-connector.tsx @@ -3,8 +3,10 @@ import { MenuBar } from "@/components/menu-bar" import { Skeleton } from "@/components/skeleton" import type { SubmitHandler } from "react-hook-form" import { ConfirmationForm } from "../components/confirmation-form" +import { SelectionForm } from "../components/credential-selection-form" import { InputForm } from "../components/input-form" import type { UserInputForm } from "../types" +import { renderPayload } from "../utils/render-payload" type WebConnectorViewProps = { title: string @@ -17,6 +19,7 @@ type WebConnectorViewProps = { submitButtonLabel?: string onSubmit: SubmitHandler loading: boolean + loadingMessage?: string } export const WebConnectorView = ({ @@ -30,11 +33,19 @@ export const WebConnectorView = ({ submitButtonLabel, onSubmit, loading, + loadingMessage, }: WebConnectorViewProps) => { const onClose = () => { onReject() onDecline() } + + const handleSelectionSubmit = (selectedCredentials: string) => { + onSubmit({ userInput: selectedCredentials }) + } + + const displayTitle = loadingMessage || title + return (
@@ -42,16 +53,14 @@ export const WebConnectorView = ({
-

{title}

+

{displayTitle}

-
+
+ {renderPayload(payload)} +
-
+
{inputType === "confirmation" && ( )} + {inputType === "selection" && ( + + )}
diff --git a/packages/features/tsup.config.ts b/packages/features/tsup.config.ts index 76688060..92b3fb56 100644 --- a/packages/features/tsup.config.ts +++ b/packages/features/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { polyfillNode } from "esbuild-plugin-polyfill-node" import svgr from "esbuild-plugin-svgr" import { defineConfig } from "tsup" diff --git a/packages/key-management/package.json b/packages/key-management/package.json index 7f26c57d..8d6daca5 100644 --- a/packages/key-management/package.json +++ b/packages/key-management/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/key-management", + "name": "@palladco/key-management", "description": "An agnostic key management package for Pallad", "version": "0.0.1", "type": "module", @@ -21,17 +21,15 @@ "dependencies": { "@noble/ciphers": "0.5.3", "@noble/hashes": "1.4.0", - "@noble/secp256k1": "2.1.0", - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/pallad-core": "workspace:*", + "@palladco/mina-core": "workspace:*", + "@palladco/pallad-core": "workspace:*", "@scure/base": "1.1.7", "@scure/bip32": "1.4.0", "@scure/bip39": "1.3.0", - "buffer": "6.0.3", "mina-signer": "3.0.7", "ts-custom-error": "3.3.1" }, "devDependencies": { - "@palladxyz/common": "workspace:*" + "@palladco/common": "workspace:*" } } diff --git a/packages/key-management/src/chains/Mina/credentialDerivation.ts b/packages/key-management/src/chains/Mina/credentialDerivation.ts index b46d249b..fbac6ba2 100644 --- a/packages/key-management/src/chains/Mina/credentialDerivation.ts +++ b/packages/key-management/src/chains/Mina/credentialDerivation.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import Client from "mina-signer" import type { diff --git a/packages/key-management/src/chains/Mina/guards.ts b/packages/key-management/src/chains/Mina/guards.ts index baafa76b..929c1d58 100644 --- a/packages/key-management/src/chains/Mina/guards.ts +++ b/packages/key-management/src/chains/Mina/guards.ts @@ -1,5 +1,5 @@ import { TransactionBodySchema } from "@mina-js/utils" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" export function isConstructedTransaction(payload: any) { const transaction = TransactionBodySchema.parse(payload) diff --git a/packages/key-management/src/chains/Mina/keyDerivationUtils.ts b/packages/key-management/src/chains/Mina/keyDerivationUtils.ts index 8325595a..169d8843 100644 --- a/packages/key-management/src/chains/Mina/keyDerivationUtils.ts +++ b/packages/key-management/src/chains/Mina/keyDerivationUtils.ts @@ -1,4 +1,4 @@ -import { Network } from "@palladxyz/pallad-core" +import { Network } from "@palladco/pallad-core" import type { MinaDerivationArgs } from "./types" diff --git a/packages/key-management/src/chains/Mina/signingOperations.ts b/packages/key-management/src/chains/Mina/signingOperations.ts index 0e04f468..a362fd28 100644 --- a/packages/key-management/src/chains/Mina/signingOperations.ts +++ b/packages/key-management/src/chains/Mina/signingOperations.ts @@ -33,6 +33,7 @@ export function MinaSigningOperations( throw new Error("Invalid transaction payload") } + case "mina_signFieldsWithPassphrase": case "mina_signFields": { if (util.isFields(payload)) { return minaClient.signFields(payload.fields, privateKey) diff --git a/packages/key-management/src/chains/Mina/types.ts b/packages/key-management/src/chains/Mina/types.ts index 6d5cd67a..3d4e42cf 100644 --- a/packages/key-management/src/chains/Mina/types.ts +++ b/packages/key-management/src/chains/Mina/types.ts @@ -1,5 +1,5 @@ -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import type { Nullifier, diff --git a/packages/key-management/src/chains/README.md b/packages/key-management/src/chains/README.md index 910dda55..c2d92ce0 100644 --- a/packages/key-management/src/chains/README.md +++ b/packages/key-management/src/chains/README.md @@ -1,6 +1,6 @@ -# `@palladxyz/key-management` Package - `chains` Subfolder Documentation +# `@palladco/key-management` Package - `chains` Subfolder Documentation -The `chains` subfolder of the `@palladxyz/key-management` package contains TypeScript modules that provide functionality related to key management, including credential derivation, key derivation, and signing operations specific to the Mina protocol. Each chain's folder follows a specific strucutre, below is an overview of each file for this strucutre within the `mina` subfolder as an example: +The `chains` subfolder of the `@palladco/key-management` package contains TypeScript modules that provide functionality related to key management, including credential derivation, key derivation, and signing operations specific to the Mina protocol. Each chain's folder follows a specific strucutre, below is an overview of each file for this strucutre within the `mina` subfolder as an example: ## `credentialDerivation.ts` diff --git a/packages/key-management/src/types.ts b/packages/key-management/src/types.ts index dc34d7cd..c3a04733 100644 --- a/packages/key-management/src/types.ts +++ b/packages/key-management/src/types.ts @@ -1,5 +1,5 @@ -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import { deriveMinaCredentials, diff --git a/packages/key-management/test/mina/in-memory-key-agent.test.ts b/packages/key-management/test/mina/in-memory-key-agent.test.ts index 3c36bf30..daef60b0 100644 --- a/packages/key-management/test/mina/in-memory-key-agent.test.ts +++ b/packages/key-management/test/mina/in-memory-key-agent.test.ts @@ -1,6 +1,6 @@ -import { mnemonic } from "@palladxyz/common" -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +import { mnemonic } from "@palladco/common" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import * as bip32 from "@scure/bip32" import Client from "mina-signer" diff --git a/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts b/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts index 02343890..f4bd7e7f 100644 --- a/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts +++ b/packages/key-management/test/mina/key-agent-base-zkapp-command.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it } from "bun:test" -import { mnemonic } from "@palladxyz/common" -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +import { mnemonic } from "@palladco/common" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import Client from "mina-signer" import { utf8ToBytes } from "@noble/hashes/utils" diff --git a/packages/key-management/test/mina/key-agent-base.test.ts b/packages/key-management/test/mina/key-agent-base.test.ts index c1a955f4..d042a81f 100644 --- a/packages/key-management/test/mina/key-agent-base.test.ts +++ b/packages/key-management/test/mina/key-agent-base.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it } from "bun:test" -import { mnemonic } from "@palladxyz/common" -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +import { mnemonic } from "@palladco/common" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import * as bip32 from "@scure/bip32" import Client from "mina-signer" diff --git a/packages/key-management/test/util/guards.test.ts b/packages/key-management/test/util/guards.test.ts index ac37dd66..e11bc8db 100644 --- a/packages/key-management/test/util/guards.test.ts +++ b/packages/key-management/test/util/guards.test.ts @@ -1,5 +1,5 @@ import { describe, expect, it } from "bun:test" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { isConstructedTransaction, diff --git a/packages/key-management/tsconfig.json b/packages/key-management/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/key-management/tsconfig.json +++ b/packages/key-management/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/key-management/tsup.config.ts b/packages/key-management/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/key-management/tsup.config.ts +++ b/packages/key-management/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/mina-core/README.md b/packages/mina-core/README.md index 9e45f402..08d7471a 100644 --- a/packages/mina-core/README.md +++ b/packages/mina-core/README.md @@ -1,13 +1,13 @@ -# @palladxyz/mina-core +# @palladco/mina-core -@palladxyz/mina-core is a TypeScript package designed for helping other libraries to interact with Mina. It provides interfaces & types for many the main data strcutures of Mina that are relevant for wallets and applications. This includes providers that retrieve account information, process transaction history, submit transactions, and fetch health checks. +@palladco/mina-core is a TypeScript package designed for helping other libraries to interact with Mina. It provides interfaces & types for many the main data strcutures of Mina that are relevant for wallets and applications. This includes providers that retrieve account information, process transaction history, submit transactions, and fetch health checks. ## Installation Install the package via npm: ```bash -npm install @palladxyz/mina-core +npm install @palladco/mina-core ``` ## Usage @@ -17,7 +17,7 @@ npm install @palladxyz/mina-core The `AccountInfoProvider` interface is used to fetch account information based on a public key. ```ts -import { AccountInfoProvider } from "@palladxyz/mina-core"; +import { AccountInfoProvider } from "@palladco/mina-core"; async function getAccountInfo(provider: AccountInfoProvider) { const accountInfo = await provider.getAccountInfo({ publicKey: "..." }); @@ -29,7 +29,7 @@ async function getAccountInfo(provider: AccountInfoProvider) { The `ChainHistoryProvider` interface provides methods to fetch transactions either by addresses or by hashes. ```ts -import { ChainHistoryProvider } from "@palladxyz/mina-core"; +import { ChainHistoryProvider } from "@palladco/mina-core"; async function getTransactionsByAddresses(provider: ChainHistoryProvider) { const transactions = await provider.transactionsByAddresses({ @@ -47,7 +47,7 @@ async function getTransactionsByHashes(provider: ChainHistoryProvider) { The `TxSubmitProvider` interface allows you to submit signed transactions to the network. ```ts -import { TxSubmitProvider } from "@palladxyz/mina-core"; +import { TxSubmitProvider } from "@palladco/mina-core"; async function submitTx(provider: TxSubmitProvider) { const signedTx = // Prepare your signed transaction here @@ -60,7 +60,7 @@ async function submitTx(provider: TxSubmitProvider) { All provider types extend the base Provider interface, which provides a health check method to verify if the provider is operational. ```ts -import { Provider } from "@palladxyz/mina-core"; +import { Provider } from "@palladco/mina-core"; async function checkHealth(provider: Provider) { const healthCheckResponse = await provider.healthCheck(); diff --git a/packages/mina-core/package.json b/packages/mina-core/package.json index 7920b221..4271ec77 100644 --- a/packages/mina-core/package.json +++ b/packages/mina-core/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/mina-core", + "name": "@palladco/mina-core", "version": "0.0.1", "type": "module", "description": "Core Mina Package SDK for Pallad", @@ -17,13 +17,9 @@ "cleanup": "bunx --bun rimraf node_modules dist .turbo" }, "dependencies": { - "@palladxyz/util": "workspace:*", - "bs58check": "4.0.0", - "buffer": "6.0.3", - "mina-signer": "3.0.7" + "@palladco/util": "workspace:*" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/secp256k1": "4.0.6" + "@palladco/common": "workspace:*" } } diff --git a/packages/mina-core/src/Mina/Block.ts b/packages/mina-core/src/Mina/Block.ts index fba12961..323467ac 100644 --- a/packages/mina-core/src/Mina/Block.ts +++ b/packages/mina-core/src/Mina/Block.ts @@ -1,4 +1,4 @@ -import type { OpaqueNumber } from "@palladxyz/util" +import type { OpaqueNumber } from "@palladco/util" /** * The block number. diff --git a/packages/mina-core/src/Mina/Transaction.ts b/packages/mina-core/src/Mina/Transaction.ts index f32e5f88..e646a50a 100644 --- a/packages/mina-core/src/Mina/Transaction.ts +++ b/packages/mina-core/src/Mina/Transaction.ts @@ -1,4 +1,4 @@ -import { InvalidStringError, type OpaqueString } from "@palladxyz/util" +import { InvalidStringError, type OpaqueString } from "@palladco/util" import type { BorrowedTypes } from ".." diff --git a/packages/mina-core/src/Providers/chain-history-provider/types.ts b/packages/mina-core/src/Providers/chain-history-provider/types.ts index c48a2cb4..b3865816 100644 --- a/packages/mina-core/src/Providers/chain-history-provider/types.ts +++ b/packages/mina-core/src/Providers/chain-history-provider/types.ts @@ -1,4 +1,4 @@ -import type { Range } from "@palladxyz/util" +import type { Range } from "@palladco/util" import type { Mina, Provider } from "../.." diff --git a/packages/mina-core/tsconfig.json b/packages/mina-core/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/mina-core/tsconfig.json +++ b/packages/mina-core/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/mina-core/tsup.config.ts b/packages/mina-core/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/mina-core/tsup.config.ts +++ b/packages/mina-core/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/offchain-data/README.md b/packages/offchain-data/README.md index af2c116a..ad431d20 100644 --- a/packages/offchain-data/README.md +++ b/packages/offchain-data/README.md @@ -1,3 +1,3 @@ -# @palladxyz/offchain-data +# @palladco/offchain-data Package for fetching off-chain data like fiat prices. diff --git a/packages/offchain-data/package.json b/packages/offchain-data/package.json index 40970057..5b081f1e 100644 --- a/packages/offchain-data/package.json +++ b/packages/offchain-data/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/offchain-data", + "name": "@palladco/offchain-data", "description": "Off-chain data fetching services.", "type": "module", "version": "1.0.0", @@ -21,6 +21,6 @@ "swr": "2.2.5" }, "devDependencies": { - "@palladxyz/common": "workspace:*" + "@palladco/common": "workspace:*" } } diff --git a/packages/offchain-data/tsconfig.json b/packages/offchain-data/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/offchain-data/tsconfig.json +++ b/packages/offchain-data/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/offchain-data/tsup.config.ts b/packages/offchain-data/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/offchain-data/tsup.config.ts +++ b/packages/offchain-data/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/pallad-core/README.md b/packages/pallad-core/README.md index 09d88d82..82cd6bcd 100644 --- a/packages/pallad-core/README.md +++ b/packages/pallad-core/README.md @@ -1,13 +1,13 @@ -# @palladxyz/mina-core +# @palladco/mina-core -@palladxyz/mina-core is a TypeScript package designed for interacting with the Mina Protocol. It provides interfaces for retrieving account information, processing transaction history, submitting transactions, and provider health checks. The package also includes the core types that represent the main data structures of the Mina Protocol. +@palladco/mina-core is a TypeScript package designed for interacting with the Mina Protocol. It provides interfaces for retrieving account information, processing transaction history, submitting transactions, and provider health checks. The package also includes the core types that represent the main data structures of the Mina Protocol. ## Installation Install the package via npm: ```bash -npm install @palladxyz/mina-core +npm install @palladco/mina-core ``` ## Usage @@ -17,7 +17,7 @@ npm install @palladxyz/mina-core The `AccountInfoProvider` interface is used to fetch account information based on a public key. ```ts -import { AccountInfoProvider } from "@palladxyz/mina-core"; +import { AccountInfoProvider } from "@palladco/mina-core"; async function getAccountInfo(provider: AccountInfoProvider) { const accountInfo = await provider.getAccountInfo({ publicKey: "..." }); @@ -29,7 +29,7 @@ async function getAccountInfo(provider: AccountInfoProvider) { The `ChainHistoryProvider` interface provides methods to fetch transactions either by addresses or by hashes. ```ts -import { ChainHistoryProvider } from "@palladxyz/mina-core"; +import { ChainHistoryProvider } from "@palladco/mina-core"; async function getTransactionsByAddresses(provider: ChainHistoryProvider) { const transactions = await provider.transactionsByAddresses({ @@ -47,7 +47,7 @@ async function getTransactionsByHashes(provider: ChainHistoryProvider) { The `TxSubmitProvider` interface allows you to submit signed transactions to the network. ```ts -import { TxSubmitProvider } from "@palladxyz/mina-core"; +import { TxSubmitProvider } from "@palladco/mina-core"; async function submitTx(provider: TxSubmitProvider) { const signedTx = // Prepare your signed transaction here @@ -60,7 +60,7 @@ async function submitTx(provider: TxSubmitProvider) { All provider types extend the base Provider interface, which provides a health check method to verify if the provider is operational. ```ts -import { Provider } from "@palladxyz/mina-core"; +import { Provider } from "@palladco/mina-core"; async function checkHealth(provider: Provider) { const healthCheckResponse = await provider.healthCheck(); diff --git a/packages/pallad-core/package.json b/packages/pallad-core/package.json index 7a8bfc4b..35007f82 100644 --- a/packages/pallad-core/package.json +++ b/packages/pallad-core/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/pallad-core", + "name": "@palladco/pallad-core", "version": "0.0.1", "type": "module", "description": "Core Pallad Package", @@ -18,17 +18,11 @@ "cleanup": "bunx --bun rimraf node_modules dist .turbo" }, "dependencies": { - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/util": "workspace:*", - "bs58check": "4.0.0", - "buffer": "6.0.3", - "mina-signer": "3.0.7", - "viem": "2.18.4", - "vite-plugin-top-level-await": "1.4.2", - "vite-plugin-wasm": "3.3.0" + "@palladco/mina-core": "workspace:*", + "@palladco/util": "workspace:*", + "viem": "2.18.4" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/secp256k1": "4.0.6" + "@palladco/common": "workspace:*" } } diff --git a/packages/pallad-core/src/Mina/Providers/account-info-provider/types.ts b/packages/pallad-core/src/Mina/Providers/account-info-provider/types.ts index d8471c6a..e130a22a 100644 --- a/packages/pallad-core/src/Mina/Providers/account-info-provider/types.ts +++ b/packages/pallad-core/src/Mina/Providers/account-info-provider/types.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { Provider } from "../.." diff --git a/packages/pallad-core/src/Mina/Providers/chain-history-provider/types.ts b/packages/pallad-core/src/Mina/Providers/chain-history-provider/types.ts index 01691b13..b14532d5 100644 --- a/packages/pallad-core/src/Mina/Providers/chain-history-provider/types.ts +++ b/packages/pallad-core/src/Mina/Providers/chain-history-provider/types.ts @@ -1,5 +1,5 @@ -import type { Mina } from "@palladxyz/mina-core" -import type { Range } from "@palladxyz/util" +import type { Mina } from "@palladco/mina-core" +import type { Range } from "@palladco/util" import type { Provider } from "../.." diff --git a/packages/pallad-core/src/Mina/Providers/tx-submit-provider/types.ts b/packages/pallad-core/src/Mina/Providers/tx-submit-provider/types.ts index dee20380..c049ef92 100644 --- a/packages/pallad-core/src/Mina/Providers/tx-submit-provider/types.ts +++ b/packages/pallad-core/src/Mina/Providers/tx-submit-provider/types.ts @@ -1,4 +1,4 @@ -import type { BorrowedTypes, Mina } from "@palladxyz/mina-core" +import type { BorrowedTypes, Mina } from "@palladco/mina-core" import type { Provider } from "../provider" diff --git a/packages/pallad-core/src/Mina/Providers/unified-mina-provider.ts b/packages/pallad-core/src/Mina/Providers/unified-mina-provider.ts index 6a02c6a2..2f3f8a2d 100644 --- a/packages/pallad-core/src/Mina/Providers/unified-mina-provider.ts +++ b/packages/pallad-core/src/Mina/Providers/unified-mina-provider.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { AccountInfo, AccountInfoArgs } from "./account-info-provider" import type { diff --git a/packages/pallad-core/src/Pallad/providers/account-info-provider/types.ts b/packages/pallad-core/src/Pallad/providers/account-info-provider/types.ts index df725e52..4ef41fec 100644 --- a/packages/pallad-core/src/Pallad/providers/account-info-provider/types.ts +++ b/packages/pallad-core/src/Pallad/providers/account-info-provider/types.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { Address, Chain } from "viem" import type { Provider } from "../" diff --git a/packages/pallad-core/src/Pallad/providers/tx-submit-provider/types.ts b/packages/pallad-core/src/Pallad/providers/tx-submit-provider/types.ts index cb9fea6e..9d177463 100644 --- a/packages/pallad-core/src/Pallad/providers/tx-submit-provider/types.ts +++ b/packages/pallad-core/src/Pallad/providers/tx-submit-provider/types.ts @@ -1,4 +1,4 @@ -import type { BorrowedTypes, Mina } from "@palladxyz/mina-core" +import type { BorrowedTypes, Mina } from "@palladco/mina-core" import type { Provider } from "../provider" diff --git a/packages/pallad-core/src/Pallad/providers/types.ts b/packages/pallad-core/src/Pallad/providers/types.ts index 188dcc4e..011df823 100644 --- a/packages/pallad-core/src/Pallad/providers/types.ts +++ b/packages/pallad-core/src/Pallad/providers/types.ts @@ -1,4 +1,4 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { Address, GetTransactionReturnType, Hash } from "viem" export type TransactionHash = Mina.TxId[] | Hash[] diff --git a/packages/pallad-core/tsconfig.json b/packages/pallad-core/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/pallad-core/tsconfig.json +++ b/packages/pallad-core/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/pallad-core/tsup.config.ts b/packages/pallad-core/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/pallad-core/tsup.config.ts +++ b/packages/pallad-core/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/providers/README.md b/packages/providers/README.md index 1af83fcc..c44946ff 100644 --- a/packages/providers/README.md +++ b/packages/providers/README.md @@ -1,4 +1,4 @@ -# @palladxyz/providers +# @palladco/providers This TypeScript library creates Providers that can read and write (mutate) data to Mina via a set of API providers such as Minascan. @@ -6,7 +6,7 @@ A Provider is an abstraction that encapsulates the functionality for interacting ## Implementation Detail -While these providers can be used individually, they are more functional in nature than the founding `@palladxyz/mina-graphql` providers, removing the object oriented design in many of them (full set to be determined). Each provider is scoped to specifically either read, write, or listen; not focusing on specifically storing data themselves they are an abstraction for an application. In Pallad's case, the `vault` requires this abstraction as it stores the arguments for each provider. +While these providers can be used individually, they are more functional in nature than the founding `@palladco/mina-graphql` providers, removing the object oriented design in many of them (full set to be determined). Each provider is scoped to specifically either read, write, or listen; not focusing on specifically storing data themselves they are an abstraction for an application. In Pallad's case, the `vault` requires this abstraction as it stores the arguments for each provider. ### Provider Sources diff --git a/packages/providers/package.json b/packages/providers/package.json index 8dde595b..3b687fa0 100644 --- a/packages/providers/package.json +++ b/packages/providers/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/providers", + "name": "@palladco/providers", "version": "0.0.1", "description": "Proivder Package SDK for Pallad.", "type": "module", @@ -19,26 +19,19 @@ }, "dependencies": { "@noble/hashes": "1.4.0", - "@palladxyz/key-management": "workspace:*", - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/pallad-core": "workspace:*", - "@palladxyz/util": "workspace:*", - "bs58check": "4.0.0", - "buffer": "6.0.3", - "events": "3.3.0", + "@palladco/key-management": "workspace:*", + "@palladco/mina-core": "workspace:*", + "@palladco/pallad-core": "workspace:*", + "@palladco/util": "workspace:*", "graphql": "16.9.0", "graphql-request": "7.1.0", "json-bigint": "1.0.0", "mina-signer": "3.0.7", - "subscriptions-transport-ws": "0.11.0", - "viem": "2.18.4", - "ws": "8.18.0" + "subscriptions-transport-ws": "0.11.0" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/events": "3.0.3", + "@palladco/common": "workspace:*", "@types/json-bigint": "1.0.4", - "esbuild-plugin-polyfill-node": "0.3.0", - "msw": "2.3.4" + "esbuild-plugin-polyfill-node": "0.3.0" } } diff --git a/packages/providers/src/blockberry-provider/chain-history/chain-history-provider.ts b/packages/providers/src/blockberry-provider/chain-history/chain-history-provider.ts index 7a6b5de4..6cee8004 100644 --- a/packages/providers/src/blockberry-provider/chain-history/chain-history-provider.ts +++ b/packages/providers/src/blockberry-provider/chain-history/chain-history-provider.ts @@ -1,9 +1,9 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { ChainHistoryProvider, TransactionsByAddressesArgs, Tx, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" //import { healthCheck } from "../utils/health-check-utils"; diff --git a/packages/providers/src/mina-node/account-info/account-info-provider.ts b/packages/providers/src/mina-node/account-info/account-info-provider.ts index 719096b1..4318503c 100644 --- a/packages/providers/src/mina-node/account-info/account-info-provider.ts +++ b/packages/providers/src/mina-node/account-info/account-info-provider.ts @@ -2,7 +2,7 @@ import type { AccountInfo, AccountInfoArgs, AccountInfoProvider, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createGraphQLRequest } from "../utils/fetch-utils" import { healthCheck } from "../utils/health-check-utils" diff --git a/packages/providers/src/mina-node/account-info/queries.ts b/packages/providers/src/mina-node/account-info/queries.ts index e533c374..347f9867 100644 --- a/packages/providers/src/mina-node/account-info/queries.ts +++ b/packages/providers/src/mina-node/account-info/queries.ts @@ -17,7 +17,7 @@ export const getAccountBalance = ` } } ` -import type { TokenIdMap } from "@palladxyz/mina-core" +import type { TokenIdMap } from "@palladco/mina-core" export function getTokenAccountInfoQuery(tokenIds: TokenIdMap): string { // Start with the base part of the query diff --git a/packages/providers/src/mina-node/block-listener/BlockListenerProvider.ts b/packages/providers/src/mina-node/block-listener/BlockListenerProvider.ts index 21409358..160bb4b9 100644 --- a/packages/providers/src/mina-node/block-listener/BlockListenerProvider.ts +++ b/packages/providers/src/mina-node/block-listener/BlockListenerProvider.ts @@ -1,4 +1,4 @@ -import type { AccountInfo, AccountInfoArgs } from "@palladxyz/mina-core" +import type { AccountInfo, AccountInfoArgs } from "@palladco/mina-core" import type { ExecutionResult } from "graphql" import { GraphQLClient, gql } from "graphql-request" import { SubscriptionClient } from "subscriptions-transport-ws" diff --git a/packages/providers/src/mina-node/chain-history/chain-history-provider.ts b/packages/providers/src/mina-node/chain-history/chain-history-provider.ts index 222a16b0..f0e03a8a 100644 --- a/packages/providers/src/mina-node/chain-history/chain-history-provider.ts +++ b/packages/providers/src/mina-node/chain-history/chain-history-provider.ts @@ -3,7 +3,7 @@ import type { TransactionsByAddressesArgs, TransactionsByHashesArgs, Tx, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createGraphQLRequest } from "../utils/fetch-utils" import { diff --git a/packages/providers/src/mina-node/node-status/node-status-provider.ts b/packages/providers/src/mina-node/node-status/node-status-provider.ts index f6756643..9d364c83 100644 --- a/packages/providers/src/mina-node/node-status/node-status-provider.ts +++ b/packages/providers/src/mina-node/node-status/node-status-provider.ts @@ -1,4 +1,4 @@ -import type { NodeStatus, NodeStatusProvider } from "@palladxyz/pallad-core" +import type { NodeStatus, NodeStatusProvider } from "@palladco/pallad-core" import { createGraphQLRequest } from "../utils/fetch-utils" import { healthCheck } from "../utils/health-check-utils" diff --git a/packages/providers/src/mina-node/types.ts b/packages/providers/src/mina-node/types.ts index 10aaee8a..1a80d91f 100644 --- a/packages/providers/src/mina-node/types.ts +++ b/packages/providers/src/mina-node/types.ts @@ -8,7 +8,7 @@ import type { TransactionsByIdsArgs, TxStatus, TxStatusArgs, -} from "@palladxyz/mina-core" +} from "@palladco/mina-core" /** * An interface that abstracts over Mina node queries. */ diff --git a/packages/providers/src/unified-providers/account-info-provider.ts b/packages/providers/src/unified-providers/account-info-provider.ts index c3247843..47620fad 100644 --- a/packages/providers/src/unified-providers/account-info-provider.ts +++ b/packages/providers/src/unified-providers/account-info-provider.ts @@ -3,7 +3,7 @@ import type { AccountInfoArgs, AccountInfoProvider, HealthCheckResponse, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createAccountInfoProvider as mn } from "../mina-node" import type { ProviderConfig } from "./types" diff --git a/packages/providers/src/unified-providers/chain-history-provider.ts b/packages/providers/src/unified-providers/chain-history-provider.ts index 961759cc..193675d3 100644 --- a/packages/providers/src/unified-providers/chain-history-provider.ts +++ b/packages/providers/src/unified-providers/chain-history-provider.ts @@ -4,7 +4,7 @@ import type { TransactionsByAddressesArgs, TransactionsByHashesArgs, Tx, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createChainHistoryProvider as ms } from "../blockberry-provider" import { createChainHistoryProvider as zs } from "../zeko-scan" diff --git a/packages/providers/src/unified-providers/node-status-provider.ts b/packages/providers/src/unified-providers/node-status-provider.ts index 1e2f9ba8..9adac7a7 100644 --- a/packages/providers/src/unified-providers/node-status-provider.ts +++ b/packages/providers/src/unified-providers/node-status-provider.ts @@ -2,7 +2,7 @@ import type { HealthCheckResponse, NodeStatus, NodeStatusProvider, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createNodeStatusProvider as mn } from "../mina-node" import type { ProviderConfig } from "./types" diff --git a/packages/providers/src/unified-providers/unified-provider.ts b/packages/providers/src/unified-providers/unified-provider.ts index 771e7a3c..25fa9db9 100644 --- a/packages/providers/src/unified-providers/unified-provider.ts +++ b/packages/providers/src/unified-providers/unified-provider.ts @@ -5,7 +5,7 @@ import type { TransactionsByAddressesArgs, Tx, UnifiedChainProviderType, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" import { createAccountInfoProvider } from "./account-info-provider" import { createChainHistoryProvider } from "./chain-history-provider" diff --git a/packages/providers/src/zeko-scan/chain-history/chain-history-provider.ts b/packages/providers/src/zeko-scan/chain-history/chain-history-provider.ts index 514ddd9a..9ded1260 100644 --- a/packages/providers/src/zeko-scan/chain-history/chain-history-provider.ts +++ b/packages/providers/src/zeko-scan/chain-history/chain-history-provider.ts @@ -1,9 +1,9 @@ -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import type { ChainHistoryProvider, TransactionsByAddressesArgs, Tx, -} from "@palladxyz/pallad-core" +} from "@palladco/pallad-core" const convertToTransactionBody = ( data: any[], diff --git a/packages/providers/test/blockberry/chain-history-provider.test.ts b/packages/providers/test/blockberry/chain-history-provider.test.ts index 9658f90e..ace79a5b 100644 --- a/packages/providers/test/blockberry/chain-history-provider.test.ts +++ b/packages/providers/test/blockberry/chain-history-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { Blockberry } from "../../src" diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts index 0df31a0e..576c1289 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/account-info-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { TokenIdMap } from "@palladxyz/mina-core" +import type { TokenIdMap } from "@palladco/mina-core" import { MinaNode } from "../../../../src" diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/chain-history-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/chain-history-provider.test.ts index 73ee1667..0867a6ca 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/chain-history-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/chain-history-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { MinaNode } from "../../../../src" const nodeUrl = diff --git a/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts b/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts index c6e6080b..3cde1675 100644 --- a/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts +++ b/packages/providers/test/mina-node/l1-mina-node/individual-providers/submit-tx-provider.test.ts @@ -6,9 +6,9 @@ import { type FromBip39MnemonicWordsProps, InMemoryKeyAgent, type MinaSpecificArgs, -} from "@palladxyz/key-management" -import { Mina, type TokenIdMap } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +} from "@palladco/key-management" +import { Mina, type TokenIdMap } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import type { Payment, SignedLegacy, diff --git a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/account-info-provider.test.ts b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/account-info-provider.test.ts index 50cc6afc..c867ce46 100644 --- a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/account-info-provider.test.ts +++ b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/account-info-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { TokenIdMap } from "@palladxyz/mina-core" +import type { TokenIdMap } from "@palladco/mina-core" import { MinaNode } from "../../../../src" const nodeUrl = process.env.NODE_URL || "https://devnet.zeko.io/graphql" diff --git a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts index 75d32ff3..b37a2258 100644 --- a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts +++ b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/submit-tx-provider.test.ts @@ -6,9 +6,9 @@ import { type GroupedCredentials, InMemoryKeyAgent, type MinaSpecificArgs, -} from "@palladxyz/key-management" -import { type AccountInfo, Mina, type TokenIdMap } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +} from "@palladco/key-management" +import { type AccountInfo, Mina, type TokenIdMap } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import type { Payment, SignedLegacy, diff --git a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts index c7c1f2e6..9aac9106 100644 --- a/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts +++ b/packages/providers/test/mina-node/zeko-sequencer/individual-providers/util.ts @@ -1,4 +1,4 @@ -import { Mina } from "@palladxyz/mina-core" +import { Mina } from "@palladco/mina-core" import Client from "mina-signer" import type { Payment, diff --git a/packages/providers/test/unified-providers/individual-providers/account-info-provider.test.ts b/packages/providers/test/unified-providers/individual-providers/account-info-provider.test.ts index 369dc544..5266fd8b 100644 --- a/packages/providers/test/unified-providers/individual-providers/account-info-provider.test.ts +++ b/packages/providers/test/unified-providers/individual-providers/account-info-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { TokenIdMap } from "@palladxyz/mina-core" +import type { TokenIdMap } from "@palladco/mina-core" import { type ProviderConfig, createAccountInfoProvider } from "../../../src" diff --git a/packages/providers/test/unified-providers/individual-providers/chain-history-provider.test.ts b/packages/providers/test/unified-providers/individual-providers/chain-history-provider.test.ts index dc7c0da9..fc59ab80 100644 --- a/packages/providers/test/unified-providers/individual-providers/chain-history-provider.test.ts +++ b/packages/providers/test/unified-providers/individual-providers/chain-history-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { type ProviderConfig, createChainHistoryProvider } from "../../../src" diff --git a/packages/providers/test/unified-providers/unified-provider.test.ts b/packages/providers/test/unified-providers/unified-provider.test.ts index e4f0cd65..a63f85fb 100644 --- a/packages/providers/test/unified-providers/unified-provider.test.ts +++ b/packages/providers/test/unified-providers/unified-provider.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { TokenIdMap } from "@palladxyz/mina-core" -import type { Tx } from "@palladxyz/pallad-core" +import type { TokenIdMap } from "@palladco/mina-core" +import type { Tx } from "@palladco/pallad-core" import { type ProviderConfig, createChainProvider } from "../../src" diff --git a/packages/providers/test/zeko-scan/chain-history-provider.test.ts b/packages/providers/test/zeko-scan/chain-history-provider.test.ts index 6128936f..2f0181d7 100644 --- a/packages/providers/test/zeko-scan/chain-history-provider.test.ts +++ b/packages/providers/test/zeko-scan/chain-history-provider.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { Mina } from "@palladxyz/mina-core" +import type { Mina } from "@palladco/mina-core" import { ZekoScan } from "../../src" diff --git a/packages/providers/tsconfig.json b/packages/providers/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/providers/tsconfig.json +++ b/packages/providers/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/providers/tsup.config.ts b/packages/providers/tsup.config.ts index 3d31da11..0673190e 100644 --- a/packages/providers/tsup.config.ts +++ b/packages/providers/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { polyfillNode } from "esbuild-plugin-polyfill-node" import { defineConfig } from "tsup" diff --git a/packages/util/README.md b/packages/util/README.md index d3381be1..f54b84ff 100644 --- a/packages/util/README.md +++ b/packages/util/README.md @@ -1,3 +1,3 @@ -# @palladxyz/util +# @palladco/util This TypeScript library provides util functions for other Pallad SDK packages. diff --git a/packages/util/package.json b/packages/util/package.json index 9647b9a0..f88dfd3d 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/util", + "name": "@palladco/util", "version": "0.0.1", "type": "module", "description": "Util Package SDK for Pallad", @@ -18,13 +18,9 @@ "cleanup": "bunx --bun rimraf node_modules dist .turbo" }, "dependencies": { - "bs58check": "4.0.0", - "buffer": "6.0.3", - "mina-signer": "3.0.7", "ts-custom-error": "3.3.1" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/secp256k1": "4.0.6" + "@palladco/common": "workspace:*" } } diff --git a/packages/util/tsconfig.json b/packages/util/tsconfig.json index f4e2e06e..ffab31d1 100644 --- a/packages/util/tsconfig.json +++ b/packages/util/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "@palladxyz/common/tsconfig.json" + "extends": "@palladco/common/tsconfig.json" } diff --git a/packages/util/tsup.config.ts b/packages/util/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/util/tsup.config.ts +++ b/packages/util/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/vault/README.md b/packages/vault/README.md index 87da0c59..1e8c014f 100644 --- a/packages/vault/README.md +++ b/packages/vault/README.md @@ -1,12 +1,12 @@ -# @palladxyz/vault +# @palladco/vault ## Introduction -The `@palladxyz/vault` package offers a robust solution for managing key agents, credentials, and accounts within the wallet. +The `@palladco/vault` package offers a robust solution for managing key agents, credentials, and accounts within the wallet. ## `useVault`: Central Interface for Wallet Management -The `useVault` hook is the core interface of the `@palladxyz/vault` package, encapsulating the functionalities of account, credential, and key agent management in an integrated manner. It utilizes `zustand` for state management and `immer` for immutable state updates. +The `useVault` hook is the core interface of the `@palladco/vault` package, encapsulating the functionalities of account, credential, and key agent management in an integrated manner. It utilizes `zustand` for state management and `immer` for immutable state updates. ## Features @@ -17,8 +17,8 @@ The `useVault` hook is the core interface of the `@palladxyz/vault` package, enc ## Example Usage ```ts -import { useVault } from '@palladxyz/vault'; -import { Network } from '@palladxyz/key-management'; +import { useVault } from '@palladco/vault'; +import { Network } from '@palladco/key-management'; // Example usage within a component or function const MyComponent = () => { diff --git a/packages/vault/package.json b/packages/vault/package.json index 01904957..5adf50d3 100644 --- a/packages/vault/package.json +++ b/packages/vault/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/vault", + "name": "@palladco/vault", "version": "0.0.1", "type": "module", "description": "A Vault for the Mina Wallet Package for Pallad", @@ -18,29 +18,22 @@ "cleanup": "bunx --bun rimraf node_modules dist .turbo" }, "dependencies": { - "@mina-js/klesia-sdk": "https://pkg.pr.new/palladians/mina-js/@mina-js/klesia-sdk@a51d3b4", + "@mina-js/klesia-sdk": "https://pkg.pr.new/palladians/mina-js/@mina-js/klesia-sdk@261950d", "@noble/hashes": "1.4.0", - "@palladxyz/key-management": "workspace:*", - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/pallad-core": "workspace:*", - "@palladxyz/providers": "workspace:*", - "@palladxyz/util": "workspace:*", + "@palladco/key-management": "workspace:*", + "@palladco/mina-core": "workspace:*", + "@palladco/pallad-core": "workspace:*", + "@palladco/providers": "workspace:*", + "@palladco/util": "workspace:*", "@plasmohq/storage": "1.11.0", - "bs58check": "4.0.0", - "buffer": "6.0.3", "dayjs": "1.11.12", "immer": "10.1.1", - "rambda": "9.2.1", - "redux-logger": "3.0.6", "superjson": "2.2.1", "unique-names-generator": "4.7.1", "zustand": "4.5.4" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/secp256k1": "4.0.6", - "mina-signer": "3.0.7", - "msw": "2.3.4", + "@palladco/common": "workspace:*", "vite": "5.3.5" } } diff --git a/packages/vault/src/account/accountState.ts b/packages/vault/src/account/accountState.ts index e2c55920..685ea003 100644 --- a/packages/vault/src/account/accountState.ts +++ b/packages/vault/src/account/accountState.ts @@ -1,5 +1,5 @@ -import type { ChainAddress } from "@palladxyz/key-management" -import type { AccountInfo, Tx } from "@palladxyz/pallad-core" +import type { ChainAddress } from "@palladco/key-management" +import type { AccountInfo, Tx } from "@palladco/pallad-core" export type SingleAccountState = { accountInfo: Record diff --git a/packages/vault/src/credentials/credentialsState.ts b/packages/vault/src/credentials/credentialsState.ts index 922cba78..367baae8 100644 --- a/packages/vault/src/credentials/credentialsState.ts +++ b/packages/vault/src/credentials/credentialsState.ts @@ -1,8 +1,4 @@ -/** - * @file Represents the state definitions related to credentials specific to keyAgents & accounts. - */ - -import type { GroupedCredentials } from "@palladxyz/key-management" +import type { GroupedCredentials } from "@palladco/key-management" import type { KeyAgentName } from "../keyAgent" import type { SearchQuery } from "../utils/utils" @@ -10,30 +6,18 @@ import type { SearchQuery } from "../utils/utils" export type CredentialName = string export type StoredCredential = GroupedCredentials | undefined -/** - * Type representing the basic state of a credential. - * @typedef {Object} SingleCredentialState - */ export type SingleCredentialState = { credentialName: CredentialName keyAgentName: KeyAgentName credential: StoredCredential } -/** - * Constant representing the initial credential state - * @typedef {Object} - */ export const initialCredentialState: SingleCredentialState = { credentialName: "", keyAgentName: "", credential: undefined, } -/** - * Type representing the store's state and actions combined. - * @typedef {Object} CredentialsState - */ export type CredentialStore = { credentials: Record ensureCredential: ( diff --git a/packages/vault/src/keyAgent/README.md b/packages/vault/src/keyAgent/README.md index a64e396d..183a7b40 100644 --- a/packages/vault/src/keyAgent/README.md +++ b/packages/vault/src/keyAgent/README.md @@ -1,6 +1,6 @@ # Key Agent Store -This TypeScript module provides a state management store for cryptographic key agents using Zustand, Immer, and the `@palladxyz/key-management` package. It is the key agent store for Pallad and it offers a robust set of functionalities to manage key agents securely in memory. +This TypeScript module provides a state management store for cryptographic key agents using Zustand, Immer, and the `@palladco/key-management` package. It is the key agent store for Pallad and it offers a robust set of functionalities to manage key agents securely in memory. ## Key Files - `key-agent-store.ts`: Contains the core logic for the Zustand store slice managing the state of key agents. @@ -35,4 +35,4 @@ useStore.getState().initialiseKeyAgent("myKeyAgent", KeyAgents.InMemory, { mnemonicWords, getPassphrase: async () => "yourSecurePassphrase" }); -``` \ No newline at end of file +``` diff --git a/packages/vault/src/keyAgent/keyAgentState.ts b/packages/vault/src/keyAgent/keyAgentState.ts index 19a06062..bdaa50be 100644 --- a/packages/vault/src/keyAgent/keyAgentState.ts +++ b/packages/vault/src/keyAgent/keyAgentState.ts @@ -12,7 +12,7 @@ import type { GroupedCredentials, InMemoryKeyAgent, SerializableInMemoryKeyAgentData, -} from "@palladxyz/key-management" +} from "@palladco/key-management" export type KeyAgentName = string export enum KeyAgents { diff --git a/packages/vault/src/keyAgent/keyAgentStore.ts b/packages/vault/src/keyAgent/keyAgentStore.ts index cf9f9020..04e17f3f 100644 --- a/packages/vault/src/keyAgent/keyAgentStore.ts +++ b/packages/vault/src/keyAgent/keyAgentStore.ts @@ -1,7 +1,7 @@ import { type FromBip39MnemonicWordsProps, InMemoryKeyAgent, -} from "@palladxyz/key-management" +} from "@palladco/key-management" import { produce } from "immer" import type { StateCreator } from "zustand" diff --git a/packages/vault/src/lib/utils.ts b/packages/vault/src/lib/utils.ts index 8d56f53d..9c0ac276 100644 --- a/packages/vault/src/lib/utils.ts +++ b/packages/vault/src/lib/utils.ts @@ -1,4 +1,4 @@ -import type { CredentialName } from "@palladxyz/vault" +import type { CredentialName } from "@palladco/vault" import { type Config, adjectives, diff --git a/packages/vault/src/network-info/default.ts b/packages/vault/src/network-info/default.ts index aa22698a..162b72d5 100644 --- a/packages/vault/src/network-info/default.ts +++ b/packages/vault/src/network-info/default.ts @@ -1,4 +1,4 @@ -import type { ProviderConfig } from "@palladxyz/providers" +import type { ProviderConfig } from "@palladco/providers" import type { NetworkId } from "./network-info-state" diff --git a/packages/vault/src/network-info/network-info-state.ts b/packages/vault/src/network-info/network-info-state.ts index 46ae8293..ab698d79 100644 --- a/packages/vault/src/network-info/network-info-state.ts +++ b/packages/vault/src/network-info/network-info-state.ts @@ -3,7 +3,7 @@ * @typedef {Object} NetworkInfoStore */ -import type { ProviderConfig } from "@palladxyz/providers" +import type { ProviderConfig } from "@palladco/providers" export type NetworkId = string diff --git a/packages/vault/src/objects/default.ts b/packages/vault/src/objects/default.ts deleted file mode 100644 index b1ae1737..00000000 --- a/packages/vault/src/objects/default.ts +++ /dev/null @@ -1,32 +0,0 @@ -export const EXAMPLE_CREDENTIAL_NAME = "Example Pallad Credential" -export const EXAMPLE_CREDENTIAL = { - "@context": ["https://www.w3.org/2018/credentials/v1"], - id: "http://example.edu/credentials/3732", - type: ["VerifiableCredential", "UniversityDegreeCredential"], - issuer: "University of Example", - issuanceDate: "2010-01-01T00:00:00Z", - credentialSubject: { - id: "did:mina:B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", - degree: { - type: "BachelorDegree", - name: "Bachelor of Science and Arts", - }, - }, - proof: { - type: "Kimchi", - created: "2023-09-19T12:40:16Z", - proof: { - publicInput: ["0"], - publicOutput: ["1"], - maxProofsVerified: 0, - proof: "KChzdGF0ZW1...SkpKSkp", - }, - }, -} - -export const DEFAULT_OBJECTS = { - [EXAMPLE_CREDENTIAL_NAME]: { - objectName: EXAMPLE_CREDENTIAL_NAME, - object: EXAMPLE_CREDENTIAL, - }, -} diff --git a/packages/vault/src/objects/index.ts b/packages/vault/src/objects/index.ts index 977ec058..d1208f8c 100644 --- a/packages/vault/src/objects/index.ts +++ b/packages/vault/src/objects/index.ts @@ -1,3 +1,2 @@ -export * from "./default" export * from "./objectsState" export * from "./objectsStore" diff --git a/packages/vault/src/objects/objectsState.ts b/packages/vault/src/objects/objectsState.ts index e07bd906..fde7943f 100644 --- a/packages/vault/src/objects/objectsState.ts +++ b/packages/vault/src/objects/objectsState.ts @@ -1,31 +1,24 @@ -/** - * @file Represents the state definitions related to objects (for example issued credentials). - */ import type { Json } from "@mina-js/utils" import type { SearchQuery } from "../utils/utils" -export type ObjectName = string +export type CredentialId = string export type StoredObject = undefined | object -/** - * Constant representing the initial object state - * @typedef {Object} - */ export const initialObjectState: Json = { - objectName: "", - object: {}, + credentialId: "", + credential: {}, } -export type ObjectsStore = Record -/** - * Type representing the store's state and actions combined. - * @typedef {Object} ObjectStore - */ +export type ObjectsStore = Record + export type ObjectStore = { objects: ObjectsStore - ensureObject: (objectName: ObjectName) => void - setObject: (objectState: Json) => void - getObject: (objectName: ObjectName) => Json | typeof initialObjectState - removeObject: (name: ObjectName) => void - searchObjects(query: SearchQuery, props?: string[]): StoredObject[] + ensureObject: (credentialId: CredentialId) => void + setObject: (props: { credentialId: CredentialId; credential: Json }) => void + getObject: (credentialId: CredentialId) => Json | typeof initialObjectState + removeObject: (credentialId: CredentialId) => void + searchObjects(props: { + query: SearchQuery + props: string[] | undefined + }): StoredObject[] clearObjects: () => void } diff --git a/packages/vault/src/objects/objectsStore.ts b/packages/vault/src/objects/objectsStore.ts index e155d289..12c9cdfa 100644 --- a/packages/vault/src/objects/objectsStore.ts +++ b/packages/vault/src/objects/objectsStore.ts @@ -2,56 +2,52 @@ import { produce } from "immer" import { type StateCreator, create } from "zustand" import { matchesQuery } from "../utils/utils" -import { DEFAULT_OBJECTS } from "./default" import { type ObjectStore, initialObjectState } from "./objectsState" export const objectSlice: StateCreator = (set, get) => ({ - objects: DEFAULT_OBJECTS, - ensureObject: (objectName) => { + objects: {}, + ensureObject: (credentialId) => { set( produce((draft) => { - draft.objects[objectName] = draft.objects[objectName] || { + draft.objects[credentialId] = draft.objects[credentialId] || { ...(initialObjectState as object), - objectName, + credentialId, } }), ) }, - setObject: (objectState: any) => { - const { objectName } = objectState + setObject: ({ credentialId, credential }) => { set((current) => produce(current, (draft: any) => { - draft.objects[objectName] = { - ...draft.objects[objectName], - ...objectState, + draft.objects[credentialId] = { + ...draft.objects[credentialId], + ...(credential as object), } }), ) }, - getObject: (objectName) => { + getObject: (credentialId) => { const { objects } = get() - return objects[objectName] || initialObjectState + return objects[credentialId] || initialObjectState }, - removeObject: (objectName) => { + removeObject: (credentialId) => { set( produce((draft) => { - delete draft.objects[objectName] + delete draft.objects[credentialId] }), ) }, - searchObjects: (query, props) => { - // TODO: improve + searchObjects: ({ query, props }) => { const { objects } = get() const objectsStatesArray = Object.values(objects) - const objectsArray = objectsStatesArray.map((obj: any) => obj?.object) - const filteredObjects = objectsArray.filter((object) => { + const filteredObjects = objectsStatesArray.filter((object) => { if (!object) { return false } return matchesQuery(object, query) }) if (props?.length) { - const arrayOfArrays = filteredObjects.map((objects) => { + const arrayOfArrays = filteredObjects.map((objects: any) => { return props .filter((prop) => objects && prop in objects) .map((prop) => (objects as unknown as Record)[prop]) @@ -63,7 +59,7 @@ export const objectSlice: StateCreator = (set, get) => ({ clearObjects: () => { set( produce((draft) => { - draft.objects = DEFAULT_OBJECTS + draft.objects = {} }), ) }, diff --git a/packages/vault/src/vault/utils/get-wallet-account-info.ts b/packages/vault/src/vault/utils/get-wallet-account-info.ts index d767edf9..684c8fc7 100644 --- a/packages/vault/src/vault/utils/get-wallet-account-info.ts +++ b/packages/vault/src/vault/utils/get-wallet-account-info.ts @@ -1,5 +1,5 @@ -import type { GroupedCredentials } from "@palladxyz/key-management" -import type { Network } from "@palladxyz/pallad-core" +import type { GroupedCredentials } from "@palladco/key-management" +import type { Network } from "@palladco/pallad-core" import type { SingleCredentialState } from "../../credentials" import { NetworkError, WalletError } from "../../lib/Errors" diff --git a/packages/vault/src/vault/utils/get-wallet-transactions.ts b/packages/vault/src/vault/utils/get-wallet-transactions.ts index 6b2c737c..de25fc9f 100644 --- a/packages/vault/src/vault/utils/get-wallet-transactions.ts +++ b/packages/vault/src/vault/utils/get-wallet-transactions.ts @@ -1,4 +1,4 @@ -import type { GroupedCredentials } from "@palladxyz/key-management" +import type { GroupedCredentials } from "@palladco/key-management" import { AddressError, NetworkError, WalletError } from "../../lib/Errors" diff --git a/packages/vault/src/vault/utils/restore-wallet.ts b/packages/vault/src/vault/utils/restore-wallet.ts index adbf0f9a..0b973a90 100644 --- a/packages/vault/src/vault/utils/restore-wallet.ts +++ b/packages/vault/src/vault/utils/restore-wallet.ts @@ -1,8 +1,8 @@ import type { ChainDerivationArgs, FromBip39MnemonicWordsProps, -} from "@palladxyz/key-management" -import { createChainProvider } from "@palladxyz/providers" +} from "@palladco/key-management" +import { createChainProvider } from "@palladco/providers" import type { CredentialName, SingleCredentialState } from "../../credentials" import type { KeyAgentName, KeyAgents } from "../../keyAgent" diff --git a/packages/vault/src/vault/utils/sign.ts b/packages/vault/src/vault/utils/sign.ts index 18614f30..87d92437 100644 --- a/packages/vault/src/vault/utils/sign.ts +++ b/packages/vault/src/vault/utils/sign.ts @@ -4,7 +4,7 @@ import type { GetPassphrase, GroupedCredentials, InMemoryKeyAgent, -} from "@palladxyz/key-management" +} from "@palladco/key-management" import { WalletError } from "../../lib/Errors" diff --git a/packages/vault/src/vault/utils/sync-account-info.ts b/packages/vault/src/vault/utils/sync-account-info.ts index ce566353..6a5c358c 100644 --- a/packages/vault/src/vault/utils/sync-account-info.ts +++ b/packages/vault/src/vault/utils/sync-account-info.ts @@ -1,4 +1,4 @@ -import { type ProviderConfig, createChainProvider } from "@palladxyz/providers" +import { type ProviderConfig, createChainProvider } from "@palladco/providers" export async function syncAccountHelper( get: any, diff --git a/packages/vault/src/vault/utils/sync-transactions.ts b/packages/vault/src/vault/utils/sync-transactions.ts index bb83d040..b36ebdee 100644 --- a/packages/vault/src/vault/utils/sync-transactions.ts +++ b/packages/vault/src/vault/utils/sync-transactions.ts @@ -1,5 +1,5 @@ -import type { Tx } from "@palladxyz/pallad-core" -import { type ProviderConfig, createChainProvider } from "@palladxyz/providers" +import type { Tx } from "@palladco/pallad-core" +import { type ProviderConfig, createChainProvider } from "@palladco/providers" export async function syncTransactionHelper( get: any, diff --git a/packages/vault/src/vault/utils/sync-wallet.ts b/packages/vault/src/vault/utils/sync-wallet.ts index 2e2cf83f..ce279d6d 100644 --- a/packages/vault/src/vault/utils/sync-wallet.ts +++ b/packages/vault/src/vault/utils/sync-wallet.ts @@ -1,5 +1,5 @@ -import { createChainProvider } from "@palladxyz/providers" -import type { ProviderConfig } from "@palladxyz/providers" +import { createChainProvider } from "@palladco/providers" +import type { ProviderConfig } from "@palladco/providers" import { AddressError } from "../../lib/Errors" diff --git a/packages/vault/src/vault/vaultState.ts b/packages/vault/src/vault/vaultState.ts index fb9c4fb6..8002dbe0 100644 --- a/packages/vault/src/vault/vaultState.ts +++ b/packages/vault/src/vault/vaultState.ts @@ -4,15 +4,15 @@ import type { ChainOperationArgs, ChainSignablePayload, FromBip39MnemonicWordsProps, -} from "@palladxyz/key-management" -import type { GetPassphrase } from "@palladxyz/key-management" +} from "@palladco/key-management" +import type { GetPassphrase } from "@palladco/key-management" import type { AccountInfo, Network, SubmitTxArgs, Tx, -} from "@palladxyz/pallad-core" -import type { ProviderConfig } from "@palladxyz/providers" +} from "@palladco/pallad-core" +import type { ProviderConfig } from "@palladco/providers" import type { TransactionBody } from "@mina-js/utils" import type { diff --git a/packages/vault/src/vault/vaultStore.ts b/packages/vault/src/vault/vaultStore.ts index b244de2a..b37a1a06 100644 --- a/packages/vault/src/vault/vaultStore.ts +++ b/packages/vault/src/vault/vaultStore.ts @@ -1,5 +1,5 @@ -import { generateMnemonicWords } from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" +import { generateMnemonicWords } from "@palladco/key-management" +import { Network } from "@palladco/pallad-core" import { produce } from "immer" import { create } from "zustand" import { createJSONStorage, persist } from "zustand/middleware" diff --git a/packages/vault/test/account/accountStore.test.ts b/packages/vault/test/account/accountStore.test.ts index ba373509..cbba9b43 100644 --- a/packages/vault/test/account/accountStore.test.ts +++ b/packages/vault/test/account/accountStore.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it } from "bun:test" -import { type AccountInfo, Mina } from "@palladxyz/mina-core" +import { type AccountInfo, Mina } from "@palladco/mina-core" import { act, renderHook } from "@testing-library/react" import { initialSingleAccountState } from "../../src" diff --git a/packages/vault/test/credentials/credentialsStore.test.ts b/packages/vault/test/credentials/credentialsStore.test.ts index f52b5068..74edbdba 100644 --- a/packages/vault/test/credentials/credentialsStore.test.ts +++ b/packages/vault/test/credentials/credentialsStore.test.ts @@ -1,6 +1,6 @@ import { beforeEach, describe, expect, it } from "bun:test" -import type { GroupedCredentials } from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" +import type { GroupedCredentials } from "@palladco/key-management" +import { Network } from "@palladco/pallad-core" import { act, renderHook } from "@testing-library/react" import { diff --git a/packages/vault/test/keyAgent/keyAgentStore.test.ts b/packages/vault/test/keyAgent/keyAgentStore.test.ts index 63aea268..8b4350d0 100644 --- a/packages/vault/test/keyAgent/keyAgentStore.test.ts +++ b/packages/vault/test/keyAgent/keyAgentStore.test.ts @@ -1,15 +1,15 @@ import { afterEach, beforeEach, describe, expect, it } from "bun:test" import { utf8ToBytes } from "@noble/hashes/utils" -import { mnemonic } from "@palladxyz/common" +import { mnemonic } from "@palladco/common" import { type ChainOperationArgs, type FromBip39MnemonicWordsProps, type GroupedCredentials, type MinaDerivationArgs, generateMnemonicWords, -} from "@palladxyz/key-management" -import type { Mina } from "@palladxyz/mina-core" -import { Network } from "@palladxyz/pallad-core" +} from "@palladco/key-management" +import type { Mina } from "@palladco/mina-core" +import { Network } from "@palladco/pallad-core" import { act, renderHook } from "@testing-library/react" import { KeyAgents } from "../../src" diff --git a/packages/vault/test/objects/objectsStore.test.ts b/packages/vault/test/objects/objectsStore.test.ts deleted file mode 100644 index 3972cc41..00000000 --- a/packages/vault/test/objects/objectsStore.test.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { beforeEach, describe, expect, it } from "bun:test" -import type { GroupedCredentials } from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" -import { act, renderHook } from "@testing-library/react" - -import type { Json } from "@mina-js/utils" -import { - DEFAULT_OBJECTS, - type ObjectName, - type StoredObject, - useVault, -} from "../../src" - -describe("ObjectStore", () => { - let object: GroupedCredentials - let objectName: ObjectName - let objectState: Json - let objectStateTwo: Json - let objectTwo: object - - beforeEach(() => { - object = { - "@context": ["https://w3id.org/wallet/v1"], - id: "did:mina:B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", - type: "MinaAddress", - controller: - "did:mina:B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", - name: "Mina Account", - description: "My Mina account.", - chain: Network.Mina, - accountIndex: 0, - addressIndex: 0, - address: "B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", - encryptedPrivateKeyBytes: new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]), - } - objectTwo = { - "@context": ["https://www.w3.org/2018/credentials/v1"], - id: "http://example.edu/credentials/3732", - type: ["VerifiableCredential", "UniversityDegreeCredential"], - issuer: "University of Example", - issuanceDate: "2010-01-01T00:00:00Z", - credentialSubject: { - id: "did:mina:B62qjsV6WQwTeEWrNrRRBP6VaaLvQhwWTnFi4WP4LQjGvpfZEumXzxb", - degree: { - type: "BachelorDegree", - name: "Bachelor of Science and Arts", - }, - }, - proof: { - type: "Kimchi", - created: "2023-09-19T12:40:16Z", - proof: { - publicInput: ["0"], - publicOutput: ["1"], - maxProofsVerified: 0, - proof: "KChzdGF0ZW1...SkpKSkp", - }, - }, - } - - objectName = "credentialName" - objectState = { - objectName: objectName, - object: object as StoredObject, - } - - objectStateTwo = { - objectName: "green crocodile credential", - object: objectTwo as StoredObject, - } - const { result } = renderHook(() => useVault()) - act(() => result.current.clearObjects()) - }) - - it("should create an objects store", () => { - const { result } = renderHook(() => useVault()) - expect(result.current.objects).toEqual(DEFAULT_OBJECTS) - }) - - it("should add one object and remove one from store", () => { - let storedObject - const { result } = renderHook(() => useVault()) - act(() => { - result.current.setObject(objectState) - storedObject = result.current.getObject(objectName) - }) - expect(storedObject?.object).toEqual(object) - act(() => { - result.current.removeObject(objectName) - storedObject = result.current.getObject(objectName) - }) - // check that object is removed - expect(storedObject.object).toEqual({}) - }) - it("should add two objects and search for Mina addresses and return them as an array not as a credential object", () => { - let storedObjects: StoredObject[] | undefined - // search for first credential - const searchQuery = { - type: "MinaAddress", - chain: Network.Mina, - } - // return props - const props = ["address"] - const { result } = renderHook(() => useVault()) - act(() => { - // add first credential - result.current.setObject(objectState) - // add second credential - result.current.setObject(objectStateTwo) - storedObjects = result.current.searchObjects(searchQuery, props) - }) - expect(storedObjects).toBeDefined() - expect(storedObjects?.length).toEqual(1) - }) -}) diff --git a/packages/vault/test/wallet/walletFlow.test.ts b/packages/vault/test/wallet/walletFlow.test.ts index 08556692..f53229e2 100644 --- a/packages/vault/test/wallet/walletFlow.test.ts +++ b/packages/vault/test/wallet/walletFlow.test.ts @@ -1,17 +1,16 @@ import { beforeEach, describe, expect, it } from "bun:test" import { utf8ToBytes } from "@noble/hashes/utils" -import { mnemonic } from "@palladxyz/common" +import { mnemonic } from "@palladco/common" import type { ChainDerivationArgs, FromBip39MnemonicWordsProps, -} from "@palladxyz/key-management" -import { Network } from "@palladxyz/pallad-core" +} from "@palladco/key-management" +import { Network } from "@palladco/pallad-core" import { act, renderHook } from "@testing-library/react" import { type CredentialName, KeyAgents } from "../../src" import { useVault } from "../../src" import { DEFAULT_NETWORK } from "../../src/network-info/default" -import { EXAMPLE_CREDENTIAL } from "../../src/objects/default" const PREGENERATED_MNEMONIC = mnemonic @@ -96,15 +95,15 @@ describe.skip("WalletTest", () => { expect(accountInfo).toBeDefined() act(() => { result.current.setObject({ - objectName: "example credential", - object: EXAMPLE_CREDENTIAL, + credentialId: "0", + credential: { test: true }, }) }) - const allObjects = result.current.searchObjects( - { issuer: "University of Example" }, - [], - ) + const allObjects = result.current.searchObjects({ + query: { issuer: "University of Example" }, + props: [], + }) expect(allObjects.length).toEqual(2) // get keyAgentName const currentKeyAgentName = result.current.keyAgentName diff --git a/packages/vault/tsconfig.json b/packages/vault/tsconfig.json index 83805819..e0cdff40 100644 --- a/packages/vault/tsconfig.json +++ b/packages/vault/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@palladxyz/common/tsconfig.json", + "extends": "@palladco/common/tsconfig.json", "compilerOptions": { "target": "esnext", "module": "esnext", diff --git a/packages/vault/tsup.config.ts b/packages/vault/tsup.config.ts index 639c8868..6a7ed6fa 100644 --- a/packages/vault/tsup.config.ts +++ b/packages/vault/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json" diff --git a/packages/web-provider/README.md b/packages/web-provider/README.md index 6ae83cf2..d4763389 100644 --- a/packages/web-provider/README.md +++ b/packages/web-provider/README.md @@ -1,4 +1,4 @@ -# @palladxyz/web-extension +# @palladco/web-extension 🚧 This package is a WIP & implementation of RFC-0008/-0009 🚧 @@ -8,7 +8,7 @@ This is a typescript package that allows applications to interact with the walle ## Implementation & Testing -For implementation of this package, you should investigate the `apps/extension` folder. In there you can view the background script, the injected script, and the content script together allow Pallad to interact with applications. See the e2e tests for a good test suite of this provider's implementation. +For implementation of this package, you should investigate the `apps/extension` folder. In there you can view the background script, the injected script, and the content script together allow Pallad to interact with applications. See the e2e tests for a good test suite of this provider's implementation. ## Current Design diff --git a/packages/web-provider/package.json b/packages/web-provider/package.json index 0cd9d7e6..435de646 100644 --- a/packages/web-provider/package.json +++ b/packages/web-provider/package.json @@ -1,5 +1,5 @@ { - "name": "@palladxyz/web-provider", + "name": "@palladco/web-provider", "version": "0.0.1", "type": "module", "description": "A web-provider for Mina wallets", @@ -17,27 +17,21 @@ "cleanup": "bunx --bun rimraf node_modules dist .turbo" }, "dependencies": { - "@mina-js/klesia-sdk": "https://pkg.pr.new/palladians/mina-js/@mina-js/klesia-sdk@a51d3b4", - "@mina-js/providers": "https://pkg.pr.new/palladians/mina-js/@mina-js/providers@a51d3b4", + "@mina-js/klesia-sdk": "https://pkg.pr.new/palladians/mina-js/@mina-js/klesia-sdk@261950d", + "@mina-js/providers": "https://pkg.pr.new/palladians/mina-js/@mina-js/providers@3", "@noble/hashes": "1.4.0", - "@palladxyz/key-management": "workspace:*", - "@palladxyz/mina-core": "workspace:*", - "@palladxyz/providers": "workspace:*", - "@palladxyz/vault": "workspace:*", + "@palladco/key-management": "workspace:*", + "@palladco/mina-core": "workspace:*", + "@palladco/providers": "workspace:*", + "@palladco/vault": "workspace:*", "dayjs": "1.11.12", - "eventemitter3": "5.0.1", "mina-signer": "3.0.7", "mitt": "3.0.1", - "superjson": "2.2.1", "ts-pattern": "5.5.0", - "webext-bridge": "6.0.1", - "webextension-polyfill": "0.12.0", "zod": "3.23.8" }, "devDependencies": { - "@palladxyz/common": "workspace:*", - "@types/chrome": "0.0.269", - "@types/webextension-polyfill": "0.10.7", - "type-fest": "4.23.0" + "@palladco/common": "workspace:*", + "@types/chrome": "0.0.269" } } diff --git a/packages/web-provider/src/mina-network/index.ts b/packages/web-provider/src/mina-network/index.ts index 1ec944f0..e21c529b 100644 --- a/packages/web-provider/src/mina-network/index.ts +++ b/packages/web-provider/src/mina-network/index.ts @@ -1,2 +1,3 @@ export * from "./mina-provider" +export * from "./utils" export * as Validation from "./validation" diff --git a/packages/web-provider/src/mina-network/mina-provider.ts b/packages/web-provider/src/mina-network/mina-provider.ts index 9a72729d..e52ac182 100644 --- a/packages/web-provider/src/mina-network/mina-provider.ts +++ b/packages/web-provider/src/mina-network/mina-provider.ts @@ -12,14 +12,14 @@ import { utf8ToBytes } from "@noble/hashes/utils" import type { ChainOperationArgs, ChainSignablePayload, -} from "@palladxyz/key-management" -import type { SearchQuery } from "@palladxyz/vault" +} from "@palladco/key-management" +import type { SearchQuery, StoredObject } from "@palladco/vault" import mitt from "mitt" import { P, match } from "ts-pattern" import { showUserPrompt } from "../utils/prompts" import { createVaultService } from "../vault-service" import type { ConnectOps } from "../web-provider-types" -import { serializeField, serializeGroup } from "./utils" +import { createCredentialHash, serializeField, serializeGroup } from "./utils" export function getMinaChainId(chains: string[]) { return Number(chains[0]?.split(":")[1]) @@ -43,7 +43,7 @@ export const createMinaProvider = async (): Promise< const _emitter = mitt() const _vault = createVaultService() const unlockWallet = async () => { - const passphrase = await showUserPrompt({ + const { value: passphrase } = await showUserPrompt({ inputType: "password", metadata: { title: "Unlock your wallet", @@ -51,6 +51,7 @@ export const createMinaProvider = async (): Promise< rejectButtonLabel: "Cancel", }, }) + if (passphrase === null) throw createProviderRpcError(4100, "Unauthorized") await _vault.unlockWallet(passphrase) } @@ -105,7 +106,7 @@ export const createMinaProvider = async (): Promise< utf8ToBytes(passphrase), )) as T } catch (error) { - throw createProviderRpcError(4100, "Unauthorized") + throw createProviderRpcError(4100, "Unauthorized: signPayload") } } return { @@ -117,14 +118,14 @@ export const createMinaProvider = async (): Promise< const { context } = typedArgs const { origin } = context as Record if (!origin) { - throw createProviderRpcError(4100, "Unauthorized") + throw createProviderRpcError(4100, "Unauthorized: origin") } if (await _vault.isBlocked({ origin })) { - throw createProviderRpcError(4100, "Unauthorized") + throw createProviderRpcError(4100, "Unauthorized: isBlocked") } const initialized = await verifyInitialized() if (!initialized) { - throw createProviderRpcError(4100, "Unauthorized") + throw createProviderRpcError(4100, "Unauthorized: initialized") } const locked = await _vault.isLocked() const enabled = await _vault.getEnabled({ origin }) @@ -152,7 +153,7 @@ export const createMinaProvider = async (): Promise< if (!networkIds.includes(networkId)) { throw createProviderRpcError(4100, "Unauthorized.") } - const userConfirmed = await showUserPrompt({ + const { value: userConfirmed } = await showUserPrompt({ inputType: "confirmation", metadata: { title: "Switch to different chain.", @@ -166,7 +167,7 @@ export const createMinaProvider = async (): Promise< return networkId }) .with({ method: "mina_requestNetwork" }, async () => { - const userConfirmed = await showUserPrompt({ + const { value: userConfirmed } = await showUserPrompt({ inputType: "confirmation", metadata: { title: "Request to current Mina network information.", @@ -181,7 +182,7 @@ export const createMinaProvider = async (): Promise< .with( { method: P.union("mina_sign", "mina_signTransaction") }, async (signatureRequest) => { - const passphrase = await showUserPrompt({ + const { value: passphrase } = await showUserPrompt({ inputType: "password", metadata: { title: "Signature request", @@ -227,7 +228,7 @@ export const createMinaProvider = async (): Promise< .with( { method: P.union("mina_createNullifier", "mina_signFields") }, async (signatureRequest) => { - const passphrase = await showUserPrompt({ + const { value: passphrase } = await showUserPrompt({ inputType: "password", metadata: { title: "Signature request", @@ -261,11 +262,11 @@ export const createMinaProvider = async (): Promise< return item }, ) - const seriliasedResponse = { + const serializedResponse = { ...signedResponse, data: serializedResponseData, } - return seriliasedResponse + return serializedResponse }) .with({ method: "mina_createNullifier" }, async ({ params }) => { const [message] = params @@ -297,13 +298,58 @@ export const createMinaProvider = async (): Promise< .exhaustive() }, ) + .with( + { method: "mina_signFieldsWithPassphrase" }, + async ({ params }) => { + const [fieldsAndPassphrase] = params + if ( + !fieldsAndPassphrase || + !fieldsAndPassphrase.fields || + !fieldsAndPassphrase.fields.length || + !fieldsAndPassphrase.passphrase + ) { + throw createProviderRpcError( + 4100, + `Unauthorized. fieldsAndPassphrase: ${JSON.stringify(fieldsAndPassphrase)}`, + ) + } + const { fields, passphrase } = fieldsAndPassphrase + + const operationArgs: ChainOperationArgs = { + operation: args.method, + network: "Mina", + } + + const signedResponse = await signPayload({ + signable: { + fields: fields.map((item: any) => BigInt(item)), + }, + operationArgs, + passphrase, + }) + + const serializedResponseData = signedResponse.data.map((item) => { + if (typeof item === "bigint") { + return String(item) + } + return item + }) + + const seriliasedResponse = { + ...signedResponse, + data: serializedResponseData, + } + + return seriliasedResponse + }, + ) .with({ method: "mina_getState" }, async ({ params }) => { const [query, props] = params const credentials = await _vault.getState( query as SearchQuery, props as string[], ) - const confirmation = await showUserPrompt({ + const { value: confirmation } = await showUserPrompt({ inputType: "confirmation", metadata: { title: "Credential read request", @@ -316,25 +362,200 @@ export const createMinaProvider = async (): Promise< return credentials }) .with({ method: "mina_setState" }, async ({ params }) => { - const payload = params?.[0] - if (!payload) throw createProviderRpcError(4000, "Invalid Request") - const confirmation = await showUserPrompt({ + const [credential] = params + if (!credential) throw createProviderRpcError(4000, "Invalid Request") + const { value: confirmation } = await showUserPrompt({ inputType: "confirmation", metadata: { title: "Credential write request", - payload: JSON.stringify(payload), + payload: JSON.stringify(credential), }, }) if (!confirmation) { throw createProviderRpcError(4001, "User Rejected Request") } - await _vault.setState(payload) + const { id } = credential as { id: string } + await _vault.setState({ credentialId: id, credential }) return { success: true } }) + .with({ method: "mina_storePrivateCredential" }, async ({ params }) => { + const [credential] = params + if (!credential) throw createProviderRpcError(4000, "Invalid Request") + + const stringifiedCredential = JSON.stringify(credential) + + let credentialToStore + + try { + const credentialWitnessType = credential.witness.type + if (credentialWitnessType === "unsigned") { + const { value: userConfirmed } = await showUserPrompt({ + inputType: "confirmation", + metadata: { + title: "Store Private Credential", + payload: stringifiedCredential, + }, + }) + + if (!userConfirmed) { + throw createProviderRpcError(4001, "User Rejected Request") + } + + credentialToStore = stringifiedCredential + } else { + // prompt user to approve incoming credential and validate if approved + const { value: userConfirmed, result } = + await showUserPrompt({ + inputType: "confirmation", + contract: "validate-credential", + metadata: { + title: "Store Private Credential", + payload: stringifiedCredential, + }, + }) + + if (!userConfirmed) { + throw createProviderRpcError(4001, "User Rejected Request") + } + + if (result?.error) { + throw createProviderRpcError( + 4100, + `Credential validation failed: ${JSON.stringify(result.error)}`, + ) + } + + if (!result?.result) { + throw createProviderRpcError(4100, "Missing validation result") + } + + credentialToStore = result.result + } + + // Generate hash of the new credential + const newCredentialHash = createCredentialHash(credential) + + // Get existing credentials and check for duplicates + const existingCredentials = await _vault.getPrivateCredential() + const isDuplicate = existingCredentials.some((existing) => { + const existingHash = createCredentialHash(existing) + return existingHash === newCredentialHash + }) + + if (isDuplicate) { + throw createProviderRpcError(4100, "Credential already stored") + } + + try { + const parsedResult = JSON.parse(credentialToStore) + await _vault.storePrivateCredential(parsedResult) + return { success: parsedResult } + } catch (error: any) { + throw createProviderRpcError( + 4100, + `Failed to store private credential: ${error}`, + ) + } + } catch (error: any) { + throw createProviderRpcError( + 4100, + error.message || "Failed to validate credential", + ) + } + }) + .with({ method: "mina_requestPresentation" }, async ({ params }) => { + try { + const [request] = params + if (!request) throw createProviderRpcError(4000, "Invalid Request") + + const { presentationRequest, zkAppAccount } = request + + const verifierIdentity = + presentationRequest.type === "zk-app" ? zkAppAccount : origin + + // Ask for approval to proceed with the presentation request + const { value: userConfirmed } = await showUserPrompt({ + inputType: "confirmation", + metadata: { + title: "Presentation request", + payload: JSON.stringify({ + origin, + presentationRequest, + verifierIdentity: verifierIdentity, + }), + }, + }) + + if (!userConfirmed) { + throw createProviderRpcError(4001, "User Rejected Request") + } + + // Get stored credentials that could be used for the presentation + const storedCredentials: StoredObject[] = + await _vault.getPrivateCredential() + + // Show credential selection prompt + const { value: selectedCredentials } = await showUserPrompt( + { + inputType: "selection", + metadata: { + title: "Select credentials for presentation", + payload: JSON.stringify({ + presentationRequest, + storedCredentials, + }), + submitButtonLabel: "Continue", + rejectButtonLabel: "Cancel", + }, + }, + ) + + if (!selectedCredentials) { + throw createProviderRpcError( + 4001, + "User Rejected Credential Selection", + ) + } + + const { value: passphrase, result } = await showUserPrompt({ + inputType: "password", + contract: "presentation", + metadata: { + title: "Create presentation", + payload: JSON.stringify({ + verifierIdentity, + presentationRequest, + selectedCredentials: JSON.parse(selectedCredentials), + }), + }, + }) + + if (passphrase === null) + throw createProviderRpcError(4100, "Unauthorized.") + + if (result?.error) { + throw createProviderRpcError( + 4100, + `Presentation creation failed: ${JSON.stringify(result.error)}`, + ) + } + + if (!result?.result) { + throw createProviderRpcError(4100, "Missing presentation result") + } + + return result.result + } catch (error: any) { + throw createProviderRpcError( + 4100, + error.message || "Failed to create presentation", + ) + } + }) .with({ method: "mina_sendTransaction" }, async ({ params }) => { const [payload] = params if (!payload) throw createProviderRpcError(4000, "Invalid Request") - const passphrase = await showUserPrompt({ + const { value: passphrase } = await showUserPrompt({ inputType: "password", metadata: { title: "Send transaction request", diff --git a/packages/web-provider/src/mina-network/utils.ts b/packages/web-provider/src/mina-network/utils.ts index 28c725b6..1417ba9f 100644 --- a/packages/web-provider/src/mina-network/utils.ts +++ b/packages/web-provider/src/mina-network/utils.ts @@ -1,5 +1,7 @@ -import type { MinaSignablePayload } from "@palladxyz/key-management" -import type { BorrowedTypes } from "@palladxyz/mina-core" +import { sha256 } from "@noble/hashes/sha256" +import { utf8ToBytes } from "@noble/hashes/utils" +import type { MinaSignablePayload } from "@palladco/key-management" +import type { BorrowedTypes } from "@palladco/mina-core" export const serializeField = (field: BorrowedTypes.Field) => { if (typeof field === "bigint" || typeof field === "number") { @@ -46,3 +48,15 @@ export const serializeTransaction = (transaction: MinaSignablePayload) => { const clonedTransaction = JSON.parse(JSON.stringify(transaction)) return serializeObject(clonedTransaction) } + +export const createCredentialHash = (credential: any): string => { + // exclude metadata from hash + const { metadata: _, ...credentialWithoutMetadata } = credential + + const stableString = JSON.stringify(credentialWithoutMetadata) + const bytes = utf8ToBytes(stableString) + const hash = sha256(bytes) + return Array.from(hash) + .map((b) => b.toString(16).padStart(2, "0")) + .join("") +} diff --git a/packages/web-provider/src/utils/prompts.ts b/packages/web-provider/src/utils/prompts.ts index 107f30ea..0e23458a 100644 --- a/packages/web-provider/src/utils/prompts.ts +++ b/packages/web-provider/src/utils/prompts.ts @@ -1,4 +1,4 @@ -type InputType = "text" | "password" | "confirmation" +type InputType = "text" | "password" | "confirmation" | "selection" type Metadata = { title: string submitButtonLabel?: string @@ -6,16 +6,29 @@ type Metadata = { payload?: string } +type ContractResult = { + type?: string + result?: string + error?: any +} + +type PromptResult = { + value: T + result?: ContractResult +} + export const showUserPrompt = async ({ inputType, metadata, + contract, emitConnected = false, }: { inputType: InputType metadata: Metadata + contract?: string emitConnected?: boolean -}): Promise => { - return new Promise((resolve, reject) => { +}): Promise> => { + return new Promise>((resolve, reject) => { chrome.windows .create({ url: "prompt.html", @@ -32,11 +45,20 @@ export const showUserPrompt = async ({ return reject(new Error("4001 - User Rejected Request")) } if (inputType === "confirmation") { - if (response.userConfirmed) return resolve(true as any) + if (response.userConfirmed) { + return resolve({ + value: true as T, + result: response.result, + }) + } return reject(new Error("4001 - User Rejected Request")) } - if (response.userInput.length > 0) - return resolve(response.userInput) + if (response.userInput.length > 0) { + return resolve({ + value: response.userInput, + result: response.result, + }) + } return reject(new Error("4100 - Unauthorized")) } return reject(new Error("Wrong window context")) @@ -53,6 +75,7 @@ export const showUserPrompt = async ({ rejectButtonLabel: metadata.rejectButtonLabel, payload: metadata.payload ?? "{}", inputType, + contract, emitConnected, }, }) diff --git a/packages/web-provider/src/vault-service/types.ts b/packages/web-provider/src/vault-service/types.ts index e7c45d24..1482d579 100644 --- a/packages/web-provider/src/vault-service/types.ts +++ b/packages/web-provider/src/vault-service/types.ts @@ -2,11 +2,11 @@ import type { ChainOperationArgs, ChainSignablePayload, GetPassphrase, -} from "@palladxyz/key-management" +} from "@palladco/key-management" import type { Json, Sendable } from "@mina-js/utils" -import type { ProviderConfig } from "@palladxyz/providers" -import type { SearchQuery, StoredObject } from "@palladxyz/vault" +import type { ProviderConfig } from "@palladco/providers" +import type { SearchQuery, StoredObject } from "@palladco/vault" export interface IVaultService { getAccounts(): Promise @@ -18,7 +18,9 @@ export interface IVaultService { getBalance(): Promise getNetworkId(): Promise getNetworkIds(): Promise - setState(state: Json): Promise + setState(props: { credentialId: string; credential: Json }): Promise + storePrivateCredential(state: Json): Promise + getPrivateCredential(query?: SearchQuery): Promise getEnabled({ origin }: { origin: string }): Promise setEnabled({ origin }: { origin: string }): Promise switchNetwork( diff --git a/packages/web-provider/src/vault-service/vault-service.ts b/packages/web-provider/src/vault-service/vault-service.ts index 13ea006c..d717ea6c 100644 --- a/packages/web-provider/src/vault-service/vault-service.ts +++ b/packages/web-provider/src/vault-service/vault-service.ts @@ -1,9 +1,9 @@ import { createClient } from "@mina-js/klesia-sdk" -import type { ChainOperationArgs } from "@palladxyz/key-management" -import type { ProviderConfig } from "@palladxyz/providers" -import { securePersistence, sessionPersistence } from "@palladxyz/vault" -import { usePendingTransactionStore } from "@palladxyz/vault" -import { useVault } from "@palladxyz/vault" +import type { ChainOperationArgs } from "@palladco/key-management" +import type { ProviderConfig } from "@palladco/providers" +import { securePersistence, sessionPersistence } from "@palladco/vault" +import { usePendingTransactionStore } from "@palladco/vault" +import { useVault } from "@palladco/vault" import dayjs from "dayjs" import Client from "mina-signer" @@ -95,15 +95,38 @@ export const createVaultService = (): IVaultService => { getState: async (params, props?) => { await rehydrate() const store = useVault.getState() - if (props === undefined) { - return store.searchObjects(params) - } - return store.searchObjects(params, props) + return store.searchObjects({ query: params, props }) + }, + setState: async ({ credentialId, credential }) => { + await rehydrate() + const store = useVault.getState() + store.setObject({ credentialId, credential }) + }, + storePrivateCredential: async (credential) => { + await rehydrate() + const store = useVault.getState() + return store.setObject({ + credentialId: crypto.randomUUID(), + credential: { + ...(credential as object), + type: "private-credential", + }, + }) }, - setState: async (state) => { + getPrivateCredential: async () => { await rehydrate() const store = useVault.getState() - store.setObject(state) + const credentials = await store.searchObjects({ + query: { type: "private-credential" }, + props: [], + }) + + // Remove the type field from each credential in the results + return credentials.map((credential) => { + if (!credential) return credential + const { type, ...credentialWithoutType } = credential as any + return credentialWithoutType + }) }, getEnabled: async ({ origin }) => { const { permissions } = await chrome.storage.local.get({ diff --git a/packages/web-provider/tsconfig.json b/packages/web-provider/tsconfig.json index 7d1358d6..6fc060ac 100644 --- a/packages/web-provider/tsconfig.json +++ b/packages/web-provider/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "@palladxyz/common/tsconfig.json", + "extends": "@palladco/common/tsconfig.json", "compilerOptions": { "types": ["@types/chrome"] } diff --git a/packages/web-provider/tsup.config.ts b/packages/web-provider/tsup.config.ts index 8449a56d..3325517c 100644 --- a/packages/web-provider/tsup.config.ts +++ b/packages/web-provider/tsup.config.ts @@ -1,4 +1,4 @@ -import { baseTsupConfig } from "@palladxyz/common" +import { baseTsupConfig } from "@palladco/common" import { defineConfig } from "tsup" import packageJson from "./package.json"