pda-explorer-react 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.static{position:static}.mx-auto{margin-left:auto;margin-right:auto}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mt-1{margin-top:.25rem}.mt-2{margin-top:.5rem}.mt-4{margin-top:1rem}.flex{display:flex}.inline-flex{display:inline-flex}.\!h-3{height:.75rem!important}.h-12{height:3rem}.h-2{height:.5rem}.h-3{height:.75rem}.h-4{height:1rem}.h-full{height:100%}.min-h-0{min-height:0}.min-h-screen{min-height:100vh}.\!w-3{width:.75rem!important}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-3{width:.75rem}.w-4{width:1rem}.w-full{width:100%}.min-w-\[160px\]{min-width:160px}.max-w-7xl{max-width:80rem}.flex-1{flex:1 1 0%}.cursor-pointer{cursor:pointer}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem*var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.75rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem*var(--tw-space-y-reverse))}.space-y-6>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(1.5rem*(1 - var(--tw-space-y-reverse)));margin-bottom:calc(1.5rem*var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.\!rounded-lg{border-radius:.5rem!important}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-sm{border-radius:.125rem}.\!border-2{border-width:2px!important}.border{border-width:1px}.border-2{border-width:2px}.\!border-gray-700{--tw-border-opacity:1!important;border-color:rgb(55 65 81/var(--tw-border-opacity,1))!important}.border-gray-700{--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}.\!bg-gray-400{--tw-bg-opacity:1!important;background-color:rgb(156 163 175/var(--tw-bg-opacity,1))!important}.\!bg-gray-800{--tw-bg-opacity:1!important;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))!important}.bg-blue-900\/30{background-color:rgba(30,58,138,.3)}.bg-blue-900\/50{background-color:rgba(30,58,138,.5)}.bg-gray-800{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}.bg-gray-800\/50{background-color:rgba(31,41,55,.5)}.bg-gray-900{--tw-bg-opacity:1;background-color:rgb(17 24 39/var(--tw-bg-opacity,1))}.bg-green-900\/50{background-color:rgba(20,83,45,.5)}.bg-purple-900\/50{background-color:rgba(88,28,135,.5)}.p-3{padding:.75rem}.p-4{padding:1rem}.p-8{padding:2rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-4{padding-left:1rem;padding-right:1rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.pt-0\.5{padding-top:.125rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.italic{font-style:italic}.leading-relaxed{line-height:1.625}.tracking-wide{letter-spacing:.025em}.text-blue-400{--tw-text-opacity:1;color:rgb(96 165 250/var(--tw-text-opacity,1))}.text-gray-300{--tw-text-opacity:1;color:rgb(209 213 219/var(--tw-text-opacity,1))}.text-gray-400{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity,1))}.text-gray-500{--tw-text-opacity:1;color:rgb(107 114 128/var(--tw-text-opacity,1))}.text-gray-600{--tw-text-opacity:1;color:rgb(75 85 99/var(--tw-text-opacity,1))}.text-green-400{--tw-text-opacity:1;color:rgb(74 222 128/var(--tw-text-opacity,1))}.text-purple-400{--tw-text-opacity:1;color:rgb(192 132 252/var(--tw-text-opacity,1))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-white{--tw-ring-opacity:1;--tw-ring-color:rgb(255 255 255/var(--tw-ring-opacity,1))}.ring-offset-1{--tw-ring-offset-width:1px}.ring-offset-2{--tw-ring-offset-width:2px}.ring-offset-gray-900{--tw-ring-offset-color:#111827}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150,.transition-all{transition-duration:.15s}.duration-200{transition-duration:.2s}.pda-explorer{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif}.pda-explorer-node{font-family:inherit}.pda-explorer-panel::-webkit-scrollbar{width:6px}.pda-explorer-panel::-webkit-scrollbar-track{background:transparent}.pda-explorer-panel::-webkit-scrollbar-thumb{background:#4b5563;border-radius:3px}.pda-explorer-panel::-webkit-scrollbar-thumb:hover{background:#6b7280}.pda-explorer-graph .react-flow__controls button{background:#1f2937;border-color:#374151;color:#9ca3af}.pda-explorer-graph .react-flow__controls button:hover{background:#374151}.pda-explorer-graph .react-flow__controls button svg{fill:currentColor}.hover\:bg-gray-800:hover{--tw-bg-opacity:1;background-color:rgb(31 41 55/var(--tw-bg-opacity,1))}
@@ -0,0 +1,29 @@
1
+ import { Node, Edge } from '@xyflow/react';
2
+ import { PdaAccountType, SeedComponent } from './schema';
3
+
4
+ /**
5
+ * Data attached to each node in the graph
6
+ */
7
+ export interface PdaNodeData extends Record<string, unknown> {
8
+ accountType: PdaAccountType;
9
+ label: string;
10
+ }
11
+ /**
12
+ * Custom node type for React Flow
13
+ */
14
+ export type PdaNode = Node<PdaNodeData, "account">;
15
+ /**
16
+ * Edge data for relationships between PDAs
17
+ */
18
+ export interface PdaEdgeData extends Record<string, unknown> {
19
+ relationship: "parent-child" | "reference";
20
+ }
21
+ /**
22
+ * Custom edge type for React Flow
23
+ */
24
+ export type PdaEdge = Edge<PdaEdgeData>;
25
+ /**
26
+ * Seed type display configuration
27
+ */
28
+ export declare const SEED_TYPE_COLORS: Record<SeedComponent["type"], string>;
29
+ export declare const SEED_TYPE_LABELS: Record<SeedComponent["type"], string>;
@@ -0,0 +1,2 @@
1
+ export * from './schema';
2
+ export * from './graph';
@@ -0,0 +1,84 @@
1
+ /**
2
+ * PDA Schema Types
3
+ *
4
+ * These types define the schema format for describing a Solana program's
5
+ * PDA (Program Derived Address) hierarchy. Any Solana program can define
6
+ * its account model using this schema.
7
+ */
8
+ /**
9
+ * Seed component types
10
+ * - literal: A static string/bytes value (e.g., "board", "membership")
11
+ * - pubkey: A 32-byte public key
12
+ * - u8/u16/u32/u64: Unsigned integers (stored as little-endian bytes)
13
+ */
14
+ export type SeedType = "literal" | "pubkey" | "u8" | "u16" | "u32" | "u64";
15
+ /**
16
+ * A single component of a PDA seed
17
+ */
18
+ export interface SeedComponent {
19
+ /** Name of this seed component (for display) */
20
+ name: string;
21
+ /** Type of the seed value */
22
+ type: SeedType;
23
+ /** For literal seeds: the actual string value */
24
+ value?: string;
25
+ /** Human-readable description of where this value comes from */
26
+ source?: string;
27
+ }
28
+ /**
29
+ * Definition of a single PDA account type
30
+ */
31
+ export interface PdaAccountType {
32
+ /** Unique identifier for this account type */
33
+ id: string;
34
+ /** Human-readable display name */
35
+ name: string;
36
+ /** Seed components used to derive this PDA */
37
+ seeds: SeedComponent[];
38
+ /** ID of the parent account type (null for root-level accounts) */
39
+ parent: string | null;
40
+ /** IDs of child account types */
41
+ children: string[];
42
+ /** Description of what this account stores */
43
+ description: string;
44
+ /** Color for visualization (hex or Tailwind color) */
45
+ color: string;
46
+ /** Optional: Name of the TypeScript/Rust function that derives this PDA */
47
+ deriveFunctionName?: string;
48
+ /** Optional: Additional metadata */
49
+ metadata?: Record<string, unknown>;
50
+ }
51
+ /**
52
+ * Complete PDA schema for a Solana program
53
+ */
54
+ export interface PdaSchema {
55
+ /** Name of the program */
56
+ programName: string;
57
+ /** Program ID (base58 encoded) */
58
+ programId?: string;
59
+ /** Description of the program */
60
+ description?: string;
61
+ /** Account type definitions keyed by ID */
62
+ accounts: Record<string, PdaAccountType>;
63
+ }
64
+ /**
65
+ * Helper: Get all root-level accounts (no parent)
66
+ */
67
+ export declare function getRootAccounts(schema: PdaSchema): PdaAccountType[];
68
+ /**
69
+ * Helper: Get children of a specific account type
70
+ */
71
+ export declare function getChildren(schema: PdaSchema, accountId: string): PdaAccountType[];
72
+ /**
73
+ * Helper: Get the parent of a specific account type
74
+ */
75
+ export declare function getParent(schema: PdaSchema, accountId: string): PdaAccountType | null;
76
+ /**
77
+ * Helper: Format seed pattern as display string
78
+ * Example: ["board", pubkey, u64_le]
79
+ */
80
+ export declare function formatSeedPattern(account: PdaAccountType): string;
81
+ /**
82
+ * Helper: Validate a PDA schema
83
+ */
84
+ export declare function validateSchema(schema: PdaSchema): string[];
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "pda-explorer-react",
3
+ "version": "0.1.0",
4
+ "description": "Interactive visualization tool for Solana Program Derived Address (PDA) hierarchies",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.js",
12
+ "require": "./dist/index.cjs",
13
+ "types": "./dist/index.d.ts"
14
+ },
15
+ "./styles.css": "./dist/styles.css"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "tsc && vite build && npm run build:css",
23
+ "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify",
24
+ "preview": "vite preview",
25
+ "lint": "eslint src --ext ts,tsx",
26
+ "prepublishOnly": "npm run build"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">=17.0.0",
30
+ "react-dom": ">=17.0.0"
31
+ },
32
+ "dependencies": {
33
+ "@xyflow/react": "^12.0.0",
34
+ "dagre": "^0.8.5"
35
+ },
36
+ "devDependencies": {
37
+ "@types/dagre": "^0.7.52",
38
+ "@types/react": "^18.2.0",
39
+ "@types/react-dom": "^18.2.0",
40
+ "@vitejs/plugin-react": "^4.2.0",
41
+ "autoprefixer": "^10.4.17",
42
+ "postcss": "^8.4.35",
43
+ "react": "^18.2.0",
44
+ "react-dom": "^18.2.0",
45
+ "tailwindcss": "^3.4.1",
46
+ "typescript": "^5.3.0",
47
+ "vite": "^5.0.0",
48
+ "vite-plugin-dts": "^3.7.0"
49
+ },
50
+ "repository": {
51
+ "type": "git",
52
+ "url": "https://github.com/gzakhar/pda-explorer.git"
53
+ },
54
+ "keywords": [
55
+ "solana",
56
+ "pda",
57
+ "program-derived-address",
58
+ "visualization",
59
+ "react",
60
+ "developer-tools"
61
+ ],
62
+ "author": "George Zakharov",
63
+ "license": "MIT"
64
+ }