diff --git a/examples/stellar-solid-receive/.env.example b/examples/stellar-solid-receive/.env.example
new file mode 100644
index 0000000..d89572f
--- /dev/null
+++ b/examples/stellar-solid-receive/.env.example
@@ -0,0 +1,2 @@
+# Optional: pre-fill the secret key input (128 hex chars / 64 bytes).
+# VITE_STELLAR_SECRET_KEY=aabbcc...
diff --git a/examples/stellar-solid-receive/index.html b/examples/stellar-solid-receive/index.html
new file mode 100644
index 0000000..bcfc26a
--- /dev/null
+++ b/examples/stellar-solid-receive/index.html
@@ -0,0 +1,12 @@
+
+
+
+
+
+ Wraith Stellar — Solid.js Receive
+
+
+
+
+
+
diff --git a/examples/stellar-solid-receive/package.json b/examples/stellar-solid-receive/package.json
new file mode 100644
index 0000000..9bd9b1c
--- /dev/null
+++ b/examples/stellar-solid-receive/package.json
@@ -0,0 +1,21 @@
+{
+ "name": "@wraith-protocol/example-stellar-solid-receive",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@wraith-protocol/sdk": "workspace:*",
+ "@wraith-protocol/sdk-solid": "workspace:*",
+ "solid-js": "^1.9.0"
+ },
+ "devDependencies": {
+ "typescript": "^5.7.0",
+ "vite": "^6.1.0",
+ "vite-plugin-solid": "^2.11.0"
+ }
+}
diff --git a/examples/stellar-solid-receive/src/App.tsx b/examples/stellar-solid-receive/src/App.tsx
new file mode 100644
index 0000000..f1a83cf
--- /dev/null
+++ b/examples/stellar-solid-receive/src/App.tsx
@@ -0,0 +1,208 @@
+import { createSignal, createMemo, Show, For } from 'solid-js';
+import { createStealthKeys, createScanner } from '@wraith-protocol/sdk-solid';
+import {
+ bytesToHex,
+ scanAnnouncements as stellarScanAnnouncements,
+ type Announcement,
+} from '@wraith-protocol/sdk/chains/stellar';
+
+// Canned announcement fixture — used in dev/demo without a live Horizon node.
+const CANNED_ANNOUNCEMENTS: Announcement[] = [];
+
+function parseHex(hex: string): Uint8Array | null {
+ const clean = hex.replace(/^0x/i, '').trim();
+ if (!/^[0-9a-fA-F]+$/.test(clean) || clean.length % 2 !== 0) return null;
+ return new Uint8Array(clean.match(/.{1,2}/g)!.map((b) => parseInt(b, 16)));
+}
+
+export default function App() {
+ const [input, setInput] = createSignal((import.meta as any).env?.VITE_STELLAR_SECRET_KEY ?? '');
+
+ // Primitives
+ const stealthKeys = createStealthKeys();
+ const scanner = createScanner();
+
+ const metaAddress = createMemo(() => stealthKeys.metaAddress());
+
+ function handleDerive() {
+ const bytes = parseHex(input());
+ if (!bytes) return;
+ if (bytes.length !== 64) return;
+
+ const k = stealthKeys.deriveKeys(bytes);
+ stealthKeys.encodeMetaAddress(k.spendingPubKey, k.viewingPubKey);
+ }
+
+ function handleScan() {
+ const k = stealthKeys.keys();
+ if (!k) return;
+
+ // Scan the canned fixture (in a real app, call scanner.scan({ chain: 'testnet' }))
+ scanner.match(CANNED_ANNOUNCEMENTS, k.viewingKey, k.spendingPubKey, k.spendingScalar);
+ }
+
+ return (
+
+ Wraith Stellar — Receive Stealth Payments (Solid.js)
+
+ Enter your 64-byte hex secret key to derive your stealth keys and meta-address. Share the
+ meta-address with senders.
+
+
+
+
+
+
+
+
+ Error: {stealthKeys.error()}
+
+
+
+
+ {(k) => (
+
+ Your Stealth Keys
+
+
+
+ {([label, val]) => (
+
+ |
+ {label}
+ |
+
+ {val}
+ |
+
+ )}
+
+
+
+
+
+ {(addr) => (
+
+
Stealth Meta-Address
+
navigator.clipboard.writeText(addr())}
+ title="Click to copy"
+ >
+ {addr()}
+
+
+ Click the meta-address to copy it. Share this with anyone who wants to send you
+ stealth payments.
+
+
+ )}
+
+
+
+
+ )}
+
+
+ 0}>
+
+ Matched Payments ({scanner.matched().length})
+
+ {(m) => (
+
+
+ Stealth Address: {m.stealthAddress}
+
+
+ View Tag: {m.viewTag}
+
+
+ )}
+
+
+
+
+
+
+ No matched payments found in the canned fixture. In production, call{' '}
+ scanner.scan({ chain: 'mainnet' }) against a live Horizon node.
+
+
+
+ );
+}
diff --git a/examples/stellar-solid-receive/src/main.tsx b/examples/stellar-solid-receive/src/main.tsx
new file mode 100644
index 0000000..d12d354
--- /dev/null
+++ b/examples/stellar-solid-receive/src/main.tsx
@@ -0,0 +1,4 @@
+import { render } from 'solid-js/web';
+import App from './App';
+
+render(() => , document.getElementById('root')!);
diff --git a/examples/stellar-solid-receive/src/vite-env.d.ts b/examples/stellar-solid-receive/src/vite-env.d.ts
new file mode 100644
index 0000000..11f02fe
--- /dev/null
+++ b/examples/stellar-solid-receive/src/vite-env.d.ts
@@ -0,0 +1 @@
+///
diff --git a/examples/stellar-solid-receive/tsconfig.json b/examples/stellar-solid-receive/tsconfig.json
new file mode 100644
index 0000000..ca08087
--- /dev/null
+++ b/examples/stellar-solid-receive/tsconfig.json
@@ -0,0 +1,15 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "strict": true,
+ "noEmit": true,
+ "skipLibCheck": true,
+ "isolatedModules": true
+ },
+ "include": ["src"]
+}
diff --git a/examples/stellar-solid-receive/vite.config.ts b/examples/stellar-solid-receive/vite.config.ts
new file mode 100644
index 0000000..da40253
--- /dev/null
+++ b/examples/stellar-solid-receive/vite.config.ts
@@ -0,0 +1,6 @@
+import { defineConfig } from 'vite';
+import solid from 'vite-plugin-solid';
+
+export default defineConfig({
+ plugins: [solid()],
+});
diff --git a/packages/sdk-solid/package.json b/packages/sdk-solid/package.json
new file mode 100644
index 0000000..a5231f6
--- /dev/null
+++ b/packages/sdk-solid/package.json
@@ -0,0 +1,40 @@
+{
+ "name": "@wraith-protocol/sdk-solid",
+ "version": "0.1.0",
+ "private": false,
+ "type": "module",
+ "exports": {
+ ".": {
+ "types": "./dist/index.d.ts",
+ "import": "./dist/index.js",
+ "require": "./dist/index.cjs"
+ }
+ },
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "build": "tsup",
+ "dev": "tsup --watch",
+ "test": "vitest run",
+ "test:watch": "vitest",
+ "typecheck": "tsc --noEmit -p tsconfig.json",
+ "clean": "rm -rf dist"
+ },
+ "dependencies": {
+ "@wraith-protocol/sdk": "workspace:*",
+ "solid-js": "^1.9.0"
+ },
+ "peerDependencies": {
+ "solid-js": "^1.9.0"
+ },
+ "devDependencies": {
+ "@solidjs/testing-library": "^0.8.10",
+ "@testing-library/jest-dom": "^6.0.0",
+ "jsdom": "^25.0.0",
+ "tsup": "^8.4.0",
+ "typescript": "^5.7.0",
+ "vite-plugin-solid": "^2.11.0",
+ "vitest": "^3.1.0"
+ }
+}
diff --git a/packages/sdk-solid/src/index.ts b/packages/sdk-solid/src/index.ts
new file mode 100644
index 0000000..2a7cfab
--- /dev/null
+++ b/packages/sdk-solid/src/index.ts
@@ -0,0 +1,5 @@
+export { createStealthKeys } from './primitives/createStealthKeys.js';
+export { createScanner } from './primitives/createScanner.js';
+export { createMetaAddress } from './primitives/createMetaAddress.js';
+export type { ChainType, AnyStealthMetaAddress } from './primitives/createMetaAddress.js';
+export { createActivity } from './primitives/createActivity.js';
diff --git a/packages/sdk-solid/src/primitives/createActivity.ts b/packages/sdk-solid/src/primitives/createActivity.ts
new file mode 100644
index 0000000..048c186
--- /dev/null
+++ b/packages/sdk-solid/src/primitives/createActivity.ts
@@ -0,0 +1,163 @@
+import { createSignal } from 'solid-js';
+import { Wraith, WraithAgent, Chain } from '@wraith-protocol/sdk';
+import type { WraithConfig, AgentConfig, AgentInfo, ChatResponse } from '@wraith-protocol/sdk';
+
+/**
+ * Solid primitive for managing Wraith agent activity (chat, balance, agent lifecycle).
+ *
+ * Mirrors sdk-react's hook contract using Solid's fine-grained signals.
+ * All reactive values are returned as getter functions following Solid conventions.
+ */
+export function createActivity(config?: WraithConfig) {
+ const [client, setClient] = createSignal(null);
+ const [agent, setAgent] = createSignal(null);
+ const [agentInfo, setAgentInfo] = createSignal(null);
+ const [agents, setAgents] = createSignal([]);
+ const [loading, setLoading] = createSignal(false);
+ const [error, setError] = createSignal(null);
+
+ function init(cfg: WraithConfig): void {
+ setClient(() => new Wraith(cfg));
+ }
+
+ if (config) {
+ init(config);
+ }
+
+ function requireClient(): Wraith {
+ const c = client();
+ if (!c) throw new Error('Wraith client not initialized');
+ return c;
+ }
+
+ function requireAgent(): WraithAgent {
+ const a = agent();
+ if (!a) throw new Error('No active agent');
+ return a;
+ }
+
+ async function createAgent(cfg: AgentConfig): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const a = await requireClient().createAgent(cfg);
+ setAgent(() => a);
+ setAgentInfo(() => a.info);
+ return a;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to create agent');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function getAgent(agentId: string): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const a = requireClient().agent(agentId);
+ setAgent(() => a);
+ setAgentInfo(() => a.info);
+ return a;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to get agent');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function getAgentByWallet(wallet: string): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const a = await requireClient().getAgentByWallet(wallet);
+ setAgent(() => a);
+ setAgentInfo(() => a.info);
+ return a;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to get agent by wallet');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function getAgentByName(name: string): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const a = await requireClient().getAgentByName(name);
+ setAgent(() => a);
+ setAgentInfo(() => a.info);
+ return a;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to get agent by name');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function listAgents(): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const list = await requireClient().listAgents();
+ setAgents(list);
+ return list;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to list agents');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function chat(message: string, conversationId?: string): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ return await requireAgent().chat(message, conversationId);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Chat failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ async function getBalance(): Promise<{ native: string; tokens: Record }> {
+ setLoading(true);
+ setError(null);
+ try {
+ return await requireAgent().getBalance();
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to get balance');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return {
+ // Reactive getters (Solid signal accessors)
+ client,
+ agent,
+ agentInfo,
+ agents,
+ loading,
+ error,
+ // Actions
+ init,
+ createAgent,
+ getAgent,
+ getAgentByWallet,
+ getAgentByName,
+ listAgents,
+ chat,
+ getBalance,
+ Chain,
+ };
+}
diff --git a/packages/sdk-solid/src/primitives/createMetaAddress.ts b/packages/sdk-solid/src/primitives/createMetaAddress.ts
new file mode 100644
index 0000000..362749b
--- /dev/null
+++ b/packages/sdk-solid/src/primitives/createMetaAddress.ts
@@ -0,0 +1,136 @@
+import { createSignal } from 'solid-js';
+import {
+ encodeStealthMetaAddress as evmEncode,
+ decodeStealthMetaAddress as evmDecode,
+ META_ADDRESS_PREFIX as EVM_PREFIX,
+} from '@wraith-protocol/sdk/chains/evm';
+import {
+ encodeStealthMetaAddress as stellarEncode,
+ decodeStealthMetaAddress as stellarDecode,
+ META_ADDRESS_PREFIX as STELLAR_PREFIX,
+} from '@wraith-protocol/sdk/chains/stellar';
+import {
+ encodeStealthMetaAddress as solanaEncode,
+ decodeStealthMetaAddress as solanaDecode,
+ META_ADDRESS_PREFIX as SOLANA_PREFIX,
+} from '@wraith-protocol/sdk/chains/solana';
+import type { HexString } from '@wraith-protocol/sdk/chains/evm';
+import type { StealthMetaAddress as EvmMetaAddress } from '@wraith-protocol/sdk/chains/evm';
+import type { StealthMetaAddress as StellarMetaAddress } from '@wraith-protocol/sdk/chains/stellar';
+
+export type ChainType = 'evm' | 'stellar' | 'solana';
+
+type AnyStealthMetaAddress = EvmMetaAddress | StellarMetaAddress;
+
+const CHAIN_PREFIXES: Record = {
+ evm: EVM_PREFIX,
+ stellar: STELLAR_PREFIX,
+ solana: SOLANA_PREFIX,
+};
+
+/**
+ * Solid primitive for encoding and decoding stealth meta-addresses across
+ * EVM, Stellar, and Solana chains.
+ *
+ * All reactive values are returned as getter functions following Solid conventions.
+ */
+export function createMetaAddress() {
+ const [encoded, setEncoded] = createSignal(null);
+ const [decoded, setDecoded] = createSignal(null);
+ const [chain, setChain] = createSignal('evm');
+ const [error, setError] = createSignal(null);
+
+ function getPrefix(chainType: ChainType): string {
+ return CHAIN_PREFIXES[chainType];
+ }
+
+ function selectChain(chainType: ChainType): void {
+ setChain(chainType);
+ }
+
+ function encode(
+ spendingPubKey: HexString | Uint8Array,
+ viewingPubKey: HexString | Uint8Array,
+ chainType?: ChainType,
+ ): string {
+ setError(null);
+ const c = chainType ?? chain();
+ try {
+ let result: string;
+ switch (c) {
+ case 'evm':
+ result = evmEncode(spendingPubKey as `0x${string}`, viewingPubKey as `0x${string}`);
+ break;
+ case 'stellar':
+ result = stellarEncode(spendingPubKey as Uint8Array, viewingPubKey as Uint8Array);
+ break;
+ case 'solana':
+ result = solanaEncode(spendingPubKey as Uint8Array, viewingPubKey as Uint8Array);
+ break;
+ default: {
+ const _exhaustive: never = c;
+ throw new Error(`Unknown chain: ${_exhaustive}`);
+ }
+ }
+ setEncoded(result);
+ setChain(c);
+ return result;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Encoding failed');
+ throw e;
+ }
+ }
+
+ function decode(address: string): AnyStealthMetaAddress {
+ setError(null);
+ try {
+ const c = detectChain(address);
+ let result: AnyStealthMetaAddress;
+ switch (c) {
+ case 'evm':
+ result = evmDecode(address);
+ break;
+ case 'stellar':
+ result = stellarDecode(address);
+ break;
+ case 'solana':
+ result = solanaDecode(address);
+ break;
+ default: {
+ const _exhaustive: never = c;
+ throw new Error(`Unknown chain: ${_exhaustive}`);
+ }
+ }
+ setDecoded(() => result);
+ setChain(c);
+ return result;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Decoding failed');
+ throw e;
+ }
+ }
+
+ function detectChain(address: string): ChainType {
+ if (address.startsWith(EVM_PREFIX)) return 'evm';
+ if (address.startsWith(STELLAR_PREFIX)) return 'stellar';
+ if (address.startsWith(SOLANA_PREFIX)) return 'solana';
+ throw new Error(`Unknown meta address prefix: ${address.slice(0, 10)}...`);
+ }
+
+ return {
+ // Reactive getters (Solid signal accessors)
+ encoded,
+ decoded,
+ chain,
+ error,
+ // Actions
+ selectChain,
+ encode,
+ decode,
+ detectChain,
+ getPrefix,
+ CHAIN_PREFIXES,
+ };
+}
+
+export type { AnyStealthMetaAddress };
diff --git a/packages/sdk-solid/src/primitives/createScanner.ts b/packages/sdk-solid/src/primitives/createScanner.ts
new file mode 100644
index 0000000..dee3722
--- /dev/null
+++ b/packages/sdk-solid/src/primitives/createScanner.ts
@@ -0,0 +1,99 @@
+import { createSignal } from 'solid-js';
+import {
+ fetchAnnouncementsStream,
+ scanAnnouncements as stellarScanAnnouncements,
+ type FetchAnnouncementsOptions,
+ type Announcement,
+ type MatchedAnnouncement,
+} from '@wraith-protocol/sdk/chains/stellar';
+
+/**
+ * Solid primitive for scanning Stellar stealth payment announcements.
+ *
+ * Handles fetch + scan lifecycle with reactive loading/error signals.
+ * All reactive values are returned as getter functions following Solid conventions.
+ */
+export function createScanner() {
+ const [announcements, setAnnouncements] = createSignal([]);
+ const [matched, setMatched] = createSignal([]);
+ const [scanning, setScanning] = createSignal(false);
+ const [error, setError] = createSignal(null);
+
+ /**
+ * Fetch raw announcements from the Stellar network using the streaming RPC.
+ * Collects all pages into a local array then updates the signal.
+ */
+ async function scan(
+ chain = 'stellar',
+ opts?: FetchAnnouncementsOptions,
+ ): Promise {
+ setScanning(true);
+ setError(null);
+ try {
+ const collected: Announcement[] = [];
+ for await (const announcement of fetchAnnouncementsStream(chain, opts)) {
+ collected.push(announcement);
+ }
+ setAnnouncements(collected);
+ return collected;
+ } catch (err) {
+ const e = err instanceof Error ? err : new Error(String(err));
+ setError(e);
+ throw e;
+ } finally {
+ setScanning(false);
+ }
+ }
+
+ /**
+ * Filter a list of announcements for ones that belong to the given keys.
+ */
+ function match(
+ announcementsList: Announcement[],
+ viewingKey: Uint8Array,
+ spendingPubKey: Uint8Array,
+ spendingScalar: bigint,
+ ): MatchedAnnouncement[] {
+ setError(null);
+ try {
+ const result = stellarScanAnnouncements(
+ announcementsList,
+ viewingKey,
+ spendingPubKey,
+ spendingScalar,
+ );
+ setMatched(() => result);
+ return result;
+ } catch (err) {
+ const e = err instanceof Error ? err : new Error(String(err));
+ setError(e);
+ throw e;
+ }
+ }
+
+ /**
+ * Fetch then match in one call.
+ */
+ async function scanAndMatch(
+ viewingKey: Uint8Array,
+ spendingPubKey: Uint8Array,
+ spendingScalar: bigint,
+ chain = 'stellar',
+ opts?: FetchAnnouncementsOptions,
+ ): Promise {
+ const list = await scan(chain, opts);
+ return match(list, viewingKey, spendingPubKey, spendingScalar);
+ }
+
+ return {
+ // Reactive getters (Solid signal accessors)
+ announcements,
+ matched,
+ scanning,
+ error,
+ // Actions
+ scan,
+ match,
+ scanAndMatch,
+ };
+}
diff --git a/packages/sdk-solid/src/primitives/createStealthKeys.ts b/packages/sdk-solid/src/primitives/createStealthKeys.ts
new file mode 100644
index 0000000..073525f
--- /dev/null
+++ b/packages/sdk-solid/src/primitives/createStealthKeys.ts
@@ -0,0 +1,193 @@
+import { createSignal } from 'solid-js';
+import {
+ deriveStealthKeys as stellarDeriveKeys,
+ generateStealthAddress as stellarGenerateAddress,
+ checkStealthAddress as stellarCheckAddress,
+ scanAnnouncements as stellarScan,
+ deriveStealthPrivateScalar,
+ encodeStealthMetaAddress,
+ decodeStealthMetaAddress,
+ fetchAnnouncementsStream,
+ type FetchAnnouncementsOptions,
+} from '@wraith-protocol/sdk/chains/stellar';
+import type {
+ StealthKeys,
+ GeneratedStealthAddress,
+ Announcement,
+ MatchedAnnouncement,
+ StealthMetaAddress,
+} from '@wraith-protocol/sdk/chains/stellar';
+
+/**
+ * Solid primitive for managing Stellar stealth keys.
+ *
+ * Uses fine-grained signals for reactive state. All reactive values are
+ * returned as getter functions following Solid conventions.
+ */
+export function createStealthKeys() {
+ const [keys, setKeys] = createSignal(null);
+ const [stealthAddress, setStealthAddress] = createSignal(null);
+ const [announcements, setAnnouncements] = createSignal([]);
+ const [matched, setMatched] = createSignal([]);
+ const [metaAddress, setMetaAddress] = createSignal(null);
+ const [loading, setLoading] = createSignal(false);
+ const [error, setError] = createSignal(null);
+
+ function deriveKeys(signature: Uint8Array): StealthKeys {
+ setLoading(true);
+ setError(null);
+ try {
+ const k = stellarDeriveKeys(signature);
+ setKeys(() => k);
+ return k;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Key derivation failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ function generateAddress(
+ spendingPubKey: Uint8Array,
+ viewingPubKey: Uint8Array,
+ ephemeralSeed?: Uint8Array,
+ ): GeneratedStealthAddress {
+ setLoading(true);
+ setError(null);
+ try {
+ const addr = stellarGenerateAddress(spendingPubKey, viewingPubKey, ephemeralSeed);
+ setStealthAddress(() => addr);
+ return addr;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Address generation failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ function checkAddress(
+ ephemeralPubKey: Uint8Array,
+ viewingKey: Uint8Array,
+ spendingPubKey: Uint8Array,
+ viewTag: number,
+ ) {
+ setLoading(true);
+ setError(null);
+ try {
+ return stellarCheckAddress(ephemeralPubKey, viewingKey, spendingPubKey, viewTag);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Address check failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ function derivePrivateScalar(
+ spendingScalar: bigint,
+ viewingKey: Uint8Array,
+ ephemeralPubKey: Uint8Array,
+ ): bigint {
+ setLoading(true);
+ setError(null);
+ try {
+ return deriveStealthPrivateScalar(spendingScalar, viewingKey, ephemeralPubKey);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Private scalar derivation failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ function encodeMetaAddress(spendingPubKey: Uint8Array, viewingPubKey: Uint8Array): string {
+ setError(null);
+ try {
+ const encoded = encodeStealthMetaAddress(spendingPubKey, viewingPubKey);
+ setMetaAddress(encoded);
+ return encoded;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Meta address encoding failed');
+ throw e;
+ }
+ }
+
+ function decodeMetaAddress(address: string): StealthMetaAddress {
+ setLoading(true);
+ setError(null);
+ try {
+ return decodeStealthMetaAddress(address);
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Meta address decoding failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ /**
+ * Fetch announcements from the Stellar network (collects the streaming pages).
+ */
+ async function fetchAnnouncements(
+ chain = 'stellar',
+ opts?: FetchAnnouncementsOptions,
+ ): Promise {
+ setLoading(true);
+ setError(null);
+ try {
+ const collected: Announcement[] = [];
+ for await (const announcement of fetchAnnouncementsStream(chain, opts)) {
+ collected.push(announcement);
+ }
+ setAnnouncements(collected);
+ return collected;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Failed to fetch announcements');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ function scanAnnouncements(
+ announcementsList: Announcement[],
+ viewingKey: Uint8Array,
+ spendingPubKey: Uint8Array,
+ spendingScalar: bigint,
+ ): MatchedAnnouncement[] {
+ setLoading(true);
+ setError(null);
+ try {
+ const result = stellarScan(announcementsList, viewingKey, spendingPubKey, spendingScalar);
+ setMatched(() => result);
+ return result;
+ } catch (e) {
+ setError(e instanceof Error ? e.message : 'Scan failed');
+ throw e;
+ } finally {
+ setLoading(false);
+ }
+ }
+
+ return {
+ // Reactive getters (Solid signal accessors)
+ keys,
+ stealthAddress,
+ announcements,
+ matched,
+ metaAddress,
+ loading,
+ error,
+ // Actions
+ deriveKeys,
+ generateAddress,
+ checkAddress,
+ derivePrivateScalar,
+ encodeMetaAddress,
+ decodeMetaAddress,
+ fetchAnnouncements,
+ scanAnnouncements,
+ };
+}
diff --git a/packages/sdk-solid/test/createActivity.test.ts b/packages/sdk-solid/test/createActivity.test.ts
new file mode 100644
index 0000000..b2c6db5
--- /dev/null
+++ b/packages/sdk-solid/test/createActivity.test.ts
@@ -0,0 +1,174 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { createActivity } from '../src/primitives/createActivity';
+
+const mockAgentInfo = vi.hoisted(() => ({
+ id: 'agent-1',
+ name: 'test-agent',
+ chains: ['stellar'],
+ addresses: { stellar: 'G...' },
+ wallet: '0x...',
+}));
+
+const mockAgent = vi.hoisted(() => ({
+ info: mockAgentInfo,
+ chat: vi.fn().mockResolvedValue({ response: 'hello' }),
+ getBalance: vi.fn().mockResolvedValue({ native: '10.5', tokens: {} }),
+}));
+
+const mockClient = vi.hoisted(() => ({
+ createAgent: vi.fn().mockResolvedValue(mockAgent),
+ agent: vi.fn().mockReturnValue(mockAgent),
+ getAgentByWallet: vi.fn().mockResolvedValue(mockAgent),
+ getAgentByName: vi.fn().mockResolvedValue(mockAgent),
+ listAgents: vi.fn().mockResolvedValue([mockAgentInfo]),
+}));
+
+vi.mock('@wraith-protocol/sdk', () => ({
+ Wraith: vi.fn().mockImplementation(() => mockClient),
+ WraithAgent: vi.fn(),
+ Chain: {
+ Stellar: 'stellar',
+ Ethereum: 'ethereum',
+ All: 'all',
+ },
+}));
+
+// Grab mocked references once (safe because vi.mock hoists before imports)
+import { Wraith as MockWraith } from '@wraith-protocol/sdk';
+
+describe('createActivity', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('exports the function', () => {
+ expect(typeof createActivity).toBe('function');
+ });
+
+ it('initialises with null reactive state', () => {
+ const primitive = createActivity();
+ expect(primitive.client()).toBeNull();
+ expect(primitive.agent()).toBeNull();
+ expect(primitive.agentInfo()).toBeNull();
+ expect(primitive.agents()).toEqual([]);
+ expect(primitive.loading()).toBe(false);
+ expect(primitive.error()).toBeNull();
+ });
+
+ it('init creates the Wraith client', () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+
+ expect(vi.mocked(MockWraith)).toHaveBeenCalledWith({ apiKey: 'test-key' });
+ expect(primitive.client()).not.toBeNull();
+ });
+
+ it('auto-inits when config is provided', () => {
+ createActivity({ apiKey: 'auto-key' });
+ expect(vi.mocked(MockWraith)).toHaveBeenCalledWith({ apiKey: 'auto-key' });
+ });
+
+ it('createAgent updates agent and agentInfo signals', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+
+ const result = await primitive.createAgent({
+ name: 'test',
+ chain: 'stellar' as any,
+ wallet: '0x...',
+ signature: '0x...',
+ });
+
+ expect(result).toBe(mockAgent);
+ expect(primitive.agent()).toBe(mockAgent);
+ expect(primitive.agentInfo()).toEqual(mockAgentInfo);
+ expect(primitive.loading()).toBe(false);
+ });
+
+ it('getAgent updates agent and agentInfo signals', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+
+ await primitive.getAgent('agent-1');
+ expect(primitive.agent()).toBe(mockAgent);
+ expect(primitive.agentInfo()).toEqual(mockAgentInfo);
+ });
+
+ it('listAgents updates agents signal', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+
+ const result = await primitive.listAgents();
+ expect(result).toEqual([mockAgentInfo]);
+ expect(primitive.agents()).toEqual([mockAgentInfo]);
+ });
+
+ it('chat returns response', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+ await primitive.createAgent({
+ name: 'test',
+ chain: 'stellar' as any,
+ wallet: '0x...',
+ signature: '0x...',
+ });
+
+ const result = await primitive.chat('hello');
+ expect(result).toEqual({ response: 'hello' });
+ });
+
+ it('getBalance returns balance', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+ await primitive.createAgent({
+ name: 'test',
+ chain: 'stellar' as any,
+ wallet: '0x...',
+ signature: '0x...',
+ });
+
+ const result = await primitive.getBalance();
+ expect(result).toEqual({ native: '10.5', tokens: {} });
+ });
+
+ it('throws when client is not initialised', async () => {
+ const primitive = createActivity();
+ await expect(
+ primitive.createAgent({
+ name: 'x',
+ chain: 'stellar' as any,
+ wallet: '0x...',
+ signature: '0x...',
+ }),
+ ).rejects.toThrow('Wraith client not initialized');
+ });
+
+ it('throws when no active agent for chat', async () => {
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+ await expect(primitive.chat('hello')).rejects.toThrow('No active agent');
+ });
+
+ it('sets error signal and loading false on failure', async () => {
+ mockClient.createAgent.mockRejectedValueOnce(new Error('create failed'));
+
+ const primitive = createActivity();
+ primitive.init({ apiKey: 'test-key' });
+
+ await expect(
+ primitive.createAgent({
+ name: 'x',
+ chain: 'stellar' as any,
+ wallet: '0x...',
+ signature: '0x...',
+ }),
+ ).rejects.toThrow();
+ expect(primitive.error()).toBe('create failed');
+ expect(primitive.loading()).toBe(false);
+ });
+
+ it('exposes Chain enum', () => {
+ const primitive = createActivity();
+ expect(primitive.Chain.Stellar).toBe('stellar');
+ });
+});
diff --git a/packages/sdk-solid/test/createMetaAddress.test.ts b/packages/sdk-solid/test/createMetaAddress.test.ts
new file mode 100644
index 0000000..8d7ed8e
--- /dev/null
+++ b/packages/sdk-solid/test/createMetaAddress.test.ts
@@ -0,0 +1,129 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { createMetaAddress } from '../src/primitives/createMetaAddress';
+
+const evmEncoded = vi.hoisted(() => 'st:eth:0x' + 'ab'.repeat(66));
+const stellarEncoded = vi.hoisted(() => 'st:xlm:' + 'cd'.repeat(64));
+const solanaEncoded = vi.hoisted(() => 'st:sol:' + 'ef'.repeat(64));
+
+vi.mock('@wraith-protocol/sdk/chains/evm', () => ({
+ encodeStealthMetaAddress: vi.fn().mockReturnValue(evmEncoded),
+ decodeStealthMetaAddress: vi.fn().mockReturnValue({
+ prefix: 'st:eth:0x',
+ spendingPubKey: '0x' + '01'.repeat(33),
+ viewingPubKey: '0x' + '02'.repeat(33),
+ }),
+ META_ADDRESS_PREFIX: 'st:eth:0x',
+}));
+
+vi.mock('@wraith-protocol/sdk/chains/stellar', () => ({
+ encodeStealthMetaAddress: vi.fn().mockReturnValue(stellarEncoded),
+ decodeStealthMetaAddress: vi.fn().mockReturnValue({
+ prefix: 'st:xlm:',
+ spendingPubKey: new Uint8Array(32),
+ viewingPubKey: new Uint8Array(32),
+ }),
+ META_ADDRESS_PREFIX: 'st:xlm:',
+}));
+
+vi.mock('@wraith-protocol/sdk/chains/solana', () => ({
+ encodeStealthMetaAddress: vi.fn().mockReturnValue(solanaEncoded),
+ decodeStealthMetaAddress: vi.fn().mockReturnValue({
+ prefix: 'st:sol:',
+ spendingPubKey: new Uint8Array(32),
+ viewingPubKey: new Uint8Array(32),
+ }),
+ META_ADDRESS_PREFIX: 'st:sol:',
+}));
+
+describe('createMetaAddress', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('exports the function', () => {
+ expect(typeof createMetaAddress).toBe('function');
+ });
+
+ it('initialises with null state and evm chain', () => {
+ const primitive = createMetaAddress();
+ expect(primitive.encoded()).toBeNull();
+ expect(primitive.decoded()).toBeNull();
+ expect(primitive.chain()).toBe('evm');
+ expect(primitive.error()).toBeNull();
+ });
+
+ it('encodes an EVM meta address', () => {
+ const primitive = createMetaAddress();
+ const result = primitive.encode('0x' + '01'.repeat(33), '0x' + '02'.repeat(33), 'evm');
+
+ expect(result).toBe(evmEncoded);
+ expect(primitive.encoded()).toBe(evmEncoded);
+ expect(primitive.chain()).toBe('evm');
+ });
+
+ it('encodes a Stellar meta address', () => {
+ const primitive = createMetaAddress();
+ const result = primitive.encode(new Uint8Array(32), new Uint8Array(32), 'stellar');
+
+ expect(result).toBe(stellarEncoded);
+ expect(primitive.chain()).toBe('stellar');
+ });
+
+ it('encodes a Solana meta address', () => {
+ const primitive = createMetaAddress();
+ const result = primitive.encode(new Uint8Array(32), new Uint8Array(32), 'solana');
+
+ expect(result).toBe(solanaEncoded);
+ expect(primitive.chain()).toBe('solana');
+ });
+
+ it('decodes an EVM meta address', () => {
+ const primitive = createMetaAddress();
+ const result = primitive.decode(evmEncoded);
+
+ expect(result.prefix).toBe('st:eth:0x');
+ expect(primitive.chain()).toBe('evm');
+ });
+
+ it('decodes a Stellar meta address', () => {
+ const primitive = createMetaAddress();
+ const result = primitive.decode(stellarEncoded);
+
+ expect(result.prefix).toBe('st:xlm:');
+ expect(primitive.chain()).toBe('stellar');
+ });
+
+ it('detects the correct chain from prefix', () => {
+ const primitive = createMetaAddress();
+ expect(primitive.detectChain(evmEncoded)).toBe('evm');
+ expect(primitive.detectChain(stellarEncoded)).toBe('stellar');
+ expect(primitive.detectChain(solanaEncoded)).toBe('solana');
+ });
+
+ it('gets the correct prefix for each chain', () => {
+ const primitive = createMetaAddress();
+ expect(primitive.getPrefix('evm')).toBe('st:eth:0x');
+ expect(primitive.getPrefix('stellar')).toBe('st:xlm:');
+ expect(primitive.getPrefix('solana')).toBe('st:sol:');
+ });
+
+ it('throws for unknown prefix', () => {
+ const primitive = createMetaAddress();
+ expect(() => primitive.detectChain('unknown:prefix:abc')).toThrow(
+ 'Unknown meta address prefix',
+ );
+ });
+
+ it('selectChain updates the chain signal', () => {
+ const primitive = createMetaAddress();
+ primitive.selectChain('stellar');
+ expect(primitive.chain()).toBe('stellar');
+ });
+
+ it('exposes CHAIN_PREFIXES constant', () => {
+ const primitive = createMetaAddress();
+ expect(primitive.CHAIN_PREFIXES.evm).toBe('st:eth:0x');
+ expect(primitive.CHAIN_PREFIXES.stellar).toBe('st:xlm:');
+ expect(primitive.CHAIN_PREFIXES.solana).toBe('st:sol:');
+ });
+});
diff --git a/packages/sdk-solid/test/createScanner.test.ts b/packages/sdk-solid/test/createScanner.test.ts
new file mode 100644
index 0000000..d3ce883
--- /dev/null
+++ b/packages/sdk-solid/test/createScanner.test.ts
@@ -0,0 +1,102 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { createScanner } from '../src/primitives/createScanner';
+
+const mockAnnouncements = vi.hoisted(() => [
+ {
+ ephemeralPubKey: new Uint8Array(32),
+ viewTag: 42,
+ stealthAddress: 'GABCDEF1234567890',
+ },
+]);
+
+const mockMatched = vi.hoisted(() => [
+ {
+ stealthAddress: 'GABCDEF1234567890',
+ ephemeralPubKey: new Uint8Array(32),
+ viewTag: 42,
+ stealthPrivateScalar: 99n,
+ stealthPubKeyBytes: new Uint8Array(32),
+ },
+]);
+
+// Async generator that yields mock announcements
+async function* mockStream() {
+ for (const a of mockAnnouncements) {
+ yield a;
+ }
+}
+
+vi.mock('@wraith-protocol/sdk/chains/stellar', () => ({
+ fetchAnnouncementsStream: vi.fn().mockImplementation(() => mockStream()),
+ scanAnnouncements: vi.fn().mockReturnValue(mockMatched),
+}));
+
+describe('createScanner', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('exports the function', () => {
+ expect(typeof createScanner).toBe('function');
+ });
+
+ it('initialises with empty reactive state', () => {
+ const primitive = createScanner();
+ expect(primitive.announcements()).toEqual([]);
+ expect(primitive.matched()).toEqual([]);
+ expect(primitive.scanning()).toBe(false);
+ expect(primitive.error()).toBeNull();
+ });
+
+ it('scan fetches announcements and updates signals', async () => {
+ const primitive = createScanner();
+ const result = await primitive.scan('testnet');
+
+ expect(result).toEqual(mockAnnouncements);
+ expect(primitive.announcements()).toEqual(mockAnnouncements);
+ expect(primitive.scanning()).toBe(false);
+ expect(primitive.error()).toBeNull();
+ });
+
+ it('match filters announcements for matching keys', () => {
+ const primitive = createScanner();
+ const result = primitive.match(
+ mockAnnouncements as any,
+ new Uint8Array(32),
+ new Uint8Array(32),
+ 1n,
+ );
+
+ expect(result).toEqual(mockMatched);
+ expect(primitive.matched()).toEqual(mockMatched);
+ });
+
+ it('scanAndMatch performs fetch then match', async () => {
+ const primitive = createScanner();
+ const result = await primitive.scanAndMatch(
+ new Uint8Array(32),
+ new Uint8Array(32),
+ 1n,
+ 'testnet',
+ );
+
+ expect(result).toEqual(mockMatched);
+ expect(primitive.announcements()).toEqual(mockAnnouncements);
+ expect(primitive.matched()).toEqual(mockMatched);
+ });
+
+ it('sets error signal when scan throws', async () => {
+ const { fetchAnnouncementsStream: mockFetch } = vi.mocked(
+ await import('@wraith-protocol/sdk/chains/stellar'),
+ );
+ mockFetch.mockImplementationOnce(async function* () {
+ throw new Error('network error');
+ });
+
+ const primitive = createScanner();
+ await expect(primitive.scan('testnet')).rejects.toThrow('network error');
+ expect(primitive.error()).toBeInstanceOf(Error);
+ expect(primitive.error()!.message).toBe('network error');
+ expect(primitive.scanning()).toBe(false);
+ });
+});
diff --git a/packages/sdk-solid/test/createStealthKeys.test.ts b/packages/sdk-solid/test/createStealthKeys.test.ts
new file mode 100644
index 0000000..945022c
--- /dev/null
+++ b/packages/sdk-solid/test/createStealthKeys.test.ts
@@ -0,0 +1,150 @@
+import { describe, it, expect, vi, beforeEach } from 'vitest';
+import { createStealthKeys } from '../src/primitives/createStealthKeys';
+
+const mockKeys = vi.hoisted(() => ({
+ spendingKey: new Uint8Array(32),
+ spendingScalar: 1n,
+ viewingKey: new Uint8Array(32),
+ viewingScalar: 2n,
+ spendingPubKey: new Uint8Array(32),
+ viewingPubKey: new Uint8Array(32),
+}));
+
+const mockAddress = vi.hoisted(() => ({
+ stealthAddress: 'GABCDEF1234567890',
+ ephemeralPubKey: new Uint8Array(32),
+ viewTag: 42,
+}));
+
+// A simple async generator that yields nothing, representing an empty stream
+async function* emptyStream() {}
+
+vi.mock('@wraith-protocol/sdk/chains/stellar', () => ({
+ deriveStealthKeys: vi.fn().mockReturnValue(mockKeys),
+ generateStealthAddress: vi.fn().mockReturnValue(mockAddress),
+ checkStealthAddress: vi.fn().mockReturnValue({
+ isMatch: true,
+ stealthAddress: 'GABCDEF1234567890',
+ hashScalar: 3n,
+ stealthPubKeyBytes: new Uint8Array(32),
+ }),
+ scanAnnouncements: vi.fn().mockReturnValue([]),
+ deriveStealthPrivateScalar: vi.fn().mockReturnValue(3n),
+ encodeStealthMetaAddress: vi.fn().mockReturnValue('st:xlm:abc...'),
+ decodeStealthMetaAddress: vi.fn().mockReturnValue({
+ prefix: 'st:xlm:',
+ spendingPubKey: new Uint8Array(32),
+ viewingPubKey: new Uint8Array(32),
+ }),
+ fetchAnnouncementsStream: vi.fn().mockImplementation(() => emptyStream()),
+}));
+
+describe('createStealthKeys', () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ });
+
+ it('exports the function', () => {
+ expect(typeof createStealthKeys).toBe('function');
+ });
+
+ it('initialises with null reactive state', () => {
+ const primitive = createStealthKeys();
+ expect(primitive.keys()).toBeNull();
+ expect(primitive.stealthAddress()).toBeNull();
+ expect(primitive.metaAddress()).toBeNull();
+ expect(primitive.loading()).toBe(false);
+ expect(primitive.error()).toBeNull();
+ expect(primitive.announcements()).toEqual([]);
+ expect(primitive.matched()).toEqual([]);
+ });
+
+ it('derives keys and updates the keys signal', () => {
+ const primitive = createStealthKeys();
+ const sig = new Uint8Array(64);
+ const result = primitive.deriveKeys(sig);
+
+ expect(result).toEqual(mockKeys);
+ expect(primitive.keys()).toEqual(mockKeys);
+ });
+
+ it('loading is false after a synchronous operation completes', () => {
+ const primitive = createStealthKeys();
+ primitive.deriveKeys(new Uint8Array(64));
+ expect(primitive.loading()).toBe(false);
+ });
+
+ it('generates stealth address and updates the stealthAddress signal', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.generateAddress(new Uint8Array(32), new Uint8Array(32));
+
+ expect(result).toEqual(mockAddress);
+ expect(primitive.stealthAddress()).toEqual(mockAddress);
+ });
+
+ it('checks a stealth address', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.checkAddress(
+ new Uint8Array(32),
+ new Uint8Array(32),
+ new Uint8Array(32),
+ 42,
+ );
+ expect(result.isMatch).toBe(true);
+ });
+
+ it('encodes meta address and updates the metaAddress signal', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.encodeMetaAddress(new Uint8Array(32), new Uint8Array(32));
+
+ expect(result).toBe('st:xlm:abc...');
+ expect(primitive.metaAddress()).toBe('st:xlm:abc...');
+ });
+
+ it('decodes meta address', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.decodeMetaAddress('st:xlm:abc...');
+
+ expect(result.prefix).toBe('st:xlm:');
+ });
+
+ it('scans announcements and updates the matched signal', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.scanAnnouncements([], new Uint8Array(32), new Uint8Array(32), 1n);
+
+ expect(Array.isArray(result)).toBe(true);
+ expect(primitive.matched()).toEqual([]);
+ });
+
+ it('derives private scalar', () => {
+ const primitive = createStealthKeys();
+ const result = primitive.derivePrivateScalar(1n, new Uint8Array(32), new Uint8Array(32));
+ expect(result).toBe(3n);
+ });
+
+ it('fetchAnnouncements collects from the stream', async () => {
+ const { fetchAnnouncementsStream: mockStream } = vi.mocked(
+ await import('@wraith-protocol/sdk/chains/stellar'),
+ );
+ // Already mocked to return an empty async generator
+ const primitive = createStealthKeys();
+ const result = await primitive.fetchAnnouncements('testnet');
+ expect(result).toEqual([]);
+ expect(primitive.announcements()).toEqual([]);
+ expect(mockStream).toHaveBeenCalledWith('testnet', undefined);
+ });
+
+ it('sets error signal when key derivation throws', async () => {
+ const { deriveStealthKeys: mockDeriveStealthKeys } = vi.mocked(
+ await import('@wraith-protocol/sdk/chains/stellar'),
+ );
+ mockDeriveStealthKeys.mockImplementationOnce(() => {
+ throw new Error('derivation error');
+ });
+
+ const primitive = createStealthKeys();
+ expect(() => primitive.deriveKeys(new Uint8Array(64))).toThrow('derivation error');
+ expect(primitive.error()).toBe('derivation error');
+ expect(primitive.loading()).toBe(false);
+ });
+});
diff --git a/packages/sdk-solid/tsconfig.json b/packages/sdk-solid/tsconfig.json
new file mode 100644
index 0000000..6ac18b7
--- /dev/null
+++ b/packages/sdk-solid/tsconfig.json
@@ -0,0 +1,20 @@
+{
+ "compilerOptions": {
+ "target": "ES2022",
+ "module": "ESNext",
+ "moduleResolution": "bundler",
+ "declaration": true,
+ "strict": true,
+ "esModuleInterop": true,
+ "skipLibCheck": true,
+ "forceConsistentCasingInFileNames": true,
+ "outDir": "dist",
+ "jsx": "preserve",
+ "jsxImportSource": "solid-js",
+ "paths": {
+ "@wraith-protocol/sdk": ["../../src"]
+ }
+ },
+ "include": ["src"],
+ "exclude": ["node_modules", "dist", "test"]
+}
diff --git a/packages/sdk-solid/tsup.config.ts b/packages/sdk-solid/tsup.config.ts
new file mode 100644
index 0000000..d238c1f
--- /dev/null
+++ b/packages/sdk-solid/tsup.config.ts
@@ -0,0 +1,13 @@
+import { defineConfig } from 'tsup';
+
+export default defineConfig({
+ entry: {
+ index: 'src/index.ts',
+ },
+ format: ['esm', 'cjs'],
+ dts: true,
+ splitting: true,
+ clean: true,
+ treeshake: true,
+ external: ['solid-js', '@wraith-protocol/sdk'],
+});
diff --git a/packages/sdk-solid/vitest.config.ts b/packages/sdk-solid/vitest.config.ts
new file mode 100644
index 0000000..7f5562b
--- /dev/null
+++ b/packages/sdk-solid/vitest.config.ts
@@ -0,0 +1,20 @@
+import { defineConfig } from 'vitest/config';
+import solidPlugin from 'vite-plugin-solid';
+import path from 'path';
+
+export default defineConfig({
+ plugins: [solidPlugin()],
+ test: {
+ environment: 'jsdom',
+ globals: true,
+ transformMode: {
+ web: [/\.[jt]sx$/],
+ },
+ },
+ resolve: {
+ alias: {
+ '@wraith-protocol/sdk': path.resolve(__dirname, '../../src'),
+ },
+ conditions: ['development', 'browser'],
+ },
+});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 9f13b47..2bf45a1 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -338,6 +338,28 @@ importers:
specifier: ^6.1.0
version: 6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ examples/stellar-solid-receive:
+ dependencies:
+ '@wraith-protocol/sdk':
+ specifier: workspace:*
+ version: link:../..
+ '@wraith-protocol/sdk-solid':
+ specifier: workspace:*
+ version: link:../../packages/sdk-solid
+ solid-js:
+ specifier: ^1.9.0
+ version: 1.9.15
+ devDependencies:
+ typescript:
+ specifier: ^5.7.0
+ version: 5.9.3
+ vite:
+ specifier: ^6.1.0
+ version: 6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ vite-plugin-solid:
+ specifier: ^2.11.0
+ version: 2.11.14(@testing-library/jest-dom@6.9.1)(solid-js@1.9.15)(vite@6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+
examples/stellar-spectre-agent:
dependencies:
'@wraith-protocol/sdk':
@@ -485,6 +507,37 @@ importers:
specifier: ^3.0.0
version: 3.2.4(@types/node@25.6.0)(jiti@2.6.1)(jsdom@24.1.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ packages/sdk-solid:
+ dependencies:
+ '@wraith-protocol/sdk':
+ specifier: workspace:*
+ version: link:../..
+ solid-js:
+ specifier: ^1.9.0
+ version: 1.9.15
+ devDependencies:
+ '@solidjs/testing-library':
+ specifier: ^0.8.10
+ version: 0.8.10(solid-js@1.9.15)
+ '@testing-library/jest-dom':
+ specifier: ^6.0.0
+ version: 6.9.1
+ jsdom:
+ specifier: ^25.0.0
+ version: 25.0.1(bufferutil@4.1.0)(utf-8-validate@6.0.6)
+ tsup:
+ specifier: ^8.4.0
+ version: 8.5.1(@microsoft/api-extractor@7.58.12(@types/node@25.6.0))(jiti@2.6.1)(postcss@8.5.16)(tsx@4.23.0)(typescript@5.9.3)(yaml@2.9.0)
+ typescript:
+ specifier: ^5.7.0
+ version: 5.9.3
+ vite-plugin-solid:
+ specifier: ^2.11.0
+ version: 2.11.14(@testing-library/jest-dom@6.9.1)(solid-js@1.9.15)(vite@7.3.2(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ vitest:
+ specifier: ^3.1.0
+ version: 3.2.4(@types/node@25.6.0)(jiti@2.6.1)(jsdom@25.0.1(bufferutil@4.1.0)(utf-8-validate@6.0.6))(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+
packages/sdk-svelte:
dependencies:
'@wraith-protocol/sdk':
@@ -635,6 +688,10 @@ packages:
resolution: {integrity: sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==}
engines: {node: '>=6.9.0'}
+ '@babel/helper-module-imports@7.18.6':
+ resolution: {integrity: sha512-0NFvs3VkuSYbFi1x2Vd6tKrywq+z/cLeYC/RJNFrIX/30Bf5aiGYbtvGXolEktzJH8o5E5KJ3tT+nkxuuZFVlA==}
+ engines: {node: '>=6.9.0'}
+
'@babel/helper-module-imports@7.29.7':
resolution: {integrity: sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==}
engines: {node: '>=6.9.0'}
@@ -2745,6 +2802,16 @@ packages:
'@solana/web3.js@1.98.4':
resolution: {integrity: sha512-vv9lfnvjUsRiq//+j5pBdXig0IQdtzA0BRZ3bXEP4KaIyF1CcaydWqgyzQgfZMNIsWNWmG+AUHwPy4AHOD6gpw==}
+ '@solidjs/testing-library@0.8.10':
+ resolution: {integrity: sha512-qdeuIerwyq7oQTIrrKvV0aL9aFeuwTd86VYD3afdq5HYEwoox1OBTJy4y8A3TFZr8oAR0nujYgCzY/8wgHGfeQ==}
+ engines: {node: '>= 14'}
+ peerDependencies:
+ '@solidjs/router': '>=0.9.0'
+ solid-js: '>=1.0.0'
+ peerDependenciesMeta:
+ '@solidjs/router':
+ optional: true
+
'@stellar/js-xdr@3.1.2':
resolution: {integrity: sha512-VVolPL5goVEIsvuGqDc5uiKxV03lzfWdvYg1KikvwheDmTBO68CKDji3bAZ/kppZrx5iTA8z3Ld5yuytcvhvOQ==}
@@ -2790,6 +2857,10 @@ packages:
'@swc/helpers@0.5.5':
resolution: {integrity: sha512-KGYxvIOXcceOAbEk4bi/dVLEK9z8sZ0uBB3Il5b1rhfClSpcX0yfRO0KmTkqR2cnQDymwLB+25ZyMzICg/cm/A==}
+ '@testing-library/dom@10.4.1':
+ resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==}
+ engines: {node: '>=18'}
+
'@testing-library/dom@9.3.4':
resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==}
engines: {node: '>=14'}
@@ -3244,6 +3315,9 @@ packages:
aria-query@5.1.3:
resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==}
+ aria-query@5.3.0:
+ resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
+
aria-query@5.3.1:
resolution: {integrity: sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==}
engines: {node: '>= 0.4'}
@@ -3329,6 +3403,11 @@ packages:
resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ babel-plugin-jsx-dom-expressions@0.40.10:
+ resolution: {integrity: sha512-lxve6Y02YiZTldB7efKpnbf1BH00XCFZNYYW235jSGsYaJNFtHrYlKV6/O+miHbjqpIr9FTe5+0no4hofAMbfA==}
+ peerDependencies:
+ '@babel/core': ^7.20.12
+
babel-plugin-module-resolver@5.0.3:
resolution: {integrity: sha512-h8h6H71ZvdLJZxZrYkaeR30BojTaV7O9GfqacY14SNj5CNB8ocL9tydNzTC0JrnNN7vY3eJhwCmkDj7tuEUaqQ==}
@@ -3389,6 +3468,15 @@ packages:
peerDependencies:
'@babel/core': ^7.0.0
+ babel-preset-solid@1.9.15:
+ resolution: {integrity: sha512-GBmg1OiPb+OwcH51XbDAKPtvrPfQW7rCJTJxcp8+yhtWwN+kqnbEJk2SgVybd+uhTxTKAvjaFyiQSr/eUZBwzg==}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ solid-js: ^1.9.15
+ peerDependenciesMeta:
+ solid-js:
+ optional: true
+
balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@@ -3957,6 +4045,10 @@ packages:
deprecated-react-native-prop-types@4.1.0:
resolution: {integrity: sha512-WfepZHmRbbdTvhcolb8aOKEvQdcmTMn5tKLbqbXmkBvjFjRVWAYqsXk/DBsV8TZxws8SdGHLuHaJrHSQUPRdfw==}
+ dequal@2.0.3:
+ resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
+ engines: {node: '>=6'}
+
destroy@1.2.0:
resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==}
engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16}
@@ -4628,6 +4720,9 @@ packages:
resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==}
engines: {node: '>=18'}
+ html-entities@2.3.3:
+ resolution: {integrity: sha512-DV5Ln36z34NNTDgnz0EWGBLZENelNAtkiFA4kyNOG2tDI6Mz1uSWiq1wAKdyjnJwyDiDO7Fa2SO1CTxPXL8VxA==}
+
http-errors@2.0.0:
resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==}
engines: {node: '>= 0.8'}
@@ -4932,6 +5027,10 @@ packages:
resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==}
engines: {node: '>= 0.4'}
+ is-what@4.1.16:
+ resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==}
+ engines: {node: '>=12.13'}
+
is-wsl@1.1.0:
resolution: {integrity: sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==}
engines: {node: '>=4'}
@@ -5368,6 +5467,10 @@ packages:
resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==}
engines: {node: '>=16.10'}
+ merge-anything@5.1.7:
+ resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==}
+ engines: {node: '>=12.13'}
+
merge-options@3.0.4:
resolution: {integrity: sha512-2Sug1+knBjkaMsMgf1ctR1Ujx+Ayku4EdJN4Z+C2+JzoeF7A3OZ9KM2GY0CpQS51NR61LTurMJrRKPhSs3ZRTQ==}
engines: {node: '>=10'}
@@ -6474,6 +6577,16 @@ packages:
resolution: {integrity: sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==}
engines: {node: '>=0.10.0'}
+ seroval-plugins@1.5.6:
+ resolution: {integrity: sha512-HXuLAX2pu/UByPpaeo/TaMfvMIi+1QqIoPJYCcAtU8QkVNwgR6MPlGuCQTErV1JwraaMbYaWVIBX7mppzGLATQ==}
+ engines: {node: '>=10'}
+ peerDependencies:
+ seroval: ^1.0
+
+ seroval@1.5.6:
+ resolution: {integrity: sha512-rVQVWjjSvlINzaQPZH5JFqsqEsIWdTxY3iJZCnTL/5gQbXIRooVZKI60tVCkOVfzcRPejboxO2t0P89dg5mQaA==}
+ engines: {node: '>=10'}
+
serve-static@1.16.3:
resolution: {integrity: sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==}
engines: {node: '>= 0.8.0'}
@@ -6580,6 +6693,14 @@ packages:
sodium-native@4.3.3:
resolution: {integrity: sha512-OnxSlN3uyY8D0EsLHpmm2HOFmKddQVvEMmsakCrXUzSd8kjjbzL413t4ZNF3n0UxSwNgwTyUvkmZHTfuCeiYSw==}
+ solid-js@1.9.15:
+ resolution: {integrity: sha512-EeiY2xfpZJqPLjXspVEKjAII4yv8NyG//NxZ3IpOFHdUNnnTyL0uJOeS9LWGvA7cFCz5y94cjFwYlmw5Luncsg==}
+
+ solid-refresh@0.6.3:
+ resolution: {integrity: sha512-F3aPsX6hVw9ttm5LYlth8Q15x6MlI/J3Dn+o3EQyRTtTxidepSTwAYdozt01/YA+7ObcciagGEyXIopGZzQtbA==}
+ peerDependencies:
+ solid-js: ^1.3
+
source-map-js@1.2.1:
resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==}
engines: {node: '>=0.10.0'}
@@ -7178,6 +7299,16 @@ packages:
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
hasBin: true
+ vite-plugin-solid@2.11.14:
+ resolution: {integrity: sha512-7ZVBt8rpoyqmlwin2kRIUveaHoF6/kulY7gsnD+qFh4nS29V4OPAnw+ojoAspXIjObiL9o1xh9a/nTuYHm02Rw==}
+ peerDependencies:
+ '@testing-library/jest-dom': ^5.16.6 || ^5.17.0 || ^6.0.0 || ^7.0.0
+ solid-js: ^1.7.2
+ vite: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0
+ peerDependenciesMeta:
+ '@testing-library/jest-dom':
+ optional: true
+
vite@5.4.21:
resolution: {integrity: sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==}
engines: {node: ^18.0.0 || >=20.0.0}
@@ -7688,6 +7819,10 @@ snapshots:
transitivePeerDependencies:
- supports-color
+ '@babel/helper-module-imports@7.18.6':
+ dependencies:
+ '@babel/types': 7.29.7
+
'@babel/helper-module-imports@7.29.7':
dependencies:
'@babel/traverse': 7.29.7
@@ -10257,6 +10392,11 @@ snapshots:
- typescript
- utf-8-validate
+ '@solidjs/testing-library@0.8.10(solid-js@1.9.15)':
+ dependencies:
+ '@testing-library/dom': 10.4.1
+ solid-js: 1.9.15
+
'@stellar/js-xdr@3.1.2': {}
'@stellar/stellar-base@13.1.0':
@@ -10347,6 +10487,17 @@ snapshots:
'@swc/counter': 0.1.3
tslib: 2.8.1
+ '@testing-library/dom@10.4.1':
+ dependencies:
+ '@babel/code-frame': 7.29.7
+ '@babel/runtime': 7.29.2
+ '@types/aria-query': 5.0.4
+ aria-query: 5.3.0
+ dom-accessibility-api: 0.5.16
+ lz-string: 1.5.0
+ picocolors: 1.1.1
+ pretty-format: 27.5.1
+
'@testing-library/dom@9.3.4':
dependencies:
'@babel/code-frame': 7.29.7
@@ -10887,6 +11038,10 @@ snapshots:
dependencies:
deep-equal: 2.2.3
+ aria-query@5.3.0:
+ dependencies:
+ dequal: 2.0.3
+
aria-query@5.3.1: {}
aria-query@5.3.2: {}
@@ -10978,6 +11133,15 @@ snapshots:
'@types/babel__core': 7.20.5
'@types/babel__traverse': 7.28.0
+ babel-plugin-jsx-dom-expressions@0.40.10(@babel/core@7.29.7):
+ dependencies:
+ '@babel/core': 7.29.7
+ '@babel/helper-module-imports': 7.18.6
+ '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.7)
+ '@babel/types': 7.29.7
+ html-entities: 2.3.3
+ parse5: 7.3.0
+
babel-plugin-module-resolver@5.0.3:
dependencies:
find-babel-config: 2.1.2
@@ -11121,6 +11285,13 @@ snapshots:
babel-plugin-jest-hoist: 29.6.3
babel-preset-current-node-syntax: 1.2.0(@babel/core@7.29.7)
+ babel-preset-solid@1.9.15(@babel/core@7.29.7)(solid-js@1.9.15):
+ dependencies:
+ '@babel/core': 7.29.7
+ babel-plugin-jsx-dom-expressions: 0.40.10(@babel/core@7.29.7)
+ optionalDependencies:
+ solid-js: 1.9.15
+
balanced-match@1.0.2: {}
balanced-match@4.0.4: {}
@@ -11702,6 +11873,8 @@ snapshots:
invariant: 2.2.4
prop-types: 15.8.1
+ dequal@2.0.3: {}
+
destroy@1.2.0: {}
detect-libc@1.0.3: {}
@@ -12624,6 +12797,8 @@ snapshots:
dependencies:
whatwg-encoding: 3.1.1
+ html-entities@2.3.3: {}
+
http-errors@2.0.0:
dependencies:
depd: 2.0.0
@@ -12906,6 +13081,8 @@ snapshots:
call-bound: 1.0.4
get-intrinsic: 1.3.0
+ is-what@4.1.16: {}
+
is-wsl@1.1.0: {}
is-wsl@2.2.0:
@@ -13408,6 +13585,10 @@ snapshots:
meow@12.1.1: {}
+ merge-anything@5.1.7:
+ dependencies:
+ is-what: 4.1.16
+
merge-options@3.0.4:
dependencies:
is-plain-obj: 2.1.0
@@ -14945,6 +15126,12 @@ snapshots:
serialize-error@2.1.0: {}
+ seroval-plugins@1.5.6(seroval@1.5.6):
+ dependencies:
+ seroval: 1.5.6
+
+ seroval@1.5.6: {}
+
serve-static@1.16.3:
dependencies:
encodeurl: 2.0.0
@@ -15075,6 +15262,21 @@ snapshots:
- bare-url
optional: true
+ solid-js@1.9.15:
+ dependencies:
+ csstype: 3.2.3
+ seroval: 1.5.6
+ seroval-plugins: 1.5.6(seroval@1.5.6)
+
+ solid-refresh@0.6.3(solid-js@1.9.15):
+ dependencies:
+ '@babel/generator': 7.29.7
+ '@babel/helper-module-imports': 7.29.7
+ '@babel/types': 7.29.7
+ solid-js: 1.9.15
+ transitivePeerDependencies:
+ - supports-color
+
source-map-js@1.2.1: {}
source-map-support@0.5.21:
@@ -15736,6 +15938,36 @@ snapshots:
- tsx
- yaml
+ vite-plugin-solid@2.11.14(@testing-library/jest-dom@6.9.1)(solid-js@1.9.15)(vite@6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)):
+ dependencies:
+ '@babel/core': 7.29.7
+ '@types/babel__core': 7.20.5
+ babel-preset-solid: 1.9.15(@babel/core@7.29.7)(solid-js@1.9.15)
+ merge-anything: 5.1.7
+ solid-js: 1.9.15
+ solid-refresh: 0.6.3(solid-js@1.9.15)
+ vite: 6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ vitefu: 1.1.3(vite@6.4.3(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ optionalDependencies:
+ '@testing-library/jest-dom': 6.9.1
+ transitivePeerDependencies:
+ - supports-color
+
+ vite-plugin-solid@2.11.14(@testing-library/jest-dom@6.9.1)(solid-js@1.9.15)(vite@7.3.2(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)):
+ dependencies:
+ '@babel/core': 7.29.7
+ '@types/babel__core': 7.20.5
+ babel-preset-solid: 1.9.15(@babel/core@7.29.7)(solid-js@1.9.15)
+ merge-anything: 5.1.7
+ solid-js: 1.9.15
+ solid-refresh: 0.6.3(solid-js@1.9.15)
+ vite: 7.3.2(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0)
+ vitefu: 1.1.3(vite@7.3.2(@types/node@25.6.0)(jiti@2.6.1)(terser@5.48.0)(tsx@4.23.0)(yaml@2.9.0))
+ optionalDependencies:
+ '@testing-library/jest-dom': 6.9.1
+ transitivePeerDependencies:
+ - supports-color
+
vite@5.4.21(@types/node@25.6.0)(terser@5.48.0):
dependencies:
esbuild: 0.21.5
@@ -15751,7 +15983,7 @@ snapshots:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
- postcss: 8.5.9
+ postcss: 8.5.16
rollup: 4.60.1
tinyglobby: 0.2.16
optionalDependencies:
@@ -15767,7 +15999,7 @@ snapshots:
esbuild: 0.25.12
fdir: 6.5.0(picomatch@4.0.4)
picomatch: 4.0.4
- postcss: 8.5.9
+ postcss: 8.5.16
rollup: 4.60.1
tinyglobby: 0.2.16
optionalDependencies: