From cfd87d0a5b1bfb84c2b281a41f65de3c5870daf1 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Thu, 2 Oct 2025 01:02:06 +0530 Subject: [PATCH 01/10] add initial solana methods --- packages/vault-sdk/package.json | 128 +-- packages/vault-sdk/src/exports/thirdweb.ts | 8 + packages/vault-sdk/src/sdk.ts | 992 ++++++++++++--------- packages/vault-sdk/src/types.ts | 760 +++++++++------- packages/vault-sdk/test-solana.ts | 382 ++++++++ pnpm-lock.yaml | 478 +++++++++- 6 files changed, 1896 insertions(+), 852 deletions(-) create mode 100644 packages/vault-sdk/test-solana.ts diff --git a/packages/vault-sdk/package.json b/packages/vault-sdk/package.json index 64a4d1b2d6b..918bfcac4ec 100644 --- a/packages/vault-sdk/package.json +++ b/packages/vault-sdk/package.json @@ -1,63 +1,69 @@ { - "author": "thirdweb eng ", - "bugs": { - "url": "https://github.com/thirdweb-dev/js/issues" - }, - "dependencies": { - "@noble/ciphers": "^1.2.1", - "@noble/curves": "1.8.2", - "@noble/hashes": "1.7.2", - "abitype": "1.0.8", - "jose": "6.0.11" - }, - "devDependencies": { - "@biomejs/biome": "2.0.6", - "rimraf": "6.0.1" - }, - "engines": { - "node": ">=18" - }, - "exports": { - ".": { - "types": "./dist/types/exports/thirdweb.d.ts", - "import": "./dist/esm/exports/thirdweb.js", - "default": "./dist/cjs/exports/thirdweb.js" - }, - "./package.json": "./package.json" - }, - "files": [ - "dist/*", - "src/*" - ], - "license": "Apache-2.0", - "main": "./dist/cjs/exports/thirdweb.js", - "module": "./dist/esm/exports/thirdweb.js", - "name": "@thirdweb-dev/vault-sdk", - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/thirdweb-dev/js.git#main" - }, - "scripts": { - "build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types", - "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/cjs --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json", - "build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json", - "build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap", - "clean": "rimraf dist", - "dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch", - "fix": "biome check ./src --fix", - "format": "biome format ./src --write", - "lint": "biome check ./src" - }, - "type": "module", - "types": "./dist/types/exports/thirdweb.d.ts", - "typings": "./dist/types/exports/thirdweb.d.ts", - "version": "0.0.3" + "author": "thirdweb eng ", + "bugs": { + "url": "https://github.com/thirdweb-dev/js/issues" + }, + "dependencies": { + "@noble/ciphers": "^1.2.1", + "@noble/curves": "1.8.2", + "@noble/hashes": "1.7.2", + "@solana/addresses": "^3.0.0", + "@solana/keys": "^3.0.0", + "@solana/transactions": "^3.0.0", + "@solana/rpc": "^3.0.0", + "abitype": "1.0.8", + "jose": "6.0.11" + }, + "devDependencies": { + "@biomejs/biome": "2.0.6", + "tsx": "^4.0.0", + "rimraf": "6.0.1" + }, + "engines": { + "node": ">=18" + }, + "exports": { + ".": { + "types": "./dist/types/exports/thirdweb.d.ts", + "import": "./dist/esm/exports/thirdweb.js", + "default": "./dist/cjs/exports/thirdweb.js" + }, + "./package.json": "./package.json" + }, + "files": [ + "dist/*", + "src/*" + ], + "license": "Apache-2.0", + "main": "./dist/cjs/exports/thirdweb.js", + "module": "./dist/esm/exports/thirdweb.js", + "name": "@thirdweb-dev/vault-sdk", + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/thirdweb-dev/js.git#main" + }, + "scripts": { + "build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types", + "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/cjs --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json", + "build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json", + "build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap", + "clean": "rimraf dist", + "test:solana": "tsx test-solana.ts", + "dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch", + "fix": "biome check ./src --fix", + "format": "biome format ./src --write", + "lint": "biome check ./src" + }, + "type": "module", + "types": "./dist/types/exports/thirdweb.d.ts", + "typings": "./dist/types/exports/thirdweb.d.ts", + "version": "0.0.3" } diff --git a/packages/vault-sdk/src/exports/thirdweb.ts b/packages/vault-sdk/src/exports/thirdweb.ts index 51059bdc5a1..687441a9be9 100644 --- a/packages/vault-sdk/src/exports/thirdweb.ts +++ b/packages/vault-sdk/src/exports/thirdweb.ts @@ -3,15 +3,19 @@ export { createEoa, createServiceAccount, createSignedAccessToken, + createSolanaAccount, createVaultClient, getServiceAccount, listAccessTokens, listEoas, + listSolanaAccounts, ping, revokeAccessToken, rotateServiceAccount, signAuthorization, signMessage, + signSolanaMessage, + signSolanaTransaction, signStructuredMessage, signTransaction, signTypedData, @@ -31,6 +35,7 @@ export type { CreateAccessTokenPayload, CreateEoaPayload, CreateServiceAccountPayload, + CreateSolanaAccountPayload, EncryptedPayload, GenericPayload, GetAccessTokensData, @@ -38,6 +43,7 @@ export type { GetServiceAccountPayload, ListAccessTokensPayload, ListEoaPayload, + ListSolanaAccountsPayload, Payload, PingPayload, PolicyComponent, @@ -49,6 +55,8 @@ export type { SignAuthorizationRules, SignedAuthorization, SignMessagePayload, + SignSolanaMessagePayload, + SignSolanaTransactionPayload, SignStructuredMessageData, SignStructuredMessageOptions, SignStructuredMessagePayload, diff --git a/packages/vault-sdk/src/sdk.ts b/packages/vault-sdk/src/sdk.ts index 4ddeef31548..563fb8c1534 100644 --- a/packages/vault-sdk/src/sdk.ts +++ b/packages/vault-sdk/src/sdk.ts @@ -6,461 +6,567 @@ import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils"; import type { TypedData } from "abitype"; import * as jose from "jose"; +// Base58 encoding for Solana public keys +const BASE58_ALPHABET = + "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + +function base58Encode(bytes: number[] | Uint8Array): string { + const byteArray = Array.isArray(bytes) ? new Uint8Array(bytes) : bytes; + + if (byteArray.length === 0) return ""; + + // Convert to big integer + let num = 0n; + for (const byte of byteArray) { + num = num * 256n + BigInt(byte); + } + + // Convert to base58 + let result = ""; + while (num > 0n) { + const remainder = Number(num % 58n); + result = BASE58_ALPHABET[remainder] + result; + num = num / 58n; + } + + // Add leading zeros + for (const byte of byteArray) { + if (byte === 0) { + result = BASE58_ALPHABET[0] + result; + } else { + break; + } + } + + return result; +} + +// Helper function to process Solana account data +function _processSolanaAccountData(accountData: any): any { + if (!accountData) return accountData; + + // If we have a pubkey byte array, convert it to base58 string + if (accountData.pubkey && Array.isArray(accountData.pubkey)) { + accountData.publicKey = base58Encode(accountData.pubkey); + accountData.address = accountData.publicKey; // Use the same value for address + } + + return accountData; +} + import type { - CheckedSignTypedDataPayload, - CreateAccessTokenPayload, - CreateEoaPayload, - CreateServiceAccountPayload, - EncryptedPayload, - GetServiceAccountPayload, - ListAccessTokensPayload, - ListEoaPayload, - Payload, - PingPayload, - PolicyComponent, - Prettify, - RevokeAccessTokenPayload, - RotateServiceAccountPayload, - SignAuthorizationPayload, - SignMessagePayload, - SignStructuredMessagePayload, - SignTransactionPayload, - UnencryptedErrorResponse, + CheckedSignTypedDataPayload, + CreateAccessTokenPayload, + CreateEoaPayload, + CreateServiceAccountPayload, + CreateSolanaAccountPayload, + EncryptedPayload, + GetServiceAccountPayload, + ListAccessTokensPayload, + ListEoaPayload, + ListSolanaAccountsPayload, + Payload, + PingPayload, + PolicyComponent, + Prettify, + RevokeAccessTokenPayload, + RotateServiceAccountPayload, + SignAuthorizationPayload, + SignMessagePayload, + SignSolanaMessagePayload, + SignSolanaTransactionPayload, + SignStructuredMessagePayload, + SignTransactionPayload, + UnencryptedErrorResponse, } from "./types.js"; function encryptForEnclave( - payload: Payload["input"], - enclavePublicKey: Uint8Array, + payload: Payload["input"], + enclavePublicKey: Uint8Array, ): { encryptedPayload: EncryptedPayload; ephemeralPrivateKey: Uint8Array } { - const ephemeralPrivateKey = randomBytes(32); - // Generate ephemeral keypair - const ephemeralPublicKey = x25519.getPublicKey(ephemeralPrivateKey); - - // Derive shared secret using X25519 - const sharedSecret = x25519.getSharedSecret( - ephemeralPrivateKey, - enclavePublicKey, - ); - - // Key derivation - const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); - - // Convert message to bytes if it's not already - const messageBytes = - typeof payload === "string" - ? new TextEncoder().encode(payload) - : new TextEncoder().encode(JSON.stringify(payload)); - - // XChaCha20-Poly1305 encryption - const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 - const cipher = xchacha20poly1305(encryptionKey, nonce); - const ciphertext = cipher.encrypt(messageBytes); - - // Format the encrypted package - return { - encryptedPayload: { - ciphertext: bytesToHex(ciphertext), - ephemeralPublicKey: bytesToHex(ephemeralPublicKey), - nonce: bytesToHex(nonce), - }, - ephemeralPrivateKey: ephemeralPrivateKey, - }; + const ephemeralPrivateKey = randomBytes(32); + // Generate ephemeral keypair + const ephemeralPublicKey = x25519.getPublicKey(ephemeralPrivateKey); + + // Derive shared secret using X25519 + const sharedSecret = x25519.getSharedSecret( + ephemeralPrivateKey, + enclavePublicKey, + ); + + // Key derivation + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Convert message to bytes if it's not already + const messageBytes = + typeof payload === "string" + ? new TextEncoder().encode(payload) + : new TextEncoder().encode(JSON.stringify(payload)); + + // XChaCha20-Poly1305 encryption + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const ciphertext = cipher.encrypt(messageBytes); + + // Format the encrypted package + return { + encryptedPayload: { + ciphertext: bytesToHex(ciphertext), + ephemeralPublicKey: bytesToHex(ephemeralPublicKey), + nonce: bytesToHex(nonce), + }, + ephemeralPrivateKey: ephemeralPrivateKey, + }; } function isErrorResponse( - response: UnencryptedErrorResponse | EncryptedPayload, + response: UnencryptedErrorResponse | EncryptedPayload, ): response is UnencryptedErrorResponse { - return (response as UnencryptedErrorResponse).error !== undefined; + return (response as UnencryptedErrorResponse).error !== undefined; } function decryptFromEnclave( - encryptedPackage: EncryptedPayload, - ephemeralPrivateKey: Uint8Array, + encryptedPackage: EncryptedPayload, + ephemeralPrivateKey: Uint8Array, ) { - const { ephemeralPublicKey, nonce, ciphertext } = encryptedPackage; - - // Convert hex strings back to bytes - const pubKey = hexToBytes(ephemeralPublicKey); - const nonceBytes = hexToBytes(nonce); - const ciphertextBytes = hexToBytes(ciphertext); - - // Derive the same shared secret (from the enclave's ephemeral public key) - const sharedSecret = x25519.getSharedSecret(ephemeralPrivateKey, pubKey); - // Derive the same encryption key - const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); - - // Decrypt the ciphertext - const cipher = xchacha20poly1305(encryptionKey, nonceBytes); - const decrypted = cipher.decrypt(ciphertextBytes); - - // Convert bytes back to string and parse JSON if needed - const decryptedText = new TextDecoder().decode(decrypted); - try { - return JSON.parse(decryptedText); - } catch { - return decryptedText; - } + const { ephemeralPublicKey, nonce, ciphertext } = encryptedPackage; + + // Convert hex strings back to bytes + const pubKey = hexToBytes(ephemeralPublicKey); + const nonceBytes = hexToBytes(nonce); + const ciphertextBytes = hexToBytes(ciphertext); + + // Derive the same shared secret (from the enclave's ephemeral public key) + const sharedSecret = x25519.getSharedSecret(ephemeralPrivateKey, pubKey); + // Derive the same encryption key + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Decrypt the ciphertext + const cipher = xchacha20poly1305(encryptionKey, nonceBytes); + const decrypted = cipher.decrypt(ciphertextBytes); + + // Convert bytes back to string and parse JSON if needed + const decryptedText = new TextDecoder().decode(decrypted); + try { + return JSON.parse(decryptedText); + } catch { + return decryptedText; + } } export type VaultClient = { - baseUrl: string; - publicKey: Uint8Array; - headers: Record; + baseUrl: string; + publicKey: Uint8Array; + headers: Record; }; export async function createVaultClient(clientOptions?: { - baseUrl?: string; - secretKey?: string; + baseUrl?: string; + secretKey?: string; }): Promise { - const baseUrl = clientOptions?.baseUrl ?? "https://engine.thirdweb.com"; - // Construct the full URL for the fetch call - const url = new URL("api/v1/enclave", baseUrl).toString(); - - type IntrospectionResponse = { - publicKey: string; - }; - - const headers = { - // Indicate we accept JSON responses - Accept: "application/json", - ...(clientOptions?.secretKey - ? { "x-secret-key": clientOptions?.secretKey } - : {}), - }; - - try { - const response = await fetch(url, { - headers, - method: "GET", - }); - - // fetch doesn't throw on HTTP errors (like 4xx, 5xx) by default. - // Check if the request was successful (status in the range 200-299). - if (!response.ok) { - // You might want more sophisticated error handling here, - // potentially trying to parse an error message from the response body. - throw new Error( - `Failed to fetch enclave public key: ${response.status} ${response.statusText}`, - ); - } - - // Parse the JSON response body - const data = (await response.json()) as IntrospectionResponse; - - if (!data.publicKey) { - throw new Error("Invalid response format: publicKey missing"); - } - - const publicKeyBytes = hexToBytes(data.publicKey); - - return { - baseUrl, // Store baseUrl - headers, - publicKey: publicKeyBytes, - }; - } catch (error) { - // Handle network errors or JSON parsing errors - throw new Error(`Failed to fetch enclave public key: ${error}`); // Re-throw or handle as appropriate for your application - } + const baseUrl = clientOptions?.baseUrl ?? "https://engine.thirdweb.com"; + // Construct the full URL for the fetch call + const url = new URL("api/v1/enclave", baseUrl).toString(); + + type IntrospectionResponse = { + publicKey: string; + }; + + const headers = { + // Indicate we accept JSON responses + Accept: "application/json", + ...(clientOptions?.secretKey + ? { "x-secret-key": clientOptions?.secretKey } + : {}), + }; + + try { + const response = await fetch(url, { + headers, + method: "GET", + }); + + // fetch doesn't throw on HTTP errors (like 4xx, 5xx) by default. + // Check if the request was successful (status in the range 200-299). + if (!response.ok) { + // You might want more sophisticated error handling here, + // potentially trying to parse an error message from the response body. + throw new Error( + `Failed to fetch enclave public key: ${response.status} ${response.statusText}`, + ); + } + + // Parse the JSON response body + const data = (await response.json()) as IntrospectionResponse; + + if (!data.publicKey) { + throw new Error("Invalid response format: publicKey missing"); + } + + const publicKeyBytes = hexToBytes(data.publicKey); + + return { + baseUrl, // Store baseUrl + headers, + publicKey: publicKeyBytes, + }; + } catch (error) { + // Handle network errors or JSON parsing errors + throw new Error(`Failed to fetch enclave public key: ${error}`); // Re-throw or handle as appropriate for your application + } } // ========== Main API function ========== type SendRequestParams

= { - request: P["input"]; - client: VaultClient; + request: P["input"]; + client: VaultClient; }; async function sendRequest

({ - request, - client, + request, + client, }: SendRequestParams

): Promise> { - const { encryptedPayload, ephemeralPrivateKey } = encryptForEnclave( - request, - client.publicKey, - ); - - // Construct the full URL using the client's baseUrl - const url = new URL("api/v1/enclave", client.baseUrl).toString(); - - try { - const response = await fetch(url, { - // Stringify the JSON payload for the request body - body: JSON.stringify(encryptedPayload), - headers: { - ...client.headers, - Accept: "application/json", - "Content-Type": "application/json", // Good practice to specify accept header - }, - method: "POST", - }); - - // IMPORTANT: Replicate ky's throwHttpErrors: false behavior. - // We proceed to parse the body regardless of response.ok status, - // as the body itself might contain the structured error (UnencryptedErrorResponse) - // or the encrypted success payload. - - let responseData: EncryptedPayload | UnencryptedErrorResponse; - try { - responseData = await response.json(); - } catch (parseError) { - // If JSON parsing fails (e.g., 500 error with HTML body), - // construct a generic error response. - return { - data: null, - error: { - code: "FETCH_PARSE_ERROR", - message: `Failed to parse response: ${ - response.status - } ${response.statusText}. ${ - parseError instanceof Error - ? parseError.message - : String(parseError) - }`, - }, - success: false, - } as Prettify; // Cast needed because error isn't strictly EncryptedError | UnencryptedError - } - - // Now check if the *parsed* response indicates an error - if (isErrorResponse(responseData)) { - console.error("🚨 Error response from enclave:", responseData); - return { - data: null, - error: responseData.error, - success: false, // Use the error from the response body - } as Prettify; - } - - // If it's not an error response, it must be the EncryptedPayload - const decryptedResponse = decryptFromEnclave( - responseData, // No need for 'as EncryptedPayload' if isErrorResponse is accurate - ephemeralPrivateKey, - ); - - // The decrypted response should match the expected success structure P["output"] - // which includes { success: true, data: ..., error: null } - return decryptedResponse as Prettify; - } catch (error) { - // Catch network errors during the fetch itself - return { - data: null, - error: { - code: "FETCH_NETWORK_ERROR", - message: - error instanceof Error ? error.message : "Unknown network error", - }, - success: false, - } as Prettify; // Cast needed - } + const { encryptedPayload, ephemeralPrivateKey } = encryptForEnclave( + request, + client.publicKey, + ); + + // Construct the full URL using the client's baseUrl + const url = new URL("api/v1/enclave", client.baseUrl).toString(); + + try { + const response = await fetch(url, { + // Stringify the JSON payload for the request body + body: JSON.stringify(encryptedPayload), + headers: { + ...client.headers, + Accept: "application/json", + "Content-Type": "application/json", // Good practice to specify accept header + }, + method: "POST", + }); + + // IMPORTANT: Replicate ky's throwHttpErrors: false behavior. + // We proceed to parse the body regardless of response.ok status, + // as the body itself might contain the structured error (UnencryptedErrorResponse) + // or the encrypted success payload. + + let responseData: EncryptedPayload | UnencryptedErrorResponse; + try { + responseData = await response.json(); + } catch (parseError) { + // If JSON parsing fails (e.g., 500 error with HTML body), + // construct a generic error response. + return { + data: null, + error: { + code: "FETCH_PARSE_ERROR", + message: `Failed to parse response: ${ + response.status + } ${response.statusText}. ${ + parseError instanceof Error + ? parseError.message + : String(parseError) + }`, + }, + success: false, + } as Prettify; // Cast needed because error isn't strictly EncryptedError | UnencryptedError + } + + // Now check if the *parsed* response indicates an error + if (isErrorResponse(responseData)) { + console.error("🚨 Error response from enclave:", responseData); + return { + data: null, + error: responseData.error, + success: false, // Use the error from the response body + } as Prettify; + } + + // If it's not an error response, it must be the EncryptedPayload + const decryptedResponse = decryptFromEnclave( + responseData, // No need for 'as EncryptedPayload' if isErrorResponse is accurate + ephemeralPrivateKey, + ); + + // The decrypted response should match the expected success structure P["output"] + // which includes { success: true, data: ..., error: null } + return decryptedResponse as Prettify; + } catch (error) { + // Catch network errors during the fetch itself + return { + data: null, + error: { + code: "FETCH_NETWORK_ERROR", + message: + error instanceof Error ? error.message : "Unknown network error", + }, + success: false, + } as Prettify; // Cast needed + } } // ========== Generic Helper Params ========== type PayloadParams

= { - request: Prettify>; - client: VaultClient; + request: Prettify>; + client: VaultClient; }; // ========== Helper functions ========== export function ping({ client, request: options }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "ping", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "ping", + ...options, + }, + }); } export function createServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:create", + ...options, + }, + }); } export function getServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:get", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:get", + ...options, + }, + }); } export function rotateServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:rotate", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:rotate", + ...options, + }, + }); } export function createEoa({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:create", + ...options, + }, + }); } export function listEoas({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:list", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:list", + ...options, + }, + }); } export function signTransaction({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signTransaction", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signTransaction", + ...options, + }, + }); } export function signMessage({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signMessage", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signMessage", + ...options, + }, + }); } export function createAccessToken({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:create", + ...options, + }, + }); } export function signTypedData< - Types extends TypedData, - PrimaryType extends keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types, >({ - client, - request: options, + client, + request: options, }: PayloadParams>) { - return sendRequest>({ - client, - request: { - auth: options.auth, - operation: "eoa:signTypedData", - options: { - from: options.options.from, - typedData: options.options.typedData, - }, - }, - }); + return sendRequest>({ + client, + request: { + auth: options.auth, + operation: "eoa:signTypedData", + options: { + from: options.options.from, + typedData: options.options.typedData, + }, + }, + }); } export function revokeAccessToken({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:revoke", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:revoke", + ...options, + }, + }); } export function signAuthorization({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signAuthorization", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signAuthorization", + ...options, + }, + }); } export function signStructuredMessage({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signStructuredMessage", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signStructuredMessage", + ...options, + }, + }); } export function listAccessTokens({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:list", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:list", + ...options, + }, + }); +} + +// ========== Solana Functions ========== + +export function createSolanaAccount({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + client, + request: { + operation: "solana:create", + ...options, + }, + }); +} + +export function listSolanaAccounts({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + client, + request: { + operation: "solana:list", + ...options, + }, + }); +} + +export function signSolanaTransaction({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + client, + request: { + operation: "solana:signTransaction", + ...options, + }, + }); +} + +export function signSolanaMessage({ + client, + request: options, +}: PayloadParams) { + return sendRequest({ + client, + request: { + operation: "solana:signMessage", + ...options, + }, + }); } const SIGNED_TOKEN_PREFIX = "vt_sat_"; const DEFAULT_SIGNING_CONTEXT = "encryption"; // Default context for HKDF export interface CreateSignedAccessTokenParams { - /** The VaultClient instance (used to get the enclave public key). */ - vaultClient: VaultClient; - /** The base access token string obtained from the createAccessToken API call. */ - baseAccessToken: string; - /** The specific policies to embed in the signed token's claims. */ - additionalPolicies: PolicyComponent[]; - /** The desired expiration time for the signed token (Unix timestamp in seconds). */ - expiryTimestamp: number; - /** Optional: The context string for HKDF key derivation. Defaults to "encryption". MUST match server expectation. */ - signingContext?: string; + /** The VaultClient instance (used to get the enclave public key). */ + vaultClient: VaultClient; + /** The base access token string obtained from the createAccessToken API call. */ + baseAccessToken: string; + /** The specific policies to embed in the signed token's claims. */ + additionalPolicies: PolicyComponent[]; + /** The desired expiration time for the signed token (Unix timestamp in seconds). */ + expiryTimestamp: number; + /** Optional: The context string for HKDF key derivation. Defaults to "encryption". MUST match server expectation. */ + signingContext?: string; } /** @@ -476,88 +582,88 @@ export interface CreateSignedAccessTokenParams { * @throws If any cryptographic operation or JWT signing fails. */ export async function createSignedAccessToken({ - vaultClient, - baseAccessToken, - additionalPolicies, - expiryTimestamp, - signingContext = DEFAULT_SIGNING_CONTEXT, + vaultClient, + baseAccessToken, + additionalPolicies, + expiryTimestamp, + signingContext = DEFAULT_SIGNING_CONTEXT, }: CreateSignedAccessTokenParams): Promise { - if (!vaultClient || !vaultClient.publicKey) { - throw new Error("Vault client or enclave public key is missing."); - } - if (!baseAccessToken) { - throw new Error("Base access token is required."); - } - if (!additionalPolicies) { - throw new Error("Additional policies are required."); - } - if (typeof expiryTimestamp !== "number" || expiryTimestamp <= 0) { - throw new Error("Valid expiry timestamp is required."); - } - - try { - const enclavePublicKey = vaultClient.publicKey; - const contextBytes = new TextEncoder().encode(signingContext); - - // 1. Generate client ephemeral keys for this operation - const clientEphemeralPrivateKey = randomBytes(32); - const clientEphemeralPublicKey = x25519.getPublicKey( - clientEphemeralPrivateKey, - ); - - // 2. Derive shared secret (Client Ephemeral Private Key + Enclave Public Key) - const sharedSecret = x25519.getSharedSecret( - clientEphemeralPrivateKey, - enclavePublicKey, - ); - - // 3. Derive encryption key using HKDF - const encryptionKey = hkdf( - sha256, - sharedSecret, - undefined, // No salt - contextBytes, // Use the provided or default context - 32, // 32 bytes key length - ); - - // 4. Encrypt the base access token string - const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 - const cipher = xchacha20poly1305(encryptionKey, nonce); - const baseTokenBytes = new TextEncoder().encode(baseAccessToken); - const ciphertext = cipher.encrypt(baseTokenBytes); - - // 5. Prepare JWT Signing Key (SHA-256 hash of the base token) - const secretBytes = new TextEncoder().encode(baseAccessToken); - const hashBuffer = await crypto.subtle.digest("SHA-256", secretBytes); - const jwtSigningKey = new Uint8Array(hashBuffer); - - // 6. Prepare JWT Claims - const claims = { - encrypted_token: bytesToHex(ciphertext), - ephemeral_public_key: bytesToHex(clientEphemeralPublicKey), - // Match Rust SignedTokenClaims struct (ensure names match server expectation) - exp: expiryTimestamp, - iat: Math.floor(Date.now() / 1000), - nonce: bytesToHex(nonce), - policies: additionalPolicies, - }; - - // 7. Sign the JWT using HS256 - const jwt = await new jose.SignJWT(claims) - .setProtectedHeader({ alg: "HS256" }) - // .setIssuedAt(claims.iat) // Included in claims - // .setExpirationTime(claims.exp) // Included in claims - .sign(jwtSigningKey); - - // 8. Prepend the prefix - const signedAccessToken = `${SIGNED_TOKEN_PREFIX}${jwt}`; - return signedAccessToken; - } catch (error) { - console.error("Error during signed access token creation:", error); - throw new Error( - `Failed to create signed access token: ${ - error instanceof Error ? error.message : String(error) - }`, - ); - } + if (!vaultClient || !vaultClient.publicKey) { + throw new Error("Vault client or enclave public key is missing."); + } + if (!baseAccessToken) { + throw new Error("Base access token is required."); + } + if (!additionalPolicies) { + throw new Error("Additional policies are required."); + } + if (typeof expiryTimestamp !== "number" || expiryTimestamp <= 0) { + throw new Error("Valid expiry timestamp is required."); + } + + try { + const enclavePublicKey = vaultClient.publicKey; + const contextBytes = new TextEncoder().encode(signingContext); + + // 1. Generate client ephemeral keys for this operation + const clientEphemeralPrivateKey = randomBytes(32); + const clientEphemeralPublicKey = x25519.getPublicKey( + clientEphemeralPrivateKey, + ); + + // 2. Derive shared secret (Client Ephemeral Private Key + Enclave Public Key) + const sharedSecret = x25519.getSharedSecret( + clientEphemeralPrivateKey, + enclavePublicKey, + ); + + // 3. Derive encryption key using HKDF + const encryptionKey = hkdf( + sha256, + sharedSecret, + undefined, // No salt + contextBytes, // Use the provided or default context + 32, // 32 bytes key length + ); + + // 4. Encrypt the base access token string + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const baseTokenBytes = new TextEncoder().encode(baseAccessToken); + const ciphertext = cipher.encrypt(baseTokenBytes); + + // 5. Prepare JWT Signing Key (SHA-256 hash of the base token) + const secretBytes = new TextEncoder().encode(baseAccessToken); + const hashBuffer = await crypto.subtle.digest("SHA-256", secretBytes); + const jwtSigningKey = new Uint8Array(hashBuffer); + + // 6. Prepare JWT Claims + const claims = { + encrypted_token: bytesToHex(ciphertext), + ephemeral_public_key: bytesToHex(clientEphemeralPublicKey), + // Match Rust SignedTokenClaims struct (ensure names match server expectation) + exp: expiryTimestamp, + iat: Math.floor(Date.now() / 1000), + nonce: bytesToHex(nonce), + policies: additionalPolicies, + }; + + // 7. Sign the JWT using HS256 + const jwt = await new jose.SignJWT(claims) + .setProtectedHeader({ alg: "HS256" }) + // .setIssuedAt(claims.iat) // Included in claims + // .setExpirationTime(claims.exp) // Included in claims + .sign(jwtSigningKey); + + // 8. Prepend the prefix + const signedAccessToken = `${SIGNED_TOKEN_PREFIX}${jwt}`; + return signedAccessToken; + } catch (error) { + console.error("Error during signed access token creation:", error); + throw new Error( + `Failed to create signed access token: ${ + error instanceof Error ? error.message : String(error) + }`, + ); + } } diff --git a/packages/vault-sdk/src/types.ts b/packages/vault-sdk/src/types.ts index 6ea9632234c..a014a4e4c6c 100644 --- a/packages/vault-sdk/src/types.ts +++ b/packages/vault-sdk/src/types.ts @@ -1,33 +1,33 @@ import type { - Address, - TypedData, - TypedDataDomain, - TypedDataToPrimitiveTypes, + Address, + TypedData, + TypedDataDomain, + TypedDataToPrimitiveTypes, } from "abitype"; import type { EthereumTypedTransaction } from "./transaction-types.js"; export type Prettify = { - [K in keyof T]: T[K]; + [K in keyof T]: T[K]; } & {}; // Encrypted types export type EncryptedPayload = { - ephemeralPublicKey: string; - nonce: string; - ciphertext: string; + ephemeralPublicKey: string; + nonce: string; + ciphertext: string; }; // ========== Authentication Types ========== type AdminKeyAuth = { - adminKey: string; + adminKey: string; }; type AccessTokenAuth = { - accessToken: string; + accessToken: string; }; type SessionTokenAuth = { - sessionToken: string; + sessionToken: string; }; // Regular Auth union (excluding RotationCodeAuth) @@ -35,7 +35,7 @@ export type Auth = AdminKeyAuth | AccessTokenAuth | SessionTokenAuth; // Separate RotationCodeAuth (used only for rotation) type RotationCodeAuth = { - rotationCode: string; + rotationCode: string; }; // ========== Base Types ========== @@ -45,120 +45,164 @@ type Bytes = string; // e.g., "0x..." type BigNumberString = string; // String representation of U256/I256 type UnencryptedError = { - message: string; - status: number; - type: string; - details?: string; + message: string; + status: number; + type: string; + details?: string; }; export type UnencryptedErrorResponse = { - error: UnencryptedError; + error: UnencryptedError; }; type EncryptedError = { - code: string; - message: string; - details?: string; + code: string; + message: string; + details?: string; }; type GenericSuccessResponse = { - success: true; - data: Data; - error: null; + success: true; + data: Data; + error: null; }; type GenericErrorResponse = { - success: false; - data: null; - error: EncryptedError | UnencryptedError; + success: false; + data: null; + error: EncryptedError | UnencryptedError; }; export type VaultError = EncryptedError | UnencryptedError; type GenericResponse = - | GenericSuccessResponse - | GenericErrorResponse; + | GenericSuccessResponse + | GenericErrorResponse; // ========== Payload Type ========== export type OmitNever = { - [K in keyof T as T[K] extends never ? never : K]: T[K]; + [K in keyof T as T[K] extends never ? never : K]: T[K]; }; export type GenericPayload< - T extends { - operation: string; - auth?: Auth | RotationCodeAuth | never; - options?: Record | never; - data: unknown; - }, + T extends { + operation: string; + auth?: Auth | RotationCodeAuth | never; + options?: Record | never; + data: unknown; + }, > = { - input: OmitNever<{ - operation: T["operation"]; - options: T["options"]; - auth: T["auth"]; - }>; - output: GenericResponse; + input: OmitNever<{ + operation: T["operation"]; + options: T["options"]; + auth: T["auth"]; + }>; + output: GenericResponse; }; // ========== Options Types ========== type CreateServiceAccountOptions = { - metadata: Record; + metadata: Record; }; type MetadataValue = string | number | boolean; type CreateEoaOptions = { - metadata: Record; + metadata: Record; }; type GetEoasOptions = { - page?: number; - pageSize?: number; + page?: number; + pageSize?: number; }; type PingOptions = { - message: string; + message: string; }; type SignTransactionOptions = { - transaction: EthereumTypedTransaction; - from: string; + transaction: EthereumTypedTransaction; + from: string; }; export type SignAuthorizationOptions = { - from: Address; - authorization: Authorization; // Use the defined type + from: Address; + authorization: Authorization; // Use the defined type }; export type SignStructuredMessageOptions = { - from: Address; - structuredMessage: StructuredMessageInput; // Use the defined type - chainId?: number; // Keep as number for ChainId + from: Address; + structuredMessage: StructuredMessageInput; // Use the defined type + chainId?: number; // Keep as number for ChainId }; export type GetAccessTokensOptions = { - page?: number; - pageSize?: number; + page?: number; + pageSize?: number; }; type SignMessageOptions = { - message: string; - from: string; - chainId?: number; - format?: "text" | "hex"; + message: string; + from: string; + chainId?: number; + format?: "text" | "hex"; +}; + +// ========== Solana Options Types ========== + +// Solana message type that's compatible with both Kit and our Rust serialization +export type SolanaVersionedMessage = { + version: "legacy" | "v0"; + header: { + numRequiredSignatures: number; + numReadonlySignedAccounts: number; + numReadonlyUnsignedAccounts: number; + }; + staticAccountKeys: string[]; // Use string instead of SolanaAddress for simplicity + recentBlockhash: string; + instructions: Array<{ + programIdIndex: number; + accountKeyIndexes: number[]; + data: Uint8Array; + }>; + addressTableLookups?: Array<{ + accountKey: string; // Use string instead of SolanaAddress + writableIndexes: number[]; + readonlyIndexes: number[]; + }>; +}; + +type CreateSolanaAccountOptions = { + metadata: Record; +}; + +type GetSolanaAccountsOptions = { + page?: number; + pageSize?: number; +}; + +type SignSolanaTransactionOptions = { + message: SolanaVersionedMessage; + from: string; // Use string for Solana public key +}; + +type SignSolanaMessageOptions = { + message: string; + from: string; // Use string for Solana public key + format?: "text" | "hex"; }; type CheckedSignTypedDataOptions< - Types extends TypedData, - PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, > = { - typedData: { - domain: TypedDataDomain; - types: Types; - primaryType: PrimaryType; - message: TypedDataToPrimitiveTypes[PrimaryType]; - }; - from: string; + typedData: { + domain: TypedDataDomain; + types: Types; + primaryType: PrimaryType; + message: TypedDataToPrimitiveTypes[PrimaryType]; + }; + from: string; }; // biome-ignore lint/suspicious/noExplicitAny: we truly want to accept anything here @@ -168,404 +212,486 @@ type SignedTypedDataOptions = CheckedSignTypedDataOptions; // Corresponds to Rust UserOperationV06Input export type UserOperationV06Input = { - sender: Address; - nonce: BigNumberString; // U256 - initCode?: Bytes; // Optional due to #[serde(default)] - callData: Bytes; - callGasLimit: BigNumberString; // U256 - verificationGasLimit: BigNumberString; // U256 - preVerificationGas: BigNumberString; // U256 - maxFeePerGas: BigNumberString; // U256 - maxPriorityFeePerGas: BigNumberString; // U256 - paymasterAndData?: Bytes; // Optional due to #[serde(default)] - signature?: Bytes; // Optional due to #[serde(default)] - entrypoint?: Address; // Optional due to #[serde(default = ...)] + sender: Address; + nonce: BigNumberString; // U256 + initCode?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymasterAndData?: Bytes; // Optional due to #[serde(default)] + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] }; // Corresponds to Rust UserOperationV07Input export type UserOperationV07Input = { - sender: Address; - nonce: BigNumberString; // U256 - factory?: Address; // Optional due to #[serde(default)] - factoryData?: Bytes; // Optional due to #[serde(default)] - callData: Bytes; - callGasLimit: BigNumberString; // U256 - verificationGasLimit: BigNumberString; // U256 - preVerificationGas: BigNumberString; // U256 - maxFeePerGas: BigNumberString; // U256 - maxPriorityFeePerGas: BigNumberString; // U256 - paymaster?: Address; // Optional due to #[serde(default)] - paymasterData?: Bytes; // Optional due to #[serde(default)] - Assuming default is empty bytes - paymasterVerificationGasLimit?: BigNumberString; // U256 - Assuming default is 0 - paymasterPostOpGasLimit?: BigNumberString; // U256 - Assuming default is 0 - signature?: Bytes; // Optional due to #[serde(default)] - entrypoint?: Address; // Optional due to #[serde(default = ...)] + sender: Address; + nonce: BigNumberString; // U256 + factory?: Address; // Optional due to #[serde(default)] + factoryData?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymaster?: Address; // Optional due to #[serde(default)] + paymasterData?: Bytes; // Optional due to #[serde(default)] - Assuming default is empty bytes + paymasterVerificationGasLimit?: BigNumberString; // U256 - Assuming default is 0 + paymasterPostOpGasLimit?: BigNumberString; // U256 - Assuming default is 0 + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] }; // Corresponds to Rust StructuredMessageInput enum export type StructuredMessageInput = - | { useropV06: UserOperationV06Input } - | { useropV07: UserOperationV07Input }; + | { useropV06: UserOperationV06Input } + | { useropV07: UserOperationV07Input }; // ========== Policy Types ========== type RegexRule = { - pattern: string; + pattern: string; }; type NumberRuleOp = "greaterThan" | "lessThan" | "equalTo"; type NumberRule = { - op: NumberRuleOp; - value: number | BigNumberString; + op: NumberRuleOp; + value: number | BigNumberString; }; type Rule = NumberRule | RegexRule; type MetadataRule = { - key: string; - rule: Rule; + key: string; + rule: Rule; }; // ========== Policy Rule Structs ========== // Corresponds to Rust UserOperationV06Rules export type UserOperationV06Rules = { - sender?: Rule; - nonce?: Rule; - initCode?: Rule; - callData?: Rule; - callGasLimit?: Rule; - verificationGasLimit?: Rule; - preVerificationGas?: Rule; - maxFeePerGas?: Rule; - maxPriorityFeePerGas?: Rule; - paymasterAndData?: Rule; - chainId?: Rule; - entrypoint?: Rule; // Optional, but Rust has a default func + sender?: Rule; + nonce?: Rule; + initCode?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymasterAndData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func }; // Corresponds to Rust UserOperationV07Rules export type UserOperationV07Rules = { - sender?: Rule; - nonce?: Rule; - factory?: Rule; - factoryData?: Rule; - callData?: Rule; - callGasLimit?: Rule; - verificationGasLimit?: Rule; - preVerificationGas?: Rule; - maxFeePerGas?: Rule; - maxPriorityFeePerGas?: Rule; - paymaster?: Rule; - paymasterVerificationGasLimit?: Rule; - paymasterPostOpGasLimit?: Rule; - paymasterData?: Rule; - chainId?: Rule; - entrypoint?: Rule; // Optional, but Rust has a default func + sender?: Rule; + nonce?: Rule; + factory?: Rule; + factoryData?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymaster?: Rule; + paymasterVerificationGasLimit?: Rule; + paymasterPostOpGasLimit?: Rule; + paymasterData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func }; // Corresponds to Rust SignAuthorizationRules export type SignAuthorizationRules = { - chainId?: Rule; - nonce?: Rule; - address?: Rule; + chainId?: Rule; + nonce?: Rule; + address?: Rule; }; export type PolicyComponent = - | { - type: "eoa:create"; - requiredMetadataPatterns?: MetadataRule[]; - allowedMetadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:read"; - metadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:signTransaction"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - payloadPatterns: Record; - } - | { - type: "eoa:signMessage"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - chainId?: number; - messagePattern?: string; - } - | { - type: "eoa:signTypedData"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:signAuthorization"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - payloadPatterns?: SignAuthorizationRules; - } - | { - type: "eoa:signStructuredMessage"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - // Define how UserOp rules are applied, e.g., separate for v6/v7 - structuredPatterns: { - useropV06?: UserOperationV06Rules; - useropV07?: UserOperationV07Rules; - }; - } - | { - type: "accessToken:read"; - metadataPatterns?: MetadataRule[]; - revealSensitive: boolean; - }; + | { + type: "eoa:create"; + requiredMetadataPatterns?: MetadataRule[]; + allowedMetadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:read"; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signTransaction"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns: Record; + } + | { + type: "eoa:signMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + chainId?: number; + messagePattern?: string; + } + | { + type: "eoa:signTypedData"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signAuthorization"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns?: SignAuthorizationRules; + } + | { + type: "eoa:signStructuredMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + // Define how UserOp rules are applied, e.g., separate for v6/v7 + structuredPatterns: { + useropV06?: UserOperationV06Rules; + useropV07?: UserOperationV07Rules; + }; + } + | { + type: "solana:create"; + requiredMetadataPatterns?: MetadataRule[]; + allowedMetadataPatterns?: MetadataRule[]; + } + | { + type: "solana:read"; + metadataPatterns?: MetadataRule[]; + } + | { + type: "solana:signTransaction"; + allowlist?: string[]; // Use string for Solana addresses + metadataPatterns?: MetadataRule[]; + payloadPatterns?: Record; + requiredCosigners?: string[]; // Use string for Solana addresses + } + | { + type: "solana:signMessage"; + allowlist?: string[]; // Use string for Solana addresses + metadataPatterns?: MetadataRule[]; + messagePattern?: string; + } + | { + type: "accessToken:read"; + metadataPatterns?: MetadataRule[]; + revealSensitive: boolean; + }; type OwnerType = string; // Define based on your eoa models type CreateAccessTokenOptions = { - policies: PolicyComponent[]; - expiresAt: string; // ISO date string - metadata: Record; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; }; type RevokeAccessTokenOptions = { - id: string; // UUID + id: string; // UUID }; // ========== Authorization Types ========== // Corresponds to Rust Authorization struct export type Authorization = { - chainId: BigNumberString; // U256 - address: Address; - nonce: number; // u64 + chainId: BigNumberString; // U256 + address: Address; + nonce: number; // u64 }; // Corresponds to Rust SignedAuthorization struct // Merges Authorization fields due to #[serde(flatten)] export type SignedAuthorization = Authorization & { - yParity: number; // U8 (typically 0 or 1) - r: BigNumberString; // U256 - s: BigNumberString; // U256 + yParity: number; // U8 (typically 0 or 1) + r: BigNumberString; // U256 + s: BigNumberString; // U256 }; // ========== Response Data Types ========== type PingData = { - timestamp: number; - pong: string; + timestamp: number; + pong: string; }; type CreateServiceAccountData = { - id: string; // UUID - adminKey: string; - rotationCode: string; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + adminKey: string; + rotationCode: string; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type GetServiceAccountData = { - id: string; // UUID - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type RotateServiceAccountData = { - newAdminKey: string; - newRotationCode: string; + newAdminKey: string; + newRotationCode: string; }; type EoaData = { - id: string; // UUID - address: string; - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + address: string; + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type GetEoasData = { - items: EoaData[]; - page: number; - pageSize: number; - totalRecords: number; + items: EoaData[]; + page: number; + pageSize: number; + totalRecords: number; }; type SignTransactionData = { - signature: string; + signature: string; }; type SignMessageData = { - signature: string; + signature: string; +}; + +// ========== Solana Data Types ========== +type CreateSolanaAccountData = { + address: string; // Use string for Solana address + publicKey: string; // Base58 encoded + pubkey?: number[]; // Raw byte array from vault (for compatibility) + metadata: Record; + createdAt: string; + updatedAt: string; +}; + +type GetSolanaAccountsData = { + accounts: CreateSolanaAccountData[]; + totalCount: number; + page: number; + pageSize: number; +}; + +type SignSolanaTransactionData = { + signature: string; // Base58 encoded signature + signerPubkey: string; // Use string for Solana public key +}; + +type SignSolanaMessageData = { + signature: string; // Base58 encoded signature + signedMessage: string; }; type SignTypedDataData = { - signature: string; + signature: string; }; export type AccessTokenData = { - accessToken: string; - id: string; // UUID - issuerId: string; // UUID - issuerType: OwnerType; - policies: PolicyComponent[]; - expiresAt: string; // ISO date string - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string - /** - * If nullish then token hasn't been explicitly revoked, otherwise the ISO date string of the revocation. - * Note that an access token will be "implicitly" revoked if the token issuer account gets rotated. Check the isRotated field for this - */ - revokedAt?: string; // ISO date string - /** - * Reflects whether the issuer of this token has "rotated" their account, which implicitly revokes the token, but is not tracked by the revokedAt? field. - */ - isRotated: boolean; + accessToken: string; + id: string; // UUID + issuerId: string; // UUID + issuerType: OwnerType; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + /** + * If nullish then token hasn't been explicitly revoked, otherwise the ISO date string of the revocation. + * Note that an access token will be "implicitly" revoked if the token issuer account gets rotated. Check the isRotated field for this + */ + revokedAt?: string; // ISO date string + /** + * Reflects whether the issuer of this token has "rotated" their account, which implicitly revokes the token, but is not tracked by the revokedAt? field. + */ + isRotated: boolean; }; // Update SignAuthorizationData to use the defined SignedAuthorization type export type SignAuthorizationData = { - signedAuthorization: SignedAuthorization; // Use the defined type + signedAuthorization: SignedAuthorization; // Use the defined type }; // Add SignStructuredMessageData (as defined previously) export type SignStructuredMessageData = { - signature: Bytes; - message: string; // This likely represents the UserOp hash in Rust + signature: Bytes; + message: string; // This likely represents the UserOp hash in Rust }; // Add GetAccessTokensData (as defined previously) export type GetAccessTokensData = { - items: AccessTokenData[]; - page: number; - pageSize: number; - totalRecords: number; // Rust uses u64, TS uses number + items: AccessTokenData[]; + page: number; + pageSize: number; + totalRecords: number; // Rust uses u64, TS uses number }; // ========== Operation Payloads ========== export type PingPayload = GenericPayload<{ - operation: "ping"; - options: PingOptions; - auth: never; - data: PingData; + operation: "ping"; + options: PingOptions; + auth: never; + data: PingData; }>; export type CreateServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:create"; - options: CreateServiceAccountOptions; - auth: never; - data: CreateServiceAccountData; + operation: "serviceAccount:create"; + options: CreateServiceAccountOptions; + auth: never; + data: CreateServiceAccountData; }>; export type GetServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:get"; - options: never; - auth: Auth; - data: GetServiceAccountData; + operation: "serviceAccount:get"; + options: never; + auth: Auth; + data: GetServiceAccountData; }>; export type RotateServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:rotate"; - options: never; - auth: RotationCodeAuth; // Only accepts RotationCodeAuth - data: RotateServiceAccountData; + operation: "serviceAccount:rotate"; + options: never; + auth: RotationCodeAuth; // Only accepts RotationCodeAuth + data: RotateServiceAccountData; }>; export type CreateEoaPayload = GenericPayload<{ - operation: "eoa:create"; - auth: Auth; - options: CreateEoaOptions; - data: EoaData; + operation: "eoa:create"; + auth: Auth; + options: CreateEoaOptions; + data: EoaData; }>; export type ListEoaPayload = GenericPayload<{ - operation: "eoa:list"; - auth: Auth; - options: GetEoasOptions; - data: GetEoasData; + operation: "eoa:list"; + auth: Auth; + options: GetEoasOptions; + data: GetEoasData; }>; export type SignTransactionPayload = GenericPayload<{ - operation: "eoa:signTransaction"; - auth: Auth; - options: SignTransactionOptions; - data: SignTransactionData; + operation: "eoa:signTransaction"; + auth: Auth; + options: SignTransactionOptions; + data: SignTransactionData; }>; export type SignAuthorizationPayload = GenericPayload<{ - operation: "eoa:signAuthorization"; - auth: Auth; // Assuming Auth is defined as before - options: SignAuthorizationOptions; - data: SignAuthorizationData; + operation: "eoa:signAuthorization"; + auth: Auth; // Assuming Auth is defined as before + options: SignAuthorizationOptions; + data: SignAuthorizationData; }>; // Add SignStructuredMessagePayload (using defined types) export type SignStructuredMessagePayload = GenericPayload<{ - operation: "eoa:signStructuredMessage"; - auth: Auth; // Assuming Auth is defined as before - options: SignStructuredMessageOptions; - data: SignStructuredMessageData; + operation: "eoa:signStructuredMessage"; + auth: Auth; // Assuming Auth is defined as before + options: SignStructuredMessageOptions; + data: SignStructuredMessageData; }>; export type CheckedSignTypedDataPayload< - Types extends TypedData, - PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, > = GenericPayload<{ - operation: "eoa:signTypedData"; - auth: Auth; - options: CheckedSignTypedDataOptions; - data: SignTypedDataData; + operation: "eoa:signTypedData"; + auth: Auth; + options: CheckedSignTypedDataOptions; + data: SignTypedDataData; }>; export type SignTypedDataPayload = GenericPayload<{ - operation: "eoa:signTypedData"; - auth: Auth; - options: SignedTypedDataOptions; - data: SignTypedDataData; + operation: "eoa:signTypedData"; + auth: Auth; + options: SignedTypedDataOptions; + data: SignTypedDataData; }>; export type SignMessagePayload = GenericPayload<{ - operation: "eoa:signMessage"; - auth: Auth; - options: SignMessageOptions; - data: SignMessageData; + operation: "eoa:signMessage"; + auth: Auth; + options: SignMessageOptions; + data: SignMessageData; }>; export type CreateAccessTokenPayload = GenericPayload<{ - operation: "accessToken:create"; - auth: Auth; - options: CreateAccessTokenOptions; - data: AccessTokenData; + operation: "accessToken:create"; + auth: Auth; + options: CreateAccessTokenOptions; + data: AccessTokenData; }>; // Add ListAccessTokensPayload (using defined types) export type ListAccessTokensPayload = GenericPayload<{ - operation: "accessToken:list"; - auth: Auth; - data: GetAccessTokensData; + operation: "accessToken:list"; + auth: Auth; + data: GetAccessTokensData; }>; export type RevokeAccessTokenPayload = GenericPayload<{ - operation: "accessToken:revoke"; - auth: Auth; - options: RevokeAccessTokenOptions; - data: AccessTokenData; + operation: "accessToken:revoke"; + auth: Auth; + options: RevokeAccessTokenOptions; + data: AccessTokenData; +}>; + +// ========== Solana Payload Types ========== +export type CreateSolanaAccountPayload = GenericPayload<{ + operation: "solana:create"; + auth: Auth; + options: CreateSolanaAccountOptions; + data: CreateSolanaAccountData; +}>; + +export type ListSolanaAccountsPayload = GenericPayload<{ + operation: "solana:list"; + auth: Auth; + options: GetSolanaAccountsOptions; + data: GetSolanaAccountsData; +}>; + +export type SignSolanaTransactionPayload = GenericPayload<{ + operation: "solana:signTransaction"; + auth: Auth; + options: SignSolanaTransactionOptions; + data: SignSolanaTransactionData; +}>; + +export type SignSolanaMessagePayload = GenericPayload<{ + operation: "solana:signMessage"; + auth: Auth; + options: SignSolanaMessageOptions; + data: SignSolanaMessageData; }>; // ========== Union of all payloads ========== export type Payload = - | PingPayload - | CreateServiceAccountPayload - | GetServiceAccountPayload - | RotateServiceAccountPayload - | CreateEoaPayload - | ListEoaPayload - | SignTransactionPayload - | SignMessagePayload - | SignTypedDataPayload - | CreateAccessTokenPayload - | RevokeAccessTokenPayload - | SignAuthorizationPayload - | SignStructuredMessagePayload - | ListAccessTokensPayload; + | PingPayload + | CreateServiceAccountPayload + | GetServiceAccountPayload + | RotateServiceAccountPayload + | CreateEoaPayload + | ListEoaPayload + | SignTransactionPayload + | SignMessagePayload + | SignTypedDataPayload + | CreateAccessTokenPayload + | RevokeAccessTokenPayload + | SignAuthorizationPayload + | SignStructuredMessagePayload + | ListAccessTokensPayload + | CreateSolanaAccountPayload + | ListSolanaAccountsPayload + | SignSolanaTransactionPayload + | SignSolanaMessagePayload; diff --git a/packages/vault-sdk/test-solana.ts b/packages/vault-sdk/test-solana.ts new file mode 100644 index 00000000000..46a982a38f0 --- /dev/null +++ b/packages/vault-sdk/test-solana.ts @@ -0,0 +1,382 @@ +#!/usr/bin/env tsx + +/** + * Comprehensive Solana Integration Test + * Tests the vault SDK with Solana operations + */ + +import { + createServiceAccount, + createSolanaAccount, + createVaultClient, + listSolanaAccounts, + signSolanaMessage, + signSolanaTransaction, + type VaultClient, +} from "./src/exports/thirdweb.js"; +// Vault SDK imports +import type { SolanaVersionedMessage } from "./src/types.js"; + +const VAULT_URL = "http://localhost:3000"; + +async function main(): Promise { + console.log("🚀 Starting Solana Integration Test...\n"); + console.log("🔧 Configuration:"); + console.log(` Vault URL: ${VAULT_URL}`); + console.log(` Node version: ${process.version}`); + console.log(` Platform: ${process.platform}\n`); + + // Test basic connectivity + console.log("🔍 Testing vault connectivity..."); + try { + const response = await fetch(`${VAULT_URL}/health`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }); + console.log(` Health check status: ${response.status}`); + console.log(` Health check ok: ${response.ok}`); + + if (response.ok) { + const healthData = await response.text(); + console.log(` Health response: ${healthData}`); + } + } catch (healthError) { + console.warn( + "⚠️ Health check failed:", + healthError instanceof Error ? healthError.message : healthError, + ); + console.warn(" Continuing with test anyway..."); + } + console.log(); + + try { + // Step 1: Create Vault Client + console.log("📡 Creating vault client..."); + console.log(` Connecting to: ${VAULT_URL}`); + + const vaultClient: VaultClient = await createVaultClient({ + baseUrl: VAULT_URL, + }); + + console.log("✅ Vault client created successfully"); + console.log(` Client type: ${typeof vaultClient}`); + console.log(` Client keys: ${Object.keys(vaultClient)}\n`); + + // Step 2: Create Service Account + console.log("👤 Creating service account..."); + console.log( + " Request payload:", + JSON.stringify( + { + options: { + metadata: { + name: "Solana Test Service Account", + description: "Testing Solana integration", + }, + }, + }, + null, + 2, + ), + ); + + const serviceAccountResult = await createServiceAccount({ + client: vaultClient, + request: { + options: { + metadata: { + name: "Solana Test Service Account", + description: "Testing Solana integration", + }, + }, + }, + }); + + console.log("✅ Service account response received"); + console.log( + " Response structure:", + JSON.stringify(serviceAccountResult, null, 2), + ); + console.log(" Service account ID:", serviceAccountResult.data?.id); + console.log(" Admin key present:", !!serviceAccountResult.data?.adminKey); + console.log( + " Admin key length:", + serviceAccountResult.data?.adminKey?.length || 0, + "\n", + ); + + const adminKey: string = serviceAccountResult.data?.adminKey || ""; + if (!adminKey) { + console.error("❌ No admin key in response!"); + console.error( + " Full response:", + JSON.stringify(serviceAccountResult, null, 2), + ); + throw new Error("Failed to get admin key from service account creation"); + } + + // Step 3: Create First Solana Account + console.log("🌟 Creating first Solana account..."); + console.log(" Using admin key:", `${adminKey.substring(0, 10)}...`); + console.log( + " Request payload:", + JSON.stringify( + { + auth: { adminKey: `${adminKey.substring(0, 10)}...` }, + options: { + metadata: { + name: "Test Account 1", + purpose: "Primary test account", + }, + }, + }, + null, + 2, + ), + ); + + const solanaAccount1 = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + metadata: { + name: "Test Account 1", + purpose: "Primary test account", + }, + }, + }, + }); + + console.log("✅ First Solana account response received"); + console.log( + " Response structure:", + JSON.stringify(solanaAccount1, null, 2), + ); + console.log(" Account address:", solanaAccount1.data?.address); + console.log(" Public key:", solanaAccount1.data?.publicKey); + console.log( + " Metadata:", + JSON.stringify(solanaAccount1.data?.metadata, null, 2), + "\n", + ); + + // Step 4: Create Second Solana Account + console.log("🌟 Creating second Solana account..."); + const solanaAccount2 = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + metadata: { + name: "Test Account 2", + purpose: "Secondary test account", + }, + }, + }, + }); + + console.log("✅ Second Solana account response received"); + console.log( + " Response structure:", + JSON.stringify(solanaAccount2, null, 2), + ); + console.log(" Account address:", solanaAccount2.data?.address); + console.log(" Public key:", solanaAccount2.data?.publicKey, "\n"); + + // Step 5: List Solana Accounts + console.log("📋 Listing Solana accounts..."); + const accountsList = await listSolanaAccounts({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + page: 1, + pageSize: 10, + }, + }, + }); + + console.log("✅ List accounts response received"); + console.log( + " Response structure:", + JSON.stringify(accountsList, null, 2), + ); + console.log(" Total count:", accountsList.data?.totalCount); + console.log(" Accounts found:", accountsList.data?.accounts?.length || 0); + + accountsList.data?.accounts?.forEach((acc, i) => { + console.log( + ` ${i + 1}. ${acc.address} (${acc.metadata?.name || "No name"})`, + ); + }); + console.log(); + + // Step 6: Create Test Transaction Message + console.log("💸 Creating test transaction message..."); + const transferAmount: bigint = 500_000_000n; // 0.5 SOL + + // Ensure we have the account data + if (!solanaAccount1.data?.publicKey || !solanaAccount2.data?.publicKey) { + throw new Error("Missing account data"); + } + + console.log("✅ Test transaction message prepared"); + console.log("📦 Transfer amount:", transferAmount / 1_000_000_000n, "SOL"); + console.log("👤 From:", solanaAccount1.data.publicKey); + console.log("👤 To:", solanaAccount2.data.publicKey, "\n"); + + // Step 7: Sign Transaction with Vault + console.log("✍️ Signing transaction with vault..."); + + // Create a simple test transaction message + const vaultMessage: SolanaVersionedMessage = { + version: "legacy", + header: { + numRequiredSignatures: 1, + numReadonlySignedAccounts: 0, + numReadonlyUnsignedAccounts: 1, + }, + staticAccountKeys: [ + solanaAccount1.data.publicKey, + solanaAccount2.data.publicKey, + "11111111111111111111111111111111", // System program + ], + recentBlockhash: "11111111111111111111111111111111111111111111", // Dummy blockhash for testing + instructions: [ + { + programIdIndex: 2, // System program + accountKeyIndexes: [0, 1], // From and to accounts + data: new Uint8Array([2, 0, 0, 0, 0, 202, 154, 59, 0, 0, 0, 0]), // Transfer 0.5 SOL + }, + ], + }; + + console.log( + " Transaction message:", + JSON.stringify(vaultMessage, null, 2), + ); + console.log(" Signing with account:", solanaAccount1.data.publicKey); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + message: vaultMessage, + from: solanaAccount1.data.publicKey, + }, + }, + }); + + console.log("✅ Transaction signing response received"); + console.log( + " Response structure:", + JSON.stringify(signatureResult, null, 2), + ); + console.log(" Signature:", signatureResult.data?.signature); + console.log(" Signer pubkey:", signatureResult.data?.signerPubkey, "\n"); + + // Step 8: Test Message Signing + console.log("📝 Testing message signing..."); + const testMessage = "Hello from Solana Vault Integration Test!"; + console.log(" Message to sign:", testMessage); + console.log(" Signing with account:", solanaAccount1.data.publicKey); + + const messageSignature = await signSolanaMessage({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + message: testMessage, + from: solanaAccount1.data.publicKey, + format: "text", + }, + }, + }); + + console.log("✅ Message signing response received"); + console.log( + " Response structure:", + JSON.stringify(messageSignature, null, 2), + ); + console.log(" Signature:", messageSignature.data?.signature); + console.log( + " Signed message:", + messageSignature.data?.signedMessage, + "\n", + ); + + // Step 9: Summary + console.log("🎉 Test Summary:"); + console.log("================"); + console.log("✅ Vault client created"); + console.log("✅ Service account created"); + console.log("✅ Two Solana accounts created"); + console.log("✅ Accounts listed successfully"); + console.log("✅ Transaction message created"); + console.log("✅ Transaction signed with vault"); + console.log("✅ Message signing tested"); + console.log("\n🔍 Explorer Links:"); + console.log( + ` Account 1: https://explorer.solana.com/address/${solanaAccount1.data?.publicKey}?cluster=devnet`, + ); + console.log( + ` Account 2: https://explorer.solana.com/address/${solanaAccount2.data?.publicKey}?cluster=devnet`, + ); + + console.log("\n🎯 All tests completed successfully!"); + console.log("\n💡 Next steps:"); + console.log(" 1. Fund the accounts using the Solana faucet"); + console.log( + " 2. Use a Solana client library to create real transactions", + ); + console.log(" 3. Sign them with the vault and submit to the network"); + } catch (error: unknown) { + console.error("\n❌ Test failed!"); + console.error("================"); + + if (error instanceof Error) { + console.error("Error name:", error.name); + console.error("Error message:", error.message); + console.error("Stack trace:", error.stack); + + // Check for network errors + if (error.message.includes("ECONNREFUSED")) { + console.error("\n🔍 Network Error Details:"); + console.error(" - Connection refused to vault server"); + console.error(" - Make sure the vault is running on", VAULT_URL); + console.error(" - Check if the port is correct (3000)"); + } + + // Check for HTTP errors + if (error.message.includes("fetch")) { + console.error("\n🔍 HTTP Error Details:"); + console.error(" - Failed to make HTTP request"); + console.error(" - Vault URL:", VAULT_URL); + console.error(" - Check network connectivity"); + } + + // Check for JSON parsing errors + if (error.message.includes("JSON")) { + console.error("\n🔍 JSON Error Details:"); + console.error(" - Failed to parse response"); + console.error(" - Server might be returning non-JSON response"); + } + } else { + console.error("Unknown error type:", typeof error); + console.error("Error value:", error); + } + + console.error("\n💡 Troubleshooting steps:"); + console.error(" 1. Ensure the vault server is running"); + console.error(" 2. Check the vault URL and port"); + console.error(" 3. Verify network connectivity"); + console.error(" 4. Check vault logs for errors"); + + process.exit(1); + } +} + +// Run the test +main().catch(console.error); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bf80a5dc580..78406ba4946 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -581,7 +581,7 @@ importers: dependencies: '@abstract-foundation/agw-react': specifier: ^1.6.4 - version: 1.6.4(pfuoymnekjwwwvphlum3lcxazm) + version: 1.6.4(lfgxwuqm6efii3akecbct27dfa) '@ai-sdk/react': specifier: ^2.0.25 version: 2.0.25(react@19.1.0)(zod@3.25.75) @@ -1665,6 +1665,18 @@ importers: '@noble/hashes': specifier: 1.7.2 version: 1.7.2 + '@solana/addresses': + specifier: ^3.0.0 + version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/keys': + specifier: ^3.0.0 + version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': + specifier: ^3.0.0 + version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': + specifier: ^3.0.0 + version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) abitype: specifier: 1.0.8 version: 1.0.8(typescript@5.8.3)(zod@3.25.76) @@ -6430,12 +6442,24 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/addresses@3.0.3': + resolution: {integrity: sha512-AuMwKhJI89ANqiuJ/fawcwxNKkSeHH9CApZd2xelQQLS7X8uxAOovpcmEgiObQuiVP944s9ScGUT62Bdul9qYg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/assertions@2.3.0': resolution: {integrity: sha512-Ekoet3khNg3XFLN7MIz8W31wPQISpKUGDGTylLptI+JjCDWx3PIa88xjEMqFo02WJ8sBj2NLV64Xg1sBcsHjZQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/assertions@3.0.3': + resolution: {integrity: sha512-2qspxdbWp2y62dfCIlqeWQr4g+hE8FYSSwcaP6itwMwGRb8393yDGCJfI/znuzJh6m/XVWhMHIgFgsBwnevCmg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/buffer-layout-utils@0.2.0': resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} engines: {node: '>= 10'} @@ -6455,6 +6479,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-core@3.0.3': + resolution: {integrity: sha512-emKykJ3h1DmnDOY29Uv9eJXP8E/FHzvlUBJ6te+5EbKdFjj7vdlKYPfDxOI6iGdXTY+YC/ELtbNBh6QwF2uEDQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-data-structures@2.0.0-rc.1': resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==} peerDependencies: @@ -6466,6 +6496,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-data-structures@3.0.3': + resolution: {integrity: sha512-R15cLp8riJvToXziW8lP6AMSwsztGhEnwgyGmll32Mo0Yjq+hduW2/fJrA/TJs6tA/OgTzMQjlxgk009EqZHCw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-numbers@2.0.0-rc.1': resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==} peerDependencies: @@ -6477,6 +6513,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-numbers@3.0.3': + resolution: {integrity: sha512-pfXkH9J0glrM8qj6389GAn30+cJOxzXLR2FsPOHCUMXrqLhGjMMZAWhsQkpOQ37SGc/7EiQsT/gmyGC7gxHqJQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-strings@2.0.0-rc.1': resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==} peerDependencies: @@ -6490,6 +6532,13 @@ packages: fastestsmallesttextencoderdecoder: ^1.0.22 typescript: '>=5.3.3' + '@solana/codecs-strings@3.0.3': + resolution: {integrity: sha512-VHBXnnTVtcQ1j+7Vrz+qSYo38no+jiHRdGnhFspRXEHNJbllzwKqgBE7YN3qoIXH+MKxgJUcwO5KHmdzf8Wn2A==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + '@solana/codecs@2.0.0-rc.1': resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==} peerDependencies: @@ -6514,30 +6563,61 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/errors@3.0.3': + resolution: {integrity: sha512-1l84xJlHNva6io62PcYfUamwWlc0eM95nHgCrKX0g0cLoC6D6QHYPCEbEVkR+C5UtP9JDgyQM8MFiv+Ei5tO9Q==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + '@solana/fast-stable-stringify@2.3.0': resolution: {integrity: sha512-KfJPrMEieUg6D3hfQACoPy0ukrAV8Kio883llt/8chPEG3FVTX9z/Zuf4O01a15xZmBbmQ7toil2Dp0sxMJSxw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/fast-stable-stringify@3.0.3': + resolution: {integrity: sha512-ED0pxB6lSEYvg+vOd5hcuQrgzEDnOrURFgp1ZOY+lQhJkQU6xo+P829NcJZQVP1rdU2/YQPAKJKEseyfe9VMIw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/functional@2.3.0': resolution: {integrity: sha512-AgsPh3W3tE+nK3eEw/W9qiSfTGwLYEvl0rWaxHht/lRcuDVwfKRzeSa5G79eioWFFqr+pTtoCr3D3OLkwKz02Q==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/functional@3.0.3': + resolution: {integrity: sha512-2qX1kKANn8995vOOh5S9AmF4ItGZcfbny0w28Eqy8AFh+GMnSDN4gqpmV2LvxBI9HibXZptGH3RVOMk82h1Mpw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/instructions@2.3.0': resolution: {integrity: sha512-PLMsmaIKu7hEAzyElrk2T7JJx4D+9eRwebhFZpy2PXziNSmFF929eRHKUsKqBFM3cYR1Yy3m6roBZfA+bGE/oQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/instructions@3.0.3': + resolution: {integrity: sha512-4csIi8YUDb5j/J+gDzmYtOvq7ZWLbCxj4t0xKn+fPrBk/FD2pK29KVT3Fu7j4Lh1/ojunQUP9X4NHwUexY3PnA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/keys@2.3.0': resolution: {integrity: sha512-ZVVdga79pNH+2pVcm6fr2sWz9HTwfopDVhYb0Lh3dh+WBmJjwkabXEIHey2rUES7NjFa/G7sV8lrUn/v8LDCCQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/keys@3.0.3': + resolution: {integrity: sha512-tp8oK9tMadtSIc4vF4aXXWkPd4oU5XPW8nf28NgrGDWGt25fUHIydKjkf2hPtMt9i1WfRyQZ33B5P3dnsNqcPQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/kit@2.3.0': resolution: {integrity: sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==} engines: {node: '>=20.18.0'} @@ -6550,6 +6630,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/nominal-types@3.0.3': + resolution: {integrity: sha512-aZavCiexeUAoMHRQg4s1AHkH3wscbOb70diyfjhwZVgFz1uUsFez7csPp9tNFkNolnadVb2gky7yBk3IImQJ6A==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/options@2.0.0-rc.1': resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==} peerDependencies: @@ -6579,24 +6665,48 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-api@3.0.3': + resolution: {integrity: sha512-Yym9/Ama62OY69rAZgbOCAy1QlqaWAyb0VlqFuwSaZV1pkFCCFSwWEJEsiN1n8pb2ZP+RtwNvmYixvWizx9yvA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-parsed-types@2.3.0': resolution: {integrity: sha512-B5pHzyEIbBJf9KHej+zdr5ZNAdSvu7WLU2lOUPh81KHdHQs6dEb310LGxcpCc7HVE8IEdO20AbckewDiAN6OCg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-parsed-types@3.0.3': + resolution: {integrity: sha512-/koM05IM2fU91kYDQxXil3VBNlOfcP+gXE0js1sdGz8KonGuLsF61CiKB5xt6u1KEXhRyDdXYLjf63JarL4Ozg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec-types@2.3.0': resolution: {integrity: sha512-xQsb65lahjr8Wc9dMtP7xa0ZmDS8dOE2ncYjlvfyw/h4mpdXTUdrSMi6RtFwX33/rGuztQ7Hwaid5xLNSLvsFQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec-types@3.0.3': + resolution: {integrity: sha512-A6Jt8SRRetnN3CeGAvGJxigA9zYRslGgWcSjueAZGvPX+MesFxEUjSWZCfl+FogVFvwkqfkgQZQbPAGZQFJQ6Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec@2.3.0': resolution: {integrity: sha512-fA2LMX4BMixCrNB2n6T83AvjZ3oUQTu7qyPLyt8gHQaoEAXs8k6GZmu6iYcr+FboQCjUmRPgMaABbcr9j2J9Sw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec@3.0.3': + resolution: {integrity: sha512-MZn5/8BebB6MQ4Gstw6zyfWsFAZYAyLzMK+AUf/rSfT8tPmWiJ/mcxnxqOXvFup/l6D67U8pyGpIoFqwCeZqqA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions-api@2.3.0': resolution: {integrity: sha512-9mCjVbum2Hg9KGX3LKsrI5Xs0KX390lS+Z8qB80bxhar6MJPugqIPH8uRgLhCW9GN3JprAfjRNl7our8CPvsPQ==} engines: {node: '>=20.18.0'} @@ -6628,24 +6738,48 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transformers@3.0.3': + resolution: {integrity: sha512-lzdaZM/dG3s19Tsk4mkJA5JBoS1eX9DnD7z62gkDwrwJDkDBzkAJT9aLcsYFfTmwTfIp6uU2UPgGYc97i1wezw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-transport-http@2.3.0': resolution: {integrity: sha512-HFKydmxGw8nAF5N+S0NLnPBDCe5oMDtI2RAmW8DMqP4U3Zxt2XWhvV1SNkAldT5tF0U1vP+is6fHxyhk4xqEvg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transport-http@3.0.3': + resolution: {integrity: sha512-bIXFwr2LR5A97Z46dI661MJPbHnPfcShBjFzOS/8Rnr8P4ho3j/9EUtjDrsqoxGJT3SLWj5OlyXAlaDAvVTOUQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-types@2.3.0': resolution: {integrity: sha512-O09YX2hED2QUyGxrMOxQ9GzH1LlEwwZWu69QbL4oYmIf6P5dzEEHcqRY6L1LsDVqc/dzAdEs/E1FaPrcIaIIPw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-types@3.0.3': + resolution: {integrity: sha512-petWQ5xSny9UfmC3Qp2owyhNU0w9SyBww4+v7tSVyXMcCC9v6j/XsqTeimH1S0qQUllnv0/FY83ohFaxofmZ6Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc@2.3.0': resolution: {integrity: sha512-ZWN76iNQAOCpYC7yKfb3UNLIMZf603JckLKOOLTHuy9MZnTN8XV6uwvDFhf42XvhglgUjGCEnbUqWtxQ9pa/pQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc@3.0.3': + resolution: {integrity: sha512-3oukAaLK78GegkKcm6iNmRnO4mFeNz+BMvA8T56oizoBNKiRVEq/6DFzVX/LkmZ+wvD601pAB3uCdrTPcC0YKQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/signers@2.3.0': resolution: {integrity: sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==} engines: {node: '>=20.18.0'} @@ -6694,12 +6828,24 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/transaction-messages@3.0.3': + resolution: {integrity: sha512-s+6NWRnBhnnjFWV4x2tzBzoWa6e5LiIxIvJlWwVQBFkc8fMGY04w7jkFh0PM08t/QFKeXBEWkyBDa/TFYdkWug==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transactions@2.3.0': resolution: {integrity: sha512-LnTvdi8QnrQtuEZor5Msje61sDpPstTVwKg4y81tNxDhiyomjuvnSNLAq6QsB9gIxUqbNzPZgOG9IU4I4/Uaug==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/transactions@3.0.3': + resolution: {integrity: sha512-iMX+n9j4ON7H1nKlWEbMqMOpKYC6yVGxKKmWHT1KdLRG7v+03I4DnDeFoI+Zmw56FA+7Bbne8jwwX60Q1vk/MQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/wallet-adapter-base@0.9.23': resolution: {integrity: sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==} engines: {node: '>=16'} @@ -7890,7 +8036,6 @@ packages: '@walletconnect/modal@2.7.0': resolution: {integrity: sha512-RQVt58oJ+rwqnPcIvRFeMGKuXb9qkgSmwz4noF8JZGUym3gUAzVs+uW2NQ1Owm9XOJAV+sANrtJ+VoVq1ftElw==} - deprecated: Please follow the migration guide on https://docs.reown.com/appkit/upgrade/wcm '@walletconnect/react-native-compat@2.17.3': resolution: {integrity: sha512-lHKwXKoB0rdDH1ukxUx7o86xosWbttWIHYMZ8tgAQC1k9VH3CZZCoBcHOAAX8iBzyb0n0UP3/9zRrOcJE5nz7Q==} @@ -8809,6 +8954,10 @@ packages: resolution: {integrity: sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==} engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chalk@5.6.2: + resolution: {integrity: sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + character-entities-html4@2.1.0: resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} @@ -16584,16 +16733,16 @@ snapshots: typescript: 5.8.3 optional: true - '@abstract-foundation/agw-react@1.6.4(pfuoymnekjwwwvphlum3lcxazm)': + '@abstract-foundation/agw-react@1.6.4(lfgxwuqm6efii3akecbct27dfa)': dependencies: '@abstract-foundation/agw-client': 1.6.2(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) '@privy-io/cross-app-connect': 0.2.2(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) - '@privy-io/react-auth': 2.17.3(@abstract-foundation/agw-client@1.8.5(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@types/react@19.1.8)(aws4fetch@1.0.20)(bs58@6.0.0)(bufferutil@4.0.9)(ioredis@5.6.1)(lit@3.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.25.75) + '@privy-io/react-auth': 2.17.3(@abstract-foundation/agw-client@1.8.5(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@types/react@19.1.8)(aws4fetch@1.0.20)(bs58@6.0.0)(bufferutil@4.0.9)(ioredis@5.6.1)(lit@3.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.25.75) '@tanstack/react-query': 5.81.5(react@19.1.0) react: 19.1.0 secp256k1: 5.0.1 viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - wagmi: 2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + wagmi: 2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) optionalDependencies: thirdweb: link:packages/thirdweb typescript: 5.8.3 @@ -16714,7 +16863,7 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sso-oidc': 3.592.0(@aws-sdk/client-sts@3.592.0) '@aws-sdk/client-sts': 3.592.0 '@aws-sdk/core': 3.592.0 '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) @@ -16760,7 +16909,7 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sso-oidc': 3.592.0(@aws-sdk/client-sts@3.592.0) '@aws-sdk/client-sts': 3.592.0 '@aws-sdk/core': 3.592.0 '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) @@ -16806,7 +16955,7 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sso-oidc': 3.592.0(@aws-sdk/client-sts@3.592.0) '@aws-sdk/client-sts': 3.592.0 '@aws-sdk/core': 3.592.0 '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) @@ -16853,7 +17002,7 @@ snapshots: transitivePeerDependencies: - aws-crt - '@aws-sdk/client-sso-oidc@3.592.0': + '@aws-sdk/client-sso-oidc@3.592.0(@aws-sdk/client-sts@3.592.0)': dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 @@ -16896,6 +17045,7 @@ snapshots: '@smithy/util-utf8': 3.0.0 tslib: 2.8.1 transitivePeerDependencies: + - '@aws-sdk/client-sts' - aws-crt '@aws-sdk/client-sso-oidc@3.840.0': @@ -17032,7 +17182,7 @@ snapshots: dependencies: '@aws-crypto/sha256-browser': 3.0.0 '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sso-oidc': 3.592.0(@aws-sdk/client-sts@3.592.0) '@aws-sdk/core': 3.592.0 '@aws-sdk/credential-provider-node': 3.592.0(@aws-sdk/client-sso-oidc@3.592.0)(@aws-sdk/client-sts@3.592.0) '@aws-sdk/middleware-host-header': 3.577.0 @@ -17478,7 +17628,7 @@ snapshots: '@aws-sdk/token-providers@3.587.0(@aws-sdk/client-sso-oidc@3.592.0)': dependencies: - '@aws-sdk/client-sso-oidc': 3.592.0 + '@aws-sdk/client-sso-oidc': 3.592.0(@aws-sdk/client-sts@3.592.0) '@aws-sdk/types': 3.577.0 '@smithy/property-provider': 3.1.11 '@smithy/shared-ini-file-loader': 3.1.12 @@ -21337,7 +21487,7 @@ snapshots: - typescript - utf-8-validate - '@privy-io/react-auth@2.17.3(@abstract-foundation/agw-client@1.8.5(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@types/react@19.1.8)(aws4fetch@1.0.20)(bs58@6.0.0)(bufferutil@4.0.9)(ioredis@5.6.1)(lit@3.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.25.75)': + '@privy-io/react-auth@2.17.3(@abstract-foundation/agw-client@1.8.5(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10))(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(@types/react@19.1.8)(aws4fetch@1.0.20)(bs58@6.0.0)(bufferutil@4.0.9)(ioredis@5.6.1)(lit@3.3.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.25.75)': dependencies: '@coinbase/wallet-sdk': 4.3.2 '@floating-ui/react': 0.26.28(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -21384,7 +21534,7 @@ snapshots: zustand: 5.0.7(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) optionalDependencies: '@abstract-foundation/agw-client': 1.8.5(abitype@1.0.8(typescript@5.8.3)(zod@3.25.75))(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) - '@solana/spl-token': 0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) + '@solana/spl-token': 0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10) '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) transitivePeerDependencies: - '@azure/app-configuration' @@ -24276,11 +24426,27 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/addresses@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 3.0.3(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/assertions@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/assertions@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 @@ -24309,6 +24475,11 @@ snapshots: '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/codecs-core@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24324,6 +24495,13 @@ snapshots: '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/codecs-data-structures@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/codecs-numbers@2.0.0-rc.1(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24337,11 +24515,18 @@ snapshots: '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/codecs-strings@2.0.0-rc.1(typescript@5.8.3)': + '@solana/codecs-numbers@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + + '@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) + fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.8.3 optional: true @@ -24353,13 +24538,21 @@ snapshots: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.8.3 - '@solana/codecs@2.0.0-rc.1(typescript@5.8.3)': + '@solana/codecs-strings@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.8.3 + + '@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.8.3) '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-strings': 2.0.0-rc.1(typescript@5.8.3) - '@solana/options': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/options': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - fastestsmallesttextencoderdecoder @@ -24389,20 +24582,40 @@ snapshots: commander: 14.0.0 typescript: 5.8.3 + '@solana/errors@3.0.3(typescript@5.8.3)': + dependencies: + chalk: 5.6.2 + commander: 14.0.0 + typescript: 5.8.3 + '@solana/fast-stable-stringify@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/fast-stable-stringify@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/functional@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/functional@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/instructions@2.3.0(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.3.0(typescript@5.8.3) '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/instructions@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/keys@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/assertions': 2.3.0(typescript@5.8.3) @@ -24414,6 +24627,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/keys@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 3.0.3(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24443,12 +24667,16 @@ snapshots: dependencies: typescript: 5.8.3 - '@solana/options@2.0.0-rc.1(typescript@5.8.3)': + '@solana/nominal-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) '@solana/codecs-data-structures': 2.0.0-rc.1(typescript@5.8.3) '@solana/codecs-numbers': 2.0.0-rc.1(typescript@5.8.3) - '@solana/codecs-strings': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs-strings': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/errors': 2.0.0-rc.1(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: @@ -24495,20 +24723,51 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-api@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-parsed-types@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/rpc-parsed-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-spec-types@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/rpc-spec-types@3.0.3(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-spec@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/rpc-spec@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + '@solana/rpc-subscriptions-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24568,6 +24827,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-transformers@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-transport-http@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24576,6 +24846,14 @@ snapshots: typescript: 5.8.3 undici-types: 7.16.0 + '@solana/rpc-transport-http@3.0.3(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + undici-types: 7.16.0 + '@solana/rpc-types@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24588,6 +24866,18 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-types@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24603,6 +24893,21 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/fast-stable-stringify': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/rpc-api': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-spec': 3.0.3(typescript@5.8.3) + '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-transformers': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-transport-http': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/signers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24617,30 +24922,30 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)': + '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/codecs': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript optional: true - '@solana/spl-token-metadata@0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)': + '@solana/spl-token-metadata@0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: - '@solana/codecs': 2.0.0-rc.1(typescript@5.8.3) + '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) transitivePeerDependencies: - fastestsmallesttextencoderdecoder - typescript optional: true - '@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)': + '@solana/spl-token@0.4.14(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 '@solana/buffer-layout-utils': 0.2.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) - '@solana/spl-token-group': 0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@solana/spl-token-group': 0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/spl-token-metadata': 0.1.6(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/web3.js': 1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10) buffer: 6.0.3 transitivePeerDependencies: @@ -24698,6 +25003,21 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transaction-messages@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/transactions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24716,6 +25036,24 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transactions@3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 3.0.3(typescript@5.8.3) + '@solana/codecs-data-structures': 3.0.3(typescript@5.8.3) + '@solana/codecs-numbers': 3.0.3(typescript@5.8.3) + '@solana/codecs-strings': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 3.0.3(typescript@5.8.3) + '@solana/functional': 3.0.3(typescript@5.8.3) + '@solana/instructions': 3.0.3(typescript@5.8.3) + '@solana/keys': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 3.0.3(typescript@5.8.3) + '@solana/rpc-types': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/wallet-standard-features': 1.3.0 @@ -26395,7 +26733,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@22.14.1)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -26513,7 +26851,7 @@ snapshots: - '@vue/composition-api' - vue - '@wagmi/connectors@5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': + '@wagmi/connectors@5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': dependencies: '@coinbase/wallet-sdk': 4.3.3 '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -26552,6 +26890,45 @@ snapshots: - utf-8-validate - zod + '@wagmi/connectors@5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': + dependencies: + '@coinbase/wallet-sdk': 4.3.3 + '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) + '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + '@walletconnect/ethereum-provider': 2.21.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + cbw-sdk: '@coinbase/wallet-sdk@3.9.3' + viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - ioredis + - react + - supports-color + - uploadthing + - utf-8-validate + - zod + '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': dependencies: eventemitter3: 5.0.1 @@ -26581,7 +26958,6 @@ snapshots: - immer - react - use-sync-external-store - optional: true '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@6.0.5)(zod@3.25.76))': dependencies: @@ -28776,6 +29152,8 @@ snapshots: chalk@5.5.0: {} + chalk@5.6.2: {} + character-entities-html4@2.1.0: {} character-entities-legacy@1.1.4: {} @@ -32656,7 +33034,7 @@ snapshots: log-symbols@6.0.0: dependencies: - chalk: 5.4.1 + chalk: 5.5.0 is-unicode-supported: 1.3.0 lokijs@1.5.12: {} @@ -37856,7 +38234,45 @@ snapshots: wagmi@2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): dependencies: '@tanstack/react-query': 5.81.5(react@19.1.0) - '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + react: 19.1.0 + use-sync-external-store: 1.4.0(react@19.1.0) + viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/query-core' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - supports-color + - uploadthing + - utf-8-validate + - zod + + wagmi@2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): + dependencies: + '@tanstack/react-query': 5.81.5(react@19.1.0) + '@wagmi/connectors': 5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) react: 19.1.0 use-sync-external-store: 1.4.0(react@19.1.0) From 409df8eef93819db43d807761f5a34eb66f0f70d Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Fri, 10 Oct 2025 10:57:34 +0530 Subject: [PATCH 02/10] end to end tests --- packages/vault-sdk/package.json | 138 +-- packages/vault-sdk/src/sdk.ts | 93 +-- packages/vault-sdk/src/types.ts | 795 +++++++++--------- packages/vault-sdk/test-solana.ts | 382 --------- packages/vault-sdk/tests/.env.example | 6 + packages/vault-sdk/tests/solana.test.ts | 512 ++++++++++++ packages/vault-sdk/vitest.config.ts | 14 + pnpm-lock.yaml | 1020 ++++++++++++++++++++--- 8 files changed, 1925 insertions(+), 1035 deletions(-) delete mode 100644 packages/vault-sdk/test-solana.ts create mode 100644 packages/vault-sdk/tests/.env.example create mode 100644 packages/vault-sdk/tests/solana.test.ts create mode 100644 packages/vault-sdk/vitest.config.ts diff --git a/packages/vault-sdk/package.json b/packages/vault-sdk/package.json index 918bfcac4ec..85fdec9234c 100644 --- a/packages/vault-sdk/package.json +++ b/packages/vault-sdk/package.json @@ -1,69 +1,73 @@ { - "author": "thirdweb eng ", - "bugs": { - "url": "https://github.com/thirdweb-dev/js/issues" - }, - "dependencies": { - "@noble/ciphers": "^1.2.1", - "@noble/curves": "1.8.2", - "@noble/hashes": "1.7.2", - "@solana/addresses": "^3.0.0", - "@solana/keys": "^3.0.0", - "@solana/transactions": "^3.0.0", - "@solana/rpc": "^3.0.0", - "abitype": "1.0.8", - "jose": "6.0.11" - }, - "devDependencies": { - "@biomejs/biome": "2.0.6", - "tsx": "^4.0.0", - "rimraf": "6.0.1" - }, - "engines": { - "node": ">=18" - }, - "exports": { - ".": { - "types": "./dist/types/exports/thirdweb.d.ts", - "import": "./dist/esm/exports/thirdweb.js", - "default": "./dist/cjs/exports/thirdweb.js" - }, - "./package.json": "./package.json" - }, - "files": [ - "dist/*", - "src/*" - ], - "license": "Apache-2.0", - "main": "./dist/cjs/exports/thirdweb.js", - "module": "./dist/esm/exports/thirdweb.js", - "name": "@thirdweb-dev/vault-sdk", - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/thirdweb-dev/js.git#main" - }, - "scripts": { - "build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types", - "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/cjs --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json", - "build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json", - "build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap", - "clean": "rimraf dist", - "test:solana": "tsx test-solana.ts", - "dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch", - "fix": "biome check ./src --fix", - "format": "biome format ./src --write", - "lint": "biome check ./src" - }, - "type": "module", - "types": "./dist/types/exports/thirdweb.d.ts", - "typings": "./dist/types/exports/thirdweb.d.ts", - "version": "0.0.3" + "author": "thirdweb eng ", + "bugs": { + "url": "https://github.com/thirdweb-dev/js/issues" + }, + "dependencies": { + "@noble/ciphers": "^1.2.1", + "@noble/curves": "1.8.2", + "@noble/hashes": "1.7.2", + "@solana/addresses": "^3.0.0", + "@solana/keys": "^3.0.0", + "@solana/rpc": "^3.0.0", + "@solana/transactions": "^3.0.0", + "abitype": "1.0.8", + "@solana/kit": "^4.0.0", + "jose": "6.0.11" + }, + "devDependencies": { + "@biomejs/biome": "2.0.6", + "@solana-program/system": "^0.8.1", + "bs58": "^6.0.0", + "rimraf": "6.0.1", + "tsx": "^4.0.0", + "vitest": "3.2.4" + }, + "engines": { + "node": ">=18" + }, + "exports": { + ".": { + "types": "./dist/types/exports/thirdweb.d.ts", + "import": "./dist/esm/exports/thirdweb.js", + "default": "./dist/cjs/exports/thirdweb.js" + }, + "./package.json": "./package.json" + }, + "files": [ + "dist/*", + "src/*" + ], + "license": "Apache-2.0", + "main": "./dist/cjs/exports/thirdweb.js", + "module": "./dist/esm/exports/thirdweb.js", + "name": "@thirdweb-dev/vault-sdk", + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + }, + "repository": { + "type": "git", + "url": "git+https://github.com/thirdweb-dev/js.git#main" + }, + "scripts": { + "build": "pnpm clean && pnpm build:cjs && pnpm build:esm && pnpm build:types", + "build:cjs": "tsc --project ./tsconfig.build.json --module commonjs --outDir ./dist/cjs --verbatimModuleSyntax false && printf '{\"type\":\"commonjs\"}' > ./dist/cjs/package.json", + "build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json", + "build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap", + "clean": "rimraf dist", + "test": "vitest", + "dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch", + "fix": "biome check ./src --fix", + "format": "biome format ./src --write", + "lint": "biome check ./src" + }, + "type": "module", + "types": "./dist/types/exports/thirdweb.d.ts", + "typings": "./dist/types/exports/thirdweb.d.ts", + "version": "0.0.3" } diff --git a/packages/vault-sdk/src/sdk.ts b/packages/vault-sdk/src/sdk.ts index 563fb8c1534..71082bd67b1 100644 --- a/packages/vault-sdk/src/sdk.ts +++ b/packages/vault-sdk/src/sdk.ts @@ -3,57 +3,16 @@ import { x25519 } from "@noble/curves/ed25519"; import { hkdf } from "@noble/hashes/hkdf"; import { sha256 } from "@noble/hashes/sha256"; import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils"; -import type { TypedData } from "abitype"; -import * as jose from "jose"; - -// Base58 encoding for Solana public keys -const BASE58_ALPHABET = - "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - -function base58Encode(bytes: number[] | Uint8Array): string { - const byteArray = Array.isArray(bytes) ? new Uint8Array(bytes) : bytes; - if (byteArray.length === 0) return ""; - - // Convert to big integer - let num = 0n; - for (const byte of byteArray) { - num = num * 256n + BigInt(byte); - } - - // Convert to base58 - let result = ""; - while (num > 0n) { - const remainder = Number(num % 58n); - result = BASE58_ALPHABET[remainder] + result; - num = num / 58n; - } - - // Add leading zeros - for (const byte of byteArray) { - if (byte === 0) { - result = BASE58_ALPHABET[0] + result; - } else { - break; - } - } - - return result; -} - -// Helper function to process Solana account data -function _processSolanaAccountData(accountData: any): any { - if (!accountData) return accountData; - - // If we have a pubkey byte array, convert it to base58 string - if (accountData.pubkey && Array.isArray(accountData.pubkey)) { - accountData.publicKey = base58Encode(accountData.pubkey); - accountData.address = accountData.publicKey; // Use the same value for address - } - - return accountData; -} +import { + address, + getBase58Encoder, + getTransactionDecoder, + getTransactionEncoder, +} from "@solana/kit"; +import type { TypedData } from "abitype"; +import * as jose from "jose"; import type { CheckedSignTypedDataPayload, CreateAccessTokenPayload, @@ -540,6 +499,42 @@ export function signSolanaTransaction({ }); } +/** + * Reconstruct a signed solana transaction from the vault signature using @solana/kit + */ +export function reconstructSolanaSignedTransaction( + base64Transaction: string, + base58Signature: string, + signerPubkey: string, +): Uint8Array { + // Decode the base64 transaction into bytes + const base64TransactionBytes = new Uint8Array( + Buffer.from(base64Transaction, "base64"), + ); + // Decode the transaction to get its structure + const transactionDecoder = getTransactionDecoder(); + const transaction = transactionDecoder.decode(base64TransactionBytes); + + // Decode the base58 signature to bytes + const base58Encoder = getBase58Encoder(); + const signatureBytes = base58Encoder.encode(base58Signature); + + // Add the signature to the transaction + const signedTransaction = { + ...transaction, + signatures: { + ...transaction.signatures, + [address(signerPubkey)]: signatureBytes, + }, + }; + + // Re-encode the signed transaction + const transactionEncoder = getTransactionEncoder(); + const signedTransactionBytes = transactionEncoder.encode(signedTransaction); + + return new Uint8Array(signedTransactionBytes); +} + export function signSolanaMessage({ client, request: options, diff --git a/packages/vault-sdk/src/types.ts b/packages/vault-sdk/src/types.ts index a014a4e4c6c..64d60c00ff1 100644 --- a/packages/vault-sdk/src/types.ts +++ b/packages/vault-sdk/src/types.ts @@ -1,33 +1,33 @@ import type { - Address, - TypedData, - TypedDataDomain, - TypedDataToPrimitiveTypes, + Address, + TypedData, + TypedDataDomain, + TypedDataToPrimitiveTypes, } from "abitype"; import type { EthereumTypedTransaction } from "./transaction-types.js"; export type Prettify = { - [K in keyof T]: T[K]; + [K in keyof T]: T[K]; } & {}; // Encrypted types export type EncryptedPayload = { - ephemeralPublicKey: string; - nonce: string; - ciphertext: string; + ephemeralPublicKey: string; + nonce: string; + ciphertext: string; }; // ========== Authentication Types ========== type AdminKeyAuth = { - adminKey: string; + adminKey: string; }; type AccessTokenAuth = { - accessToken: string; + accessToken: string; }; type SessionTokenAuth = { - sessionToken: string; + sessionToken: string; }; // Regular Auth union (excluding RotationCodeAuth) @@ -35,7 +35,7 @@ export type Auth = AdminKeyAuth | AccessTokenAuth | SessionTokenAuth; // Separate RotationCodeAuth (used only for rotation) type RotationCodeAuth = { - rotationCode: string; + rotationCode: string; }; // ========== Base Types ========== @@ -45,164 +45,164 @@ type Bytes = string; // e.g., "0x..." type BigNumberString = string; // String representation of U256/I256 type UnencryptedError = { - message: string; - status: number; - type: string; - details?: string; + message: string; + status: number; + type: string; + details?: string; }; export type UnencryptedErrorResponse = { - error: UnencryptedError; + error: UnencryptedError; }; type EncryptedError = { - code: string; - message: string; - details?: string; + code: string; + message: string; + details?: string; }; type GenericSuccessResponse = { - success: true; - data: Data; - error: null; + success: true; + data: Data; + error: null; }; type GenericErrorResponse = { - success: false; - data: null; - error: EncryptedError | UnencryptedError; + success: false; + data: null; + error: EncryptedError | UnencryptedError; }; export type VaultError = EncryptedError | UnencryptedError; type GenericResponse = - | GenericSuccessResponse - | GenericErrorResponse; + | GenericSuccessResponse + | GenericErrorResponse; // ========== Payload Type ========== export type OmitNever = { - [K in keyof T as T[K] extends never ? never : K]: T[K]; + [K in keyof T as T[K] extends never ? never : K]: T[K]; }; export type GenericPayload< - T extends { - operation: string; - auth?: Auth | RotationCodeAuth | never; - options?: Record | never; - data: unknown; - }, + T extends { + operation: string; + auth?: Auth | RotationCodeAuth | never; + options?: Record | never; + data: unknown; + }, > = { - input: OmitNever<{ - operation: T["operation"]; - options: T["options"]; - auth: T["auth"]; - }>; - output: GenericResponse; + input: OmitNever<{ + operation: T["operation"]; + options: T["options"]; + auth: T["auth"]; + }>; + output: GenericResponse; }; // ========== Options Types ========== type CreateServiceAccountOptions = { - metadata: Record; + metadata: Record; }; type MetadataValue = string | number | boolean; type CreateEoaOptions = { - metadata: Record; + metadata: Record; }; type GetEoasOptions = { - page?: number; - pageSize?: number; + page?: number; + pageSize?: number; }; type PingOptions = { - message: string; + message: string; }; type SignTransactionOptions = { - transaction: EthereumTypedTransaction; - from: string; + transaction: EthereumTypedTransaction; + from: string; }; export type SignAuthorizationOptions = { - from: Address; - authorization: Authorization; // Use the defined type + from: Address; + authorization: Authorization; // Use the defined type }; export type SignStructuredMessageOptions = { - from: Address; - structuredMessage: StructuredMessageInput; // Use the defined type - chainId?: number; // Keep as number for ChainId + from: Address; + structuredMessage: StructuredMessageInput; // Use the defined type + chainId?: number; // Keep as number for ChainId }; export type GetAccessTokensOptions = { - page?: number; - pageSize?: number; + page?: number; + pageSize?: number; }; type SignMessageOptions = { - message: string; - from: string; - chainId?: number; - format?: "text" | "hex"; + message: string; + from: string; + chainId?: number; + format?: "text" | "hex"; }; // ========== Solana Options Types ========== // Solana message type that's compatible with both Kit and our Rust serialization export type SolanaVersionedMessage = { - version: "legacy" | "v0"; - header: { - numRequiredSignatures: number; - numReadonlySignedAccounts: number; - numReadonlyUnsignedAccounts: number; - }; - staticAccountKeys: string[]; // Use string instead of SolanaAddress for simplicity - recentBlockhash: string; - instructions: Array<{ - programIdIndex: number; - accountKeyIndexes: number[]; - data: Uint8Array; - }>; - addressTableLookups?: Array<{ - accountKey: string; // Use string instead of SolanaAddress - writableIndexes: number[]; - readonlyIndexes: number[]; - }>; + version: "legacy" | "v0"; + header: { + numRequiredSignatures: number; + numReadonlySignedAccounts: number; + numReadonlyUnsignedAccounts: number; + }; + staticAccountKeys: string[]; // Use string instead of SolanaAddress for simplicity + recentBlockhash: string; + instructions: Array<{ + programIdIndex: number; + accountKeyIndexes: number[]; + data: Uint8Array; + }>; + addressTableLookups?: Array<{ + accountKey: string; // Use string instead of SolanaAddress + writableIndexes: number[]; + readonlyIndexes: number[]; + }>; }; type CreateSolanaAccountOptions = { - metadata: Record; + metadata: Record; }; type GetSolanaAccountsOptions = { - page?: number; - pageSize?: number; + page?: number; + pageSize?: number; }; type SignSolanaTransactionOptions = { - message: SolanaVersionedMessage; - from: string; // Use string for Solana public key + transaction: string; // Base64 encoded VersionedTransaction + from: string; // Use string for Solana public key }; type SignSolanaMessageOptions = { - message: string; - from: string; // Use string for Solana public key - format?: "text" | "hex"; + message: string; + from: string; // Use string for Solana public key + format?: "text" | "hex"; }; type CheckedSignTypedDataOptions< - Types extends TypedData, - PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, > = { - typedData: { - domain: TypedDataDomain; - types: Types; - primaryType: PrimaryType; - message: TypedDataToPrimitiveTypes[PrimaryType]; - }; - from: string; + typedData: { + domain: TypedDataDomain; + types: Types; + primaryType: PrimaryType; + message: TypedDataToPrimitiveTypes[PrimaryType]; + }; + from: string; }; // biome-ignore lint/suspicious/noExplicitAny: we truly want to accept anything here @@ -212,486 +212,483 @@ type SignedTypedDataOptions = CheckedSignTypedDataOptions; // Corresponds to Rust UserOperationV06Input export type UserOperationV06Input = { - sender: Address; - nonce: BigNumberString; // U256 - initCode?: Bytes; // Optional due to #[serde(default)] - callData: Bytes; - callGasLimit: BigNumberString; // U256 - verificationGasLimit: BigNumberString; // U256 - preVerificationGas: BigNumberString; // U256 - maxFeePerGas: BigNumberString; // U256 - maxPriorityFeePerGas: BigNumberString; // U256 - paymasterAndData?: Bytes; // Optional due to #[serde(default)] - signature?: Bytes; // Optional due to #[serde(default)] - entrypoint?: Address; // Optional due to #[serde(default = ...)] + sender: Address; + nonce: BigNumberString; // U256 + initCode?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymasterAndData?: Bytes; // Optional due to #[serde(default)] + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] }; // Corresponds to Rust UserOperationV07Input export type UserOperationV07Input = { - sender: Address; - nonce: BigNumberString; // U256 - factory?: Address; // Optional due to #[serde(default)] - factoryData?: Bytes; // Optional due to #[serde(default)] - callData: Bytes; - callGasLimit: BigNumberString; // U256 - verificationGasLimit: BigNumberString; // U256 - preVerificationGas: BigNumberString; // U256 - maxFeePerGas: BigNumberString; // U256 - maxPriorityFeePerGas: BigNumberString; // U256 - paymaster?: Address; // Optional due to #[serde(default)] - paymasterData?: Bytes; // Optional due to #[serde(default)] - Assuming default is empty bytes - paymasterVerificationGasLimit?: BigNumberString; // U256 - Assuming default is 0 - paymasterPostOpGasLimit?: BigNumberString; // U256 - Assuming default is 0 - signature?: Bytes; // Optional due to #[serde(default)] - entrypoint?: Address; // Optional due to #[serde(default = ...)] + sender: Address; + nonce: BigNumberString; // U256 + factory?: Address; // Optional due to #[serde(default)] + factoryData?: Bytes; // Optional due to #[serde(default)] + callData: Bytes; + callGasLimit: BigNumberString; // U256 + verificationGasLimit: BigNumberString; // U256 + preVerificationGas: BigNumberString; // U256 + maxFeePerGas: BigNumberString; // U256 + maxPriorityFeePerGas: BigNumberString; // U256 + paymaster?: Address; // Optional due to #[serde(default)] + paymasterData?: Bytes; // Optional due to #[serde(default)] - Assuming default is empty bytes + paymasterVerificationGasLimit?: BigNumberString; // U256 - Assuming default is 0 + paymasterPostOpGasLimit?: BigNumberString; // U256 - Assuming default is 0 + signature?: Bytes; // Optional due to #[serde(default)] + entrypoint?: Address; // Optional due to #[serde(default = ...)] }; // Corresponds to Rust StructuredMessageInput enum export type StructuredMessageInput = - | { useropV06: UserOperationV06Input } - | { useropV07: UserOperationV07Input }; + | { useropV06: UserOperationV06Input } + | { useropV07: UserOperationV07Input }; // ========== Policy Types ========== type RegexRule = { - pattern: string; + pattern: string; }; type NumberRuleOp = "greaterThan" | "lessThan" | "equalTo"; type NumberRule = { - op: NumberRuleOp; - value: number | BigNumberString; + op: NumberRuleOp; + value: number | BigNumberString; }; type Rule = NumberRule | RegexRule; type MetadataRule = { - key: string; - rule: Rule; + key: string; + rule: Rule; }; // ========== Policy Rule Structs ========== // Corresponds to Rust UserOperationV06Rules export type UserOperationV06Rules = { - sender?: Rule; - nonce?: Rule; - initCode?: Rule; - callData?: Rule; - callGasLimit?: Rule; - verificationGasLimit?: Rule; - preVerificationGas?: Rule; - maxFeePerGas?: Rule; - maxPriorityFeePerGas?: Rule; - paymasterAndData?: Rule; - chainId?: Rule; - entrypoint?: Rule; // Optional, but Rust has a default func + sender?: Rule; + nonce?: Rule; + initCode?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymasterAndData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func }; // Corresponds to Rust UserOperationV07Rules export type UserOperationV07Rules = { - sender?: Rule; - nonce?: Rule; - factory?: Rule; - factoryData?: Rule; - callData?: Rule; - callGasLimit?: Rule; - verificationGasLimit?: Rule; - preVerificationGas?: Rule; - maxFeePerGas?: Rule; - maxPriorityFeePerGas?: Rule; - paymaster?: Rule; - paymasterVerificationGasLimit?: Rule; - paymasterPostOpGasLimit?: Rule; - paymasterData?: Rule; - chainId?: Rule; - entrypoint?: Rule; // Optional, but Rust has a default func + sender?: Rule; + nonce?: Rule; + factory?: Rule; + factoryData?: Rule; + callData?: Rule; + callGasLimit?: Rule; + verificationGasLimit?: Rule; + preVerificationGas?: Rule; + maxFeePerGas?: Rule; + maxPriorityFeePerGas?: Rule; + paymaster?: Rule; + paymasterVerificationGasLimit?: Rule; + paymasterPostOpGasLimit?: Rule; + paymasterData?: Rule; + chainId?: Rule; + entrypoint?: Rule; // Optional, but Rust has a default func }; // Corresponds to Rust SignAuthorizationRules export type SignAuthorizationRules = { - chainId?: Rule; - nonce?: Rule; - address?: Rule; + chainId?: Rule; + nonce?: Rule; + address?: Rule; }; export type PolicyComponent = - | { - type: "eoa:create"; - requiredMetadataPatterns?: MetadataRule[]; - allowedMetadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:read"; - metadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:signTransaction"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - payloadPatterns: Record; - } - | { - type: "eoa:signMessage"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - chainId?: number; - messagePattern?: string; - } - | { - type: "eoa:signTypedData"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - } - | { - type: "eoa:signAuthorization"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - payloadPatterns?: SignAuthorizationRules; - } - | { - type: "eoa:signStructuredMessage"; - allowlist?: Address[]; - metadataPatterns?: MetadataRule[]; - // Define how UserOp rules are applied, e.g., separate for v6/v7 - structuredPatterns: { - useropV06?: UserOperationV06Rules; - useropV07?: UserOperationV07Rules; - }; - } - | { - type: "solana:create"; - requiredMetadataPatterns?: MetadataRule[]; - allowedMetadataPatterns?: MetadataRule[]; - } - | { - type: "solana:read"; - metadataPatterns?: MetadataRule[]; - } - | { - type: "solana:signTransaction"; - allowlist?: string[]; // Use string for Solana addresses - metadataPatterns?: MetadataRule[]; - payloadPatterns?: Record; - requiredCosigners?: string[]; // Use string for Solana addresses - } - | { - type: "solana:signMessage"; - allowlist?: string[]; // Use string for Solana addresses - metadataPatterns?: MetadataRule[]; - messagePattern?: string; - } - | { - type: "accessToken:read"; - metadataPatterns?: MetadataRule[]; - revealSensitive: boolean; - }; + | { + type: "eoa:create"; + requiredMetadataPatterns?: MetadataRule[]; + allowedMetadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:read"; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signTransaction"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns: Record; + } + | { + type: "eoa:signMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + chainId?: number; + messagePattern?: string; + } + | { + type: "eoa:signTypedData"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + } + | { + type: "eoa:signAuthorization"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + payloadPatterns?: SignAuthorizationRules; + } + | { + type: "eoa:signStructuredMessage"; + allowlist?: Address[]; + metadataPatterns?: MetadataRule[]; + // Define how UserOp rules are applied, e.g., separate for v6/v7 + structuredPatterns: { + useropV06?: UserOperationV06Rules; + useropV07?: UserOperationV07Rules; + }; + } + | { + type: "solana:create"; + requiredMetadataPatterns?: MetadataRule[]; + allowedMetadataPatterns?: MetadataRule[]; + } + | { + type: "solana:read"; + metadataPatterns?: MetadataRule[]; + } + | { + type: "solana:signTransaction"; + allowlist?: string[]; // Use string for Solana addresses + metadataPatterns?: MetadataRule[]; + payloadPatterns?: Record; + requiredCosigners?: string[]; // Use string for Solana addresses + } + | { + type: "solana:signMessage"; + allowlist?: string[]; // Use string for Solana addresses + metadataPatterns?: MetadataRule[]; + messagePattern?: string; + } + | { + type: "accessToken:read"; + metadataPatterns?: MetadataRule[]; + revealSensitive: boolean; + }; type OwnerType = string; // Define based on your eoa models type CreateAccessTokenOptions = { - policies: PolicyComponent[]; - expiresAt: string; // ISO date string - metadata: Record; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; }; type RevokeAccessTokenOptions = { - id: string; // UUID + id: string; // UUID }; // ========== Authorization Types ========== // Corresponds to Rust Authorization struct export type Authorization = { - chainId: BigNumberString; // U256 - address: Address; - nonce: number; // u64 + chainId: BigNumberString; // U256 + address: Address; + nonce: number; // u64 }; // Corresponds to Rust SignedAuthorization struct // Merges Authorization fields due to #[serde(flatten)] export type SignedAuthorization = Authorization & { - yParity: number; // U8 (typically 0 or 1) - r: BigNumberString; // U256 - s: BigNumberString; // U256 + yParity: number; // U8 (typically 0 or 1) + r: BigNumberString; // U256 + s: BigNumberString; // U256 }; // ========== Response Data Types ========== type PingData = { - timestamp: number; - pong: string; + timestamp: number; + pong: string; }; type CreateServiceAccountData = { - id: string; // UUID - adminKey: string; - rotationCode: string; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + adminKey: string; + rotationCode: string; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type GetServiceAccountData = { - id: string; // UUID - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type RotateServiceAccountData = { - newAdminKey: string; - newRotationCode: string; + newAdminKey: string; + newRotationCode: string; }; type EoaData = { - id: string; // UUID - address: string; - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string + id: string; // UUID + address: string; + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string }; type GetEoasData = { - items: EoaData[]; - page: number; - pageSize: number; - totalRecords: number; + items: EoaData[]; + page: number; + pageSize: number; + totalRecords: number; }; type SignTransactionData = { - signature: string; + signature: string; }; type SignMessageData = { - signature: string; + signature: string; }; // ========== Solana Data Types ========== type CreateSolanaAccountData = { - address: string; // Use string for Solana address - publicKey: string; // Base58 encoded - pubkey?: number[]; // Raw byte array from vault (for compatibility) - metadata: Record; - createdAt: string; - updatedAt: string; + pubkey: string; + metadata: Record; + createdAt: string; + updatedAt: string; }; type GetSolanaAccountsData = { - accounts: CreateSolanaAccountData[]; - totalCount: number; - page: number; - pageSize: number; + accounts: CreateSolanaAccountData[]; + totalCount: number; + page: number; + pageSize: number; }; type SignSolanaTransactionData = { - signature: string; // Base58 encoded signature - signerPubkey: string; // Use string for Solana public key + signature: string; // Base58 encoded signature + signerPubkey: string; // Use string for Solana public key }; type SignSolanaMessageData = { - signature: string; // Base58 encoded signature - signedMessage: string; + signature: string; // Base58 encoded signature }; type SignTypedDataData = { - signature: string; + signature: string; }; export type AccessTokenData = { - accessToken: string; - id: string; // UUID - issuerId: string; // UUID - issuerType: OwnerType; - policies: PolicyComponent[]; - expiresAt: string; // ISO date string - metadata: Record; - createdAt: string; // ISO date string - updatedAt: string; // ISO date string - /** - * If nullish then token hasn't been explicitly revoked, otherwise the ISO date string of the revocation. - * Note that an access token will be "implicitly" revoked if the token issuer account gets rotated. Check the isRotated field for this - */ - revokedAt?: string; // ISO date string - /** - * Reflects whether the issuer of this token has "rotated" their account, which implicitly revokes the token, but is not tracked by the revokedAt? field. - */ - isRotated: boolean; + accessToken: string; + id: string; // UUID + issuerId: string; // UUID + issuerType: OwnerType; + policies: PolicyComponent[]; + expiresAt: string; // ISO date string + metadata: Record; + createdAt: string; // ISO date string + updatedAt: string; // ISO date string + /** + * If nullish then token hasn't been explicitly revoked, otherwise the ISO date string of the revocation. + * Note that an access token will be "implicitly" revoked if the token issuer account gets rotated. Check the isRotated field for this + */ + revokedAt?: string; // ISO date string + /** + * Reflects whether the issuer of this token has "rotated" their account, which implicitly revokes the token, but is not tracked by the revokedAt? field. + */ + isRotated: boolean; }; // Update SignAuthorizationData to use the defined SignedAuthorization type export type SignAuthorizationData = { - signedAuthorization: SignedAuthorization; // Use the defined type + signedAuthorization: SignedAuthorization; // Use the defined type }; // Add SignStructuredMessageData (as defined previously) export type SignStructuredMessageData = { - signature: Bytes; - message: string; // This likely represents the UserOp hash in Rust + signature: Bytes; + message: string; // This likely represents the UserOp hash in Rust }; // Add GetAccessTokensData (as defined previously) export type GetAccessTokensData = { - items: AccessTokenData[]; - page: number; - pageSize: number; - totalRecords: number; // Rust uses u64, TS uses number + items: AccessTokenData[]; + page: number; + pageSize: number; + totalRecords: number; // Rust uses u64, TS uses number }; // ========== Operation Payloads ========== export type PingPayload = GenericPayload<{ - operation: "ping"; - options: PingOptions; - auth: never; - data: PingData; + operation: "ping"; + options: PingOptions; + auth: never; + data: PingData; }>; export type CreateServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:create"; - options: CreateServiceAccountOptions; - auth: never; - data: CreateServiceAccountData; + operation: "serviceAccount:create"; + options: CreateServiceAccountOptions; + auth: never; + data: CreateServiceAccountData; }>; export type GetServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:get"; - options: never; - auth: Auth; - data: GetServiceAccountData; + operation: "serviceAccount:get"; + options: never; + auth: Auth; + data: GetServiceAccountData; }>; export type RotateServiceAccountPayload = GenericPayload<{ - operation: "serviceAccount:rotate"; - options: never; - auth: RotationCodeAuth; // Only accepts RotationCodeAuth - data: RotateServiceAccountData; + operation: "serviceAccount:rotate"; + options: never; + auth: RotationCodeAuth; // Only accepts RotationCodeAuth + data: RotateServiceAccountData; }>; export type CreateEoaPayload = GenericPayload<{ - operation: "eoa:create"; - auth: Auth; - options: CreateEoaOptions; - data: EoaData; + operation: "eoa:create"; + auth: Auth; + options: CreateEoaOptions; + data: EoaData; }>; export type ListEoaPayload = GenericPayload<{ - operation: "eoa:list"; - auth: Auth; - options: GetEoasOptions; - data: GetEoasData; + operation: "eoa:list"; + auth: Auth; + options: GetEoasOptions; + data: GetEoasData; }>; export type SignTransactionPayload = GenericPayload<{ - operation: "eoa:signTransaction"; - auth: Auth; - options: SignTransactionOptions; - data: SignTransactionData; + operation: "eoa:signTransaction"; + auth: Auth; + options: SignTransactionOptions; + data: SignTransactionData; }>; export type SignAuthorizationPayload = GenericPayload<{ - operation: "eoa:signAuthorization"; - auth: Auth; // Assuming Auth is defined as before - options: SignAuthorizationOptions; - data: SignAuthorizationData; + operation: "eoa:signAuthorization"; + auth: Auth; // Assuming Auth is defined as before + options: SignAuthorizationOptions; + data: SignAuthorizationData; }>; // Add SignStructuredMessagePayload (using defined types) export type SignStructuredMessagePayload = GenericPayload<{ - operation: "eoa:signStructuredMessage"; - auth: Auth; // Assuming Auth is defined as before - options: SignStructuredMessageOptions; - data: SignStructuredMessageData; + operation: "eoa:signStructuredMessage"; + auth: Auth; // Assuming Auth is defined as before + options: SignStructuredMessageOptions; + data: SignStructuredMessageData; }>; export type CheckedSignTypedDataPayload< - Types extends TypedData, - PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types | "EIP712Domain" = keyof Types, > = GenericPayload<{ - operation: "eoa:signTypedData"; - auth: Auth; - options: CheckedSignTypedDataOptions; - data: SignTypedDataData; + operation: "eoa:signTypedData"; + auth: Auth; + options: CheckedSignTypedDataOptions; + data: SignTypedDataData; }>; export type SignTypedDataPayload = GenericPayload<{ - operation: "eoa:signTypedData"; - auth: Auth; - options: SignedTypedDataOptions; - data: SignTypedDataData; + operation: "eoa:signTypedData"; + auth: Auth; + options: SignedTypedDataOptions; + data: SignTypedDataData; }>; export type SignMessagePayload = GenericPayload<{ - operation: "eoa:signMessage"; - auth: Auth; - options: SignMessageOptions; - data: SignMessageData; + operation: "eoa:signMessage"; + auth: Auth; + options: SignMessageOptions; + data: SignMessageData; }>; export type CreateAccessTokenPayload = GenericPayload<{ - operation: "accessToken:create"; - auth: Auth; - options: CreateAccessTokenOptions; - data: AccessTokenData; + operation: "accessToken:create"; + auth: Auth; + options: CreateAccessTokenOptions; + data: AccessTokenData; }>; // Add ListAccessTokensPayload (using defined types) export type ListAccessTokensPayload = GenericPayload<{ - operation: "accessToken:list"; - auth: Auth; - data: GetAccessTokensData; + operation: "accessToken:list"; + auth: Auth; + data: GetAccessTokensData; }>; export type RevokeAccessTokenPayload = GenericPayload<{ - operation: "accessToken:revoke"; - auth: Auth; - options: RevokeAccessTokenOptions; - data: AccessTokenData; + operation: "accessToken:revoke"; + auth: Auth; + options: RevokeAccessTokenOptions; + data: AccessTokenData; }>; // ========== Solana Payload Types ========== export type CreateSolanaAccountPayload = GenericPayload<{ - operation: "solana:create"; - auth: Auth; - options: CreateSolanaAccountOptions; - data: CreateSolanaAccountData; + operation: "solana:create"; + auth: Auth; + options: CreateSolanaAccountOptions; + data: CreateSolanaAccountData; }>; export type ListSolanaAccountsPayload = GenericPayload<{ - operation: "solana:list"; - auth: Auth; - options: GetSolanaAccountsOptions; - data: GetSolanaAccountsData; + operation: "solana:list"; + auth: Auth; + options: GetSolanaAccountsOptions; + data: GetSolanaAccountsData; }>; export type SignSolanaTransactionPayload = GenericPayload<{ - operation: "solana:signTransaction"; - auth: Auth; - options: SignSolanaTransactionOptions; - data: SignSolanaTransactionData; + operation: "solana:signTransaction"; + auth: Auth; + options: SignSolanaTransactionOptions; + data: SignSolanaTransactionData; }>; export type SignSolanaMessagePayload = GenericPayload<{ - operation: "solana:signMessage"; - auth: Auth; - options: SignSolanaMessageOptions; - data: SignSolanaMessageData; + operation: "solana:signMessage"; + auth: Auth; + options: SignSolanaMessageOptions; + data: SignSolanaMessageData; }>; // ========== Union of all payloads ========== export type Payload = - | PingPayload - | CreateServiceAccountPayload - | GetServiceAccountPayload - | RotateServiceAccountPayload - | CreateEoaPayload - | ListEoaPayload - | SignTransactionPayload - | SignMessagePayload - | SignTypedDataPayload - | CreateAccessTokenPayload - | RevokeAccessTokenPayload - | SignAuthorizationPayload - | SignStructuredMessagePayload - | ListAccessTokensPayload - | CreateSolanaAccountPayload - | ListSolanaAccountsPayload - | SignSolanaTransactionPayload - | SignSolanaMessagePayload; + | PingPayload + | CreateServiceAccountPayload + | GetServiceAccountPayload + | RotateServiceAccountPayload + | CreateEoaPayload + | ListEoaPayload + | SignTransactionPayload + | SignMessagePayload + | SignTypedDataPayload + | CreateAccessTokenPayload + | RevokeAccessTokenPayload + | SignAuthorizationPayload + | SignStructuredMessagePayload + | ListAccessTokensPayload + | CreateSolanaAccountPayload + | ListSolanaAccountsPayload + | SignSolanaTransactionPayload + | SignSolanaMessagePayload; diff --git a/packages/vault-sdk/test-solana.ts b/packages/vault-sdk/test-solana.ts deleted file mode 100644 index 46a982a38f0..00000000000 --- a/packages/vault-sdk/test-solana.ts +++ /dev/null @@ -1,382 +0,0 @@ -#!/usr/bin/env tsx - -/** - * Comprehensive Solana Integration Test - * Tests the vault SDK with Solana operations - */ - -import { - createServiceAccount, - createSolanaAccount, - createVaultClient, - listSolanaAccounts, - signSolanaMessage, - signSolanaTransaction, - type VaultClient, -} from "./src/exports/thirdweb.js"; -// Vault SDK imports -import type { SolanaVersionedMessage } from "./src/types.js"; - -const VAULT_URL = "http://localhost:3000"; - -async function main(): Promise { - console.log("🚀 Starting Solana Integration Test...\n"); - console.log("🔧 Configuration:"); - console.log(` Vault URL: ${VAULT_URL}`); - console.log(` Node version: ${process.version}`); - console.log(` Platform: ${process.platform}\n`); - - // Test basic connectivity - console.log("🔍 Testing vault connectivity..."); - try { - const response = await fetch(`${VAULT_URL}/health`, { - method: "GET", - headers: { "Content-Type": "application/json" }, - }); - console.log(` Health check status: ${response.status}`); - console.log(` Health check ok: ${response.ok}`); - - if (response.ok) { - const healthData = await response.text(); - console.log(` Health response: ${healthData}`); - } - } catch (healthError) { - console.warn( - "⚠️ Health check failed:", - healthError instanceof Error ? healthError.message : healthError, - ); - console.warn(" Continuing with test anyway..."); - } - console.log(); - - try { - // Step 1: Create Vault Client - console.log("📡 Creating vault client..."); - console.log(` Connecting to: ${VAULT_URL}`); - - const vaultClient: VaultClient = await createVaultClient({ - baseUrl: VAULT_URL, - }); - - console.log("✅ Vault client created successfully"); - console.log(` Client type: ${typeof vaultClient}`); - console.log(` Client keys: ${Object.keys(vaultClient)}\n`); - - // Step 2: Create Service Account - console.log("👤 Creating service account..."); - console.log( - " Request payload:", - JSON.stringify( - { - options: { - metadata: { - name: "Solana Test Service Account", - description: "Testing Solana integration", - }, - }, - }, - null, - 2, - ), - ); - - const serviceAccountResult = await createServiceAccount({ - client: vaultClient, - request: { - options: { - metadata: { - name: "Solana Test Service Account", - description: "Testing Solana integration", - }, - }, - }, - }); - - console.log("✅ Service account response received"); - console.log( - " Response structure:", - JSON.stringify(serviceAccountResult, null, 2), - ); - console.log(" Service account ID:", serviceAccountResult.data?.id); - console.log(" Admin key present:", !!serviceAccountResult.data?.adminKey); - console.log( - " Admin key length:", - serviceAccountResult.data?.adminKey?.length || 0, - "\n", - ); - - const adminKey: string = serviceAccountResult.data?.adminKey || ""; - if (!adminKey) { - console.error("❌ No admin key in response!"); - console.error( - " Full response:", - JSON.stringify(serviceAccountResult, null, 2), - ); - throw new Error("Failed to get admin key from service account creation"); - } - - // Step 3: Create First Solana Account - console.log("🌟 Creating first Solana account..."); - console.log(" Using admin key:", `${adminKey.substring(0, 10)}...`); - console.log( - " Request payload:", - JSON.stringify( - { - auth: { adminKey: `${adminKey.substring(0, 10)}...` }, - options: { - metadata: { - name: "Test Account 1", - purpose: "Primary test account", - }, - }, - }, - null, - 2, - ), - ); - - const solanaAccount1 = await createSolanaAccount({ - client: vaultClient, - request: { - auth: { adminKey }, - options: { - metadata: { - name: "Test Account 1", - purpose: "Primary test account", - }, - }, - }, - }); - - console.log("✅ First Solana account response received"); - console.log( - " Response structure:", - JSON.stringify(solanaAccount1, null, 2), - ); - console.log(" Account address:", solanaAccount1.data?.address); - console.log(" Public key:", solanaAccount1.data?.publicKey); - console.log( - " Metadata:", - JSON.stringify(solanaAccount1.data?.metadata, null, 2), - "\n", - ); - - // Step 4: Create Second Solana Account - console.log("🌟 Creating second Solana account..."); - const solanaAccount2 = await createSolanaAccount({ - client: vaultClient, - request: { - auth: { adminKey }, - options: { - metadata: { - name: "Test Account 2", - purpose: "Secondary test account", - }, - }, - }, - }); - - console.log("✅ Second Solana account response received"); - console.log( - " Response structure:", - JSON.stringify(solanaAccount2, null, 2), - ); - console.log(" Account address:", solanaAccount2.data?.address); - console.log(" Public key:", solanaAccount2.data?.publicKey, "\n"); - - // Step 5: List Solana Accounts - console.log("📋 Listing Solana accounts..."); - const accountsList = await listSolanaAccounts({ - client: vaultClient, - request: { - auth: { adminKey }, - options: { - page: 1, - pageSize: 10, - }, - }, - }); - - console.log("✅ List accounts response received"); - console.log( - " Response structure:", - JSON.stringify(accountsList, null, 2), - ); - console.log(" Total count:", accountsList.data?.totalCount); - console.log(" Accounts found:", accountsList.data?.accounts?.length || 0); - - accountsList.data?.accounts?.forEach((acc, i) => { - console.log( - ` ${i + 1}. ${acc.address} (${acc.metadata?.name || "No name"})`, - ); - }); - console.log(); - - // Step 6: Create Test Transaction Message - console.log("💸 Creating test transaction message..."); - const transferAmount: bigint = 500_000_000n; // 0.5 SOL - - // Ensure we have the account data - if (!solanaAccount1.data?.publicKey || !solanaAccount2.data?.publicKey) { - throw new Error("Missing account data"); - } - - console.log("✅ Test transaction message prepared"); - console.log("📦 Transfer amount:", transferAmount / 1_000_000_000n, "SOL"); - console.log("👤 From:", solanaAccount1.data.publicKey); - console.log("👤 To:", solanaAccount2.data.publicKey, "\n"); - - // Step 7: Sign Transaction with Vault - console.log("✍️ Signing transaction with vault..."); - - // Create a simple test transaction message - const vaultMessage: SolanaVersionedMessage = { - version: "legacy", - header: { - numRequiredSignatures: 1, - numReadonlySignedAccounts: 0, - numReadonlyUnsignedAccounts: 1, - }, - staticAccountKeys: [ - solanaAccount1.data.publicKey, - solanaAccount2.data.publicKey, - "11111111111111111111111111111111", // System program - ], - recentBlockhash: "11111111111111111111111111111111111111111111", // Dummy blockhash for testing - instructions: [ - { - programIdIndex: 2, // System program - accountKeyIndexes: [0, 1], // From and to accounts - data: new Uint8Array([2, 0, 0, 0, 0, 202, 154, 59, 0, 0, 0, 0]), // Transfer 0.5 SOL - }, - ], - }; - - console.log( - " Transaction message:", - JSON.stringify(vaultMessage, null, 2), - ); - console.log(" Signing with account:", solanaAccount1.data.publicKey); - - const signatureResult = await signSolanaTransaction({ - client: vaultClient, - request: { - auth: { adminKey }, - options: { - message: vaultMessage, - from: solanaAccount1.data.publicKey, - }, - }, - }); - - console.log("✅ Transaction signing response received"); - console.log( - " Response structure:", - JSON.stringify(signatureResult, null, 2), - ); - console.log(" Signature:", signatureResult.data?.signature); - console.log(" Signer pubkey:", signatureResult.data?.signerPubkey, "\n"); - - // Step 8: Test Message Signing - console.log("📝 Testing message signing..."); - const testMessage = "Hello from Solana Vault Integration Test!"; - console.log(" Message to sign:", testMessage); - console.log(" Signing with account:", solanaAccount1.data.publicKey); - - const messageSignature = await signSolanaMessage({ - client: vaultClient, - request: { - auth: { adminKey }, - options: { - message: testMessage, - from: solanaAccount1.data.publicKey, - format: "text", - }, - }, - }); - - console.log("✅ Message signing response received"); - console.log( - " Response structure:", - JSON.stringify(messageSignature, null, 2), - ); - console.log(" Signature:", messageSignature.data?.signature); - console.log( - " Signed message:", - messageSignature.data?.signedMessage, - "\n", - ); - - // Step 9: Summary - console.log("🎉 Test Summary:"); - console.log("================"); - console.log("✅ Vault client created"); - console.log("✅ Service account created"); - console.log("✅ Two Solana accounts created"); - console.log("✅ Accounts listed successfully"); - console.log("✅ Transaction message created"); - console.log("✅ Transaction signed with vault"); - console.log("✅ Message signing tested"); - console.log("\n🔍 Explorer Links:"); - console.log( - ` Account 1: https://explorer.solana.com/address/${solanaAccount1.data?.publicKey}?cluster=devnet`, - ); - console.log( - ` Account 2: https://explorer.solana.com/address/${solanaAccount2.data?.publicKey}?cluster=devnet`, - ); - - console.log("\n🎯 All tests completed successfully!"); - console.log("\n💡 Next steps:"); - console.log(" 1. Fund the accounts using the Solana faucet"); - console.log( - " 2. Use a Solana client library to create real transactions", - ); - console.log(" 3. Sign them with the vault and submit to the network"); - } catch (error: unknown) { - console.error("\n❌ Test failed!"); - console.error("================"); - - if (error instanceof Error) { - console.error("Error name:", error.name); - console.error("Error message:", error.message); - console.error("Stack trace:", error.stack); - - // Check for network errors - if (error.message.includes("ECONNREFUSED")) { - console.error("\n🔍 Network Error Details:"); - console.error(" - Connection refused to vault server"); - console.error(" - Make sure the vault is running on", VAULT_URL); - console.error(" - Check if the port is correct (3000)"); - } - - // Check for HTTP errors - if (error.message.includes("fetch")) { - console.error("\n🔍 HTTP Error Details:"); - console.error(" - Failed to make HTTP request"); - console.error(" - Vault URL:", VAULT_URL); - console.error(" - Check network connectivity"); - } - - // Check for JSON parsing errors - if (error.message.includes("JSON")) { - console.error("\n🔍 JSON Error Details:"); - console.error(" - Failed to parse response"); - console.error(" - Server might be returning non-JSON response"); - } - } else { - console.error("Unknown error type:", typeof error); - console.error("Error value:", error); - } - - console.error("\n💡 Troubleshooting steps:"); - console.error(" 1. Ensure the vault server is running"); - console.error(" 2. Check the vault URL and port"); - console.error(" 3. Verify network connectivity"); - console.error(" 4. Check vault logs for errors"); - - process.exit(1); - } -} - -// Run the test -main().catch(console.error); diff --git a/packages/vault-sdk/tests/.env.example b/packages/vault-sdk/tests/.env.example new file mode 100644 index 00000000000..0ab3952ac14 --- /dev/null +++ b/packages/vault-sdk/tests/.env.example @@ -0,0 +1,6 @@ +# Solana RPC Configuration +SOLANA_RPC_HTTP_URL=http://127.0.0.1:8899 +SOLANA_RPC_WS_URL=ws://127.0.0.1:8900 + +# Vault Configuration +VAULT_URL=http://localhost:3000 \ No newline at end of file diff --git a/packages/vault-sdk/tests/solana.test.ts b/packages/vault-sdk/tests/solana.test.ts new file mode 100644 index 00000000000..eafaaa4725c --- /dev/null +++ b/packages/vault-sdk/tests/solana.test.ts @@ -0,0 +1,512 @@ +import { + address, + airdropFactory, + appendTransactionMessageInstruction, + type Base64EncodedWireTransaction, + compileTransaction, + createNoopSigner, + createSolanaRpc, + createSolanaRpcSubscriptions, + createTransactionMessage, + type DevnetUrl, + devnet, + getBase64EncodedWireTransaction, + lamports, + pipe, + type Signature, + setTransactionMessageFeePayer, + setTransactionMessageLifetimeUsingBlockhash, +} from "@solana/kit"; +import { getTransferSolInstruction } from "@solana-program/system"; +import bs58 from "bs58"; +import { beforeAll, describe, expect, it } from "vitest"; +import { + createServiceAccount, + createSolanaAccount, + createVaultClient, + signSolanaTransaction, + type VaultClient, +} from "../src/exports/thirdweb.js"; +import { reconstructSolanaSignedTransaction } from "../src/sdk.js"; + +// Environment variables with fallbacks +const SOLANA_RPC_HTTP_URL = + process.env.SOLANA_RPC_HTTP_URL || "http://127.0.0.1:8899"; +const SOLANA_RPC_WS_URL = + process.env.SOLANA_RPC_WS_URL || "ws://127.0.0.1:8900"; +const VAULT_URL = process.env.VAULT_URL || "http://localhost:3000"; +const LAMPORTS_PER_SOL = 1_000_000_000n; + +/** + * Generate Solana explorer URL with custom RPC endpoint + */ +function getExplorerUrl(path: string, type: "address" | "tx" = "tx"): string { + const encodedRpcUrl = encodeURIComponent(SOLANA_RPC_HTTP_URL); + return `https://explorer.solana.com/${type}/${path}?cluster=custom&customUrl=${encodedRpcUrl}`; +} + +// /** +// * Reconstruct a signed transaction from the vault signature +// */ +// function reconstructSignedTransaction( +// base64Transaction: string, +// base58Signature: string, +// ): Uint8Array { +// // Decode the base64 unsigned transaction +// const transactionBytes = new Uint8Array( +// Buffer.from(base64Transaction, "base64"), +// ); + +// // Decode the base58 signature +// const signatureBytes = bs58.decode(base58Signature); + +// if (signatureBytes.length !== 64) { +// throw new Error( +// `Invalid signature length: ${signatureBytes.length}, expected 64`, +// ); +// } + +// // Wire format structure: +// // [1 byte: signature count][64 bytes per signature][message bytes] + +// // Read the signature count +// const signatureCount = transactionBytes[0]; + +// // Calculate where the message starts (after all signature slots) +// const messageStart = 1 + signatureCount * 64; + +// // Create the signed transaction buffer +// const signedTransaction = new Uint8Array(transactionBytes.length); + +// // Copy signature count +// signedTransaction[0] = signatureCount; + +// // Copy the signature into the first signature slot +// signedTransaction.set(signatureBytes, 1); + +// // Copy any remaining signature slots (should be empty/zeros) +// if (signatureCount > 1) { +// signedTransaction.set(transactionBytes.slice(1 + 64, messageStart), 1 + 64); +// } + +// // Copy the message bytes +// signedTransaction.set(transactionBytes.slice(messageStart), messageStart); + +// return signedTransaction; +// } + +/** + * Send a signed transaction to the Solana network + */ +async function sendSignedTransaction( + rpc: ReturnType, + signedTransactionBytes: Uint8Array, +): Promise { + const base64SignedTransaction = Buffer.from(signedTransactionBytes).toString( + "base64", + ); + + const response = await rpc + .sendTransaction(base64SignedTransaction as Base64EncodedWireTransaction, { + encoding: "base64", + skipPreflight: false, + preflightCommitment: "confirmed", + }) + .send(); + + return response; +} + +describe("Solana Vault Integration Tests", () => { + let vaultClient: VaultClient; + let adminKey: string; + let senderPubkey: string; + let receiverPubkey: string; + let rpc: ReturnType>; + let rpcSubscriptions: ReturnType< + typeof createSolanaRpcSubscriptions + >; + + beforeAll(async () => { + // Setup RPC connections + rpc = createSolanaRpc(devnet(SOLANA_RPC_HTTP_URL)); + rpcSubscriptions = createSolanaRpcSubscriptions(devnet(SOLANA_RPC_WS_URL)); + + // Create vault client + vaultClient = await createVaultClient({ baseUrl: VAULT_URL }); + + // Create service account + const serviceAccountResult = await createServiceAccount({ + client: vaultClient, + request: { + options: { + metadata: { + name: "Solana Test Service Account", + description: "Testing Solana integration", + }, + }, + }, + }); + + adminKey = serviceAccountResult.data?.adminKey || ""; + expect(adminKey).toBeTruthy(); + + // Create sender account + const senderAccount = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + metadata: { + name: "Test Sender", + purpose: "Sender account for tests", + }, + }, + }, + }); + + // Create receiver account + const receiverAccount = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + metadata: { + name: "Test Receiver", + purpose: "Receiver account for tests", + }, + }, + }, + }); + + senderPubkey = senderAccount.data?.pubkey || ""; + receiverPubkey = receiverAccount.data?.pubkey || ""; + + expect(senderPubkey).toBeTruthy(); + expect(receiverPubkey).toBeTruthy(); + + console.log("\n=== Account Setup ==="); + console.log(`Sender account: ${senderPubkey}`); + console.log(`View sender: ${getExplorerUrl(senderPubkey, "address")}`); + console.log(`Receiver account: ${receiverPubkey}`); + console.log(`View receiver: ${getExplorerUrl(receiverPubkey, "address")}`); + + // Airdrop minimal SOL to sender (just enough for tx fees + transfers) + // ~5000 lamports per tx fee * 4 txs + 4 lamports for transfers = ~20004 lamports + console.log("\n=== Airdrop ==="); + console.log("Requesting airdrop of 3000000000 lamports (3 SOL)..."); + const airdrop = airdropFactory({ rpc, rpcSubscriptions }); + const airdropSignature = await airdrop({ + commitment: "confirmed", + recipientAddress: address(senderPubkey), + lamports: lamports(3_000_000_000n), // 3 SOL for tests + }); + + console.log(`Airdrop signature: ${airdropSignature}`); + console.log(`View airdrop: ${getExplorerUrl(airdropSignature)}`); + + // Wait a bit for airdrop to confirm + await new Promise((resolve) => setTimeout(resolve, 2000)); + }, 60000); // 60 second timeout for setup + + describe("Vault Health Check", () => { + it("should successfully connect to vault", async () => { + const response = await fetch(`${VAULT_URL}/health`, { + method: "GET", + headers: { "Content-Type": "application/json" }, + }); + + expect(response.ok).toBe(true); + }); + }); + + describe("Account Management", () => { + it("should have created sender account with valid pubkey", () => { + expect(senderPubkey).toMatch(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/); + }); + + it("should have created receiver account with valid pubkey", () => { + expect(receiverPubkey).toMatch(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/); + }); + + it("should have different pubkeys for sender and receiver", () => { + expect(senderPubkey).not.toBe(receiverPubkey); + }); + }); + + describe("Transaction Creation and Signing", () => { + it("should create a valid transfer transaction", async () => { + const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + + // Get latest blockhash + const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); + expect(latestBlockhash.blockhash).toBeTruthy(); + + const signer = createNoopSigner(address(senderPubkey)); + + // Create transfer instruction + const transferInstruction = getTransferSolInstruction({ + source: signer, + destination: address(receiverPubkey), + amount: transferAmount, + }); + + // Build transaction message + const transactionMessage = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayer(address(senderPubkey), tx), + (tx) => + setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstruction(transferInstruction, tx), + ); + + // Compile transaction + const compiledTransaction = compileTransaction(transactionMessage); + const base64Transaction = + getBase64EncodedWireTransaction(compiledTransaction); + + expect(base64Transaction).toBeTruthy(); + expect(base64Transaction.length).toBeGreaterThan(0); + }); + + it("should sign transaction with vault and return valid signature", async () => { + const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + + // Get latest blockhash + const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); + + const signer = createNoopSigner(address(senderPubkey)); + + // Create transfer instruction + const transferInstruction = getTransferSolInstruction({ + source: signer, + destination: address(receiverPubkey), + amount: transferAmount, + }); + + // Build transaction message + const transactionMessage = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayer(address(senderPubkey), tx), + (tx) => + setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstruction(transferInstruction, tx), + ); + + // Compile and encode + const compiledTransaction = compileTransaction(transactionMessage); + const base64Transaction = + getBase64EncodedWireTransaction(compiledTransaction); + + // Sign with vault + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + expect(signatureResult.data?.signerPubkey).toBe(senderPubkey); + + // Validate signature format (base58) + const signature = signatureResult.data?.signature || ""; + expect(signature).toMatch(/^[1-9A-HJ-NP-Za-km-z]+$/); + + // Decode to verify it's 64 bytes + const signatureBytes = bs58.decode(signature); + expect(signatureBytes.length).toBe(64); + }); + }); + + describe("End-to-End Transfer", () => { + it("should create, sign, and broadcast a SOL transfer", async () => { + const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + + // Get sender's initial balance + const initialBalance = await rpc.getBalance(address(senderPubkey)).send(); + console.log( + `Initial sender balance: ${Number(initialBalance.value) / Number(LAMPORTS_PER_SOL)} SOL`, + ); + + // Get latest blockhash + const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); + + const signer = createNoopSigner(address(senderPubkey)); + + // Create transfer instruction + const transferInstruction = getTransferSolInstruction({ + source: signer, + destination: address(receiverPubkey), + amount: transferAmount, + }); + + // Build transaction message + const transactionMessage = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayer(address(senderPubkey), tx), + (tx) => + setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstruction(transferInstruction, tx), + ); + + // Compile and encode + const compiledTransaction = compileTransaction(transactionMessage); + const base64Transaction = + getBase64EncodedWireTransaction(compiledTransaction); + + // Sign with vault + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + if (!signatureResult.success) { + throw new Error("Failed to sign transaction"); + } + + const { signature, signerPubkey } = signatureResult.data; + expect(signerPubkey).toBe(senderPubkey); + + // Reconstruct signed transaction + const signedTransactionBytes = reconstructSolanaSignedTransaction( + base64Transaction, + signature, + senderPubkey, + ); + + expect(signedTransactionBytes.length).toBeGreaterThan(0); + + // Send transaction to network + const txSignature = await sendSignedTransaction( + rpc, + signedTransactionBytes, + ); + + expect(txSignature).toBeTruthy(); + expect(typeof txSignature).toBe("string"); + + console.log("\n=== Transfer Transaction ==="); + console.log(`Transaction signature: ${txSignature}`); + console.log(`View transaction: ${getExplorerUrl(txSignature)}`); + + // Wait for confirmation + await new Promise((resolve) => setTimeout(resolve, 3000)); + + // Verify transaction was successful + const txDetails = await rpc + .getTransaction(txSignature as Signature, { + encoding: "json", + maxSupportedTransactionVersion: 0, + }) + .send(); + + expect(txDetails).toBeTruthy(); + expect(txDetails?.meta?.err).toBeNull(); + + // Get final balance + const finalBalance = await rpc.getBalance(address(senderPubkey)).send(); + console.log( + `Final sender balance: ${Number(finalBalance.value) / Number(LAMPORTS_PER_SOL)} SOL`, + ); + + // Balance should have decreased (transfer amount + fees) + expect(Number(finalBalance.value)).toBeLessThan( + Number(initialBalance.value), + ); + }, 30000); // 30 second timeout for network operations + }); + + describe("Multiple Transfers", () => { + it("should handle multiple sequential transfers", async () => { + const numTransfers = 3; + const transferAmount = lamports(100_000_000n); // 1 lamport each - minimum possible + + const signatures: string[] = []; + + for (let i = 0; i < numTransfers; i++) { + console.log(`\nProcessing transfer ${i + 1}/${numTransfers}...`); + + // Get latest blockhash (fresh for each transaction) + const { value: latestBlockhash } = await rpc + .getLatestBlockhash() + .send(); + + const signer = createNoopSigner(address(senderPubkey)); + + // Create transfer instruction + const transferInstruction = getTransferSolInstruction({ + source: signer, + destination: address(receiverPubkey), + amount: transferAmount, + }); + + // Build transaction + const transactionMessage = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayer(address(senderPubkey), tx), + (tx) => + setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstruction(transferInstruction, tx), + ); + + const compiledTransaction = compileTransaction(transactionMessage); + const base64Transaction = + getBase64EncodedWireTransaction(compiledTransaction); + + // Sign with vault + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + if (!signatureResult.success) continue; + + // Reconstruct and send + const signedTransactionBytes = reconstructSolanaSignedTransaction( + base64Transaction, + signatureResult.data.signature, + senderPubkey, + ); + + const txSignature = await sendSignedTransaction( + rpc, + signedTransactionBytes, + ); + + signatures.push(txSignature); + console.log(`Transfer ${i + 1} signature: ${txSignature}`); + console.log(`View transfer ${i + 1}: ${getExplorerUrl(txSignature)}`); + + // Wait between transactions + await new Promise((resolve) => setTimeout(resolve, 2000)); + } + + expect(signatures.length).toBe(numTransfers); + console.log(`\n=== Summary ===`); + console.log(`Completed ${numTransfers} transfers successfully!`); + for (let i = 0; i < signatures.length; i++) { + console.log(`Transfer ${i + 1}: ${getExplorerUrl(signatures[i])}`); + } + }, 60000); // 60 second timeout + }); +}); diff --git a/packages/vault-sdk/vitest.config.ts b/packages/vault-sdk/vitest.config.ts new file mode 100644 index 00000000000..b6cf1201e83 --- /dev/null +++ b/packages/vault-sdk/vitest.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from "vitest/config"; + +export default defineConfig({ + test: { + globals: true, + environment: "node", + testTimeout: 60000, // 60 seconds default timeout + hookTimeout: 60000, // 60 seconds for beforeAll/afterAll + teardownTimeout: 10000, + sequence: { + shuffle: false, // Run tests in order + }, + }, +}); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 78406ba4946..e40e83ec327 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,7 +120,7 @@ importers: version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@sentry/nextjs': specifier: 9.34.0 - version: 9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9(esbuild@0.25.5)) + version: 9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9) '@shazow/whatsabi': specifier: 0.22.2 version: 0.22.2(@noble/hashes@1.8.0)(typescript@5.8.3)(zod@3.25.75) @@ -319,7 +319,7 @@ importers: version: 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) '@storybook/nextjs': specifier: 9.0.15 - version: 9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) + version: 9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) '@types/color': specifier: 4.2.0 version: 4.2.0 @@ -1395,7 +1395,7 @@ importers: version: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) x402: specifier: 0.6.1 - version: 0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) zod: specifier: 3.25.75 version: 3.25.75 @@ -1631,7 +1631,7 @@ importers: version: 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) '@storybook/nextjs': specifier: 9.0.15 - version: 9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) + version: 9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) '@types/react': specifier: 19.1.8 version: 19.1.8 @@ -1690,9 +1690,24 @@ importers: '@biomejs/biome': specifier: 2.0.6 version: 2.0.6 + '@solana-program/system': + specifier: ^0.8.1 + version: 0.8.1(@solana/kit@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))) + '@solana/kit': + specifier: ^4.0.0 + version: 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + bs58: + specifier: ^6.0.0 + version: 6.0.0 rimraf: specifier: 6.0.1 version: 6.0.1 + tsx: + specifier: ^4.0.0 + version: 4.20.3 + vitest: + specifier: 3.2.4 + version: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) packages/wagmi-adapter: dependencies: @@ -6419,6 +6434,11 @@ packages: peerDependencies: '@solana/kit': ^2.1.0 + '@solana-program/system@0.8.1': + resolution: {integrity: sha512-71U9Mzdpw8HQtfgfJSL5xKZbLMRnza2Llsfk7gGnmg2waqK+o8MMH4YNma8xXS1UmOBptXIiNvoZ3p7cmOVktg==} + peerDependencies: + '@solana/kit': ^3.0 + '@solana-program/token-2022@0.4.2': resolution: {integrity: sha512-zIpR5t4s9qEU3hZKupzIBxJ6nUV5/UVyIT400tu9vT1HMs5JHxaTTsb5GUhYjiiTvNwU0MQavbwc4Dl29L0Xvw==} peerDependencies: @@ -6436,6 +6456,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/accounts@4.0.0': + resolution: {integrity: sha512-fxTtTk7PCJrigdzqhkc0eZYACVZpONKJZy4MkGvZzx5tCC7rUeDJvzau3IYACUCRaaAGPpkINHwYtp8weKsn8w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/addresses@2.3.0': resolution: {integrity: sha512-ypTNkY2ZaRFpHLnHAgaW8a83N0/WoqdFvCqf4CQmnMdFsZSdC7qOwcbd7YzdaQn9dy+P2hybewzB+KP7LutxGA==} engines: {node: '>=20.18.0'} @@ -6448,6 +6474,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/addresses@4.0.0': + resolution: {integrity: sha512-1OS4nU0HFZxHRxgUb6A72Qg0QbIz6Vu2AbB0j/YSxN4EI+S2BftA83Y6uXhTFDQjKuA+MtHjxe6edB3cs1Pqxw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/assertions@2.3.0': resolution: {integrity: sha512-Ekoet3khNg3XFLN7MIz8W31wPQISpKUGDGTylLptI+JjCDWx3PIa88xjEMqFo02WJ8sBj2NLV64Xg1sBcsHjZQ==} engines: {node: '>=20.18.0'} @@ -6460,6 +6492,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/assertions@4.0.0': + resolution: {integrity: sha512-QwtImPVM5JLEWOFpvHh+eKdvmxdNP6PW8FkmFFEVYR6VFDaZD/hbmSJlwt5p3L69sVmxJA0ughYgD/kkHM7fbg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/buffer-layout-utils@0.2.0': resolution: {integrity: sha512-szG4sxgJGktbuZYDg2FfNmkMi0DYQoVjN2h7ta1W1hPrwzarcFLBq9UpX1UjNXsNpT9dn+chgprtWGioUAr4/g==} engines: {node: '>= 10'} @@ -6485,6 +6523,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-core@4.0.0': + resolution: {integrity: sha512-28kNUsyIlhU3MO3/7ZLDqeJf2YAm32B4tnTjl5A9HrbBqsTZ+upT/RzxZGP1MMm7jnPuIKCMwmTpsyqyR6IUpw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-data-structures@2.0.0-rc.1': resolution: {integrity: sha512-rinCv0RrAVJ9rE/rmaibWJQxMwC5lSaORSZuwjopSUE6T0nb/MVg6Z1siNCXhh/HFTOg0l8bNvZHgBcN/yvXog==} peerDependencies: @@ -6502,6 +6546,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-data-structures@4.0.0': + resolution: {integrity: sha512-pvh+Oxz6UIbWxcgwvVwMJIV4nvZn3EHL5ZvCIPClE5Ep8K5sJ8RoRvOohqLcIv9LYn/EZNoXpCodREX/OYpsGw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-numbers@2.0.0-rc.1': resolution: {integrity: sha512-J5i5mOkvukXn8E3Z7sGIPxsThRCgSdgTWJDQeZvucQ9PT6Y3HiVXJ0pcWiOWAoQ3RX8e/f4I3IC+wE6pZiJzDQ==} peerDependencies: @@ -6519,6 +6569,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs-numbers@4.0.0': + resolution: {integrity: sha512-z9zpjtcwzqT9rbkKVZpkWB5/0V7+6YRKs6BccHkGJlaDx8Pe/+XOvPi2rEdXPqrPd9QWb5Xp1iBfcgaDMyiOiA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/codecs-strings@2.0.0-rc.1': resolution: {integrity: sha512-9/wPhw8TbGRTt6mHC4Zz1RqOnuPTqq1Nb4EyuvpZ39GW6O2t2Q7Q0XxiB3+BdoEjwA2XgPw6e2iRfvYgqty44g==} peerDependencies: @@ -6539,6 +6595,13 @@ packages: fastestsmallesttextencoderdecoder: ^1.0.22 typescript: '>=5.3.3' + '@solana/codecs-strings@4.0.0': + resolution: {integrity: sha512-XvyD+sQ1zyA0amfxbpoFZsucLoe+yASQtDiLUGMDg5TZ82IHE3B7n82jE8d8cTAqi0HgqQiwU13snPhvg1O0Ow==} + engines: {node: '>=20.18.0'} + peerDependencies: + fastestsmallesttextencoderdecoder: ^1.0.22 + typescript: '>=5.3.3' + '@solana/codecs@2.0.0-rc.1': resolution: {integrity: sha512-qxoR7VybNJixV51L0G1RD2boZTcxmwUWnKCaJJExQ5qNKwbpSyDdWfFJfM5JhGyKe9DnPVOZB+JHWXnpbZBqrQ==} peerDependencies: @@ -6550,6 +6613,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/codecs@4.0.0': + resolution: {integrity: sha512-qh+Le1u9QBDPubqUrFU5BGX3Kyj7x0viO6z2SUuM0CSqYUvwE7w724LXwDA9QoEL5JkED1rB3bQg4M0bDrABpA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/errors@2.0.0-rc.1': resolution: {integrity: sha512-ejNvQ2oJ7+bcFAYWj225lyRkHnixuAeb7RQCixm+5mH4n1IA4Qya/9Bmfy5RAAHQzxK43clu3kZmL5eF9VGtYQ==} hasBin: true @@ -6570,6 +6639,13 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/errors@4.0.0': + resolution: {integrity: sha512-3YEtvcMvtcnTl4HahqLt0VnaGVf7vVWOnt6/uPky5e0qV6BlxDSbGkbBzttNjxLXHognV0AQi3pjvrtfUnZmbg==} + engines: {node: '>=20.18.0'} + hasBin: true + peerDependencies: + typescript: '>=5.3.3' + '@solana/fast-stable-stringify@2.3.0': resolution: {integrity: sha512-KfJPrMEieUg6D3hfQACoPy0ukrAV8Kio883llt/8chPEG3FVTX9z/Zuf4O01a15xZmBbmQ7toil2Dp0sxMJSxw==} engines: {node: '>=20.18.0'} @@ -6582,6 +6658,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/fast-stable-stringify@4.0.0': + resolution: {integrity: sha512-sNJRi0RQ93vkGQ9VyFTSGm6mfKLk0FWOFpJLcqyP0BNUK1CugBaUMnxAmGqNaVSCktJagTSLqAMi9k1VSdh+Cg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/functional@2.3.0': resolution: {integrity: sha512-AgsPh3W3tE+nK3eEw/W9qiSfTGwLYEvl0rWaxHht/lRcuDVwfKRzeSa5G79eioWFFqr+pTtoCr3D3OLkwKz02Q==} engines: {node: '>=20.18.0'} @@ -6594,6 +6676,18 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/functional@4.0.0': + resolution: {integrity: sha512-duprxASuT0VXlHj3bLBdy9+ZpqdmCZhzCUmTsXps4UlDKr9PxSCQIQ+NK6OPhtBWOh1sNEcT1f1nY/MVqF/KHg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + + '@solana/instruction-plans@4.0.0': + resolution: {integrity: sha512-FcyptPR5XmKoj1EyF9xARiqy2BuF+CfrIxTU0WQn5Tix/y7whKYz5CCFtBlWbwIcGxQftmG5tAlcidgnCb7jVw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/instructions@2.3.0': resolution: {integrity: sha512-PLMsmaIKu7hEAzyElrk2T7JJx4D+9eRwebhFZpy2PXziNSmFF929eRHKUsKqBFM3cYR1Yy3m6roBZfA+bGE/oQ==} engines: {node: '>=20.18.0'} @@ -6606,6 +6700,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/instructions@4.0.0': + resolution: {integrity: sha512-/Lf3E+6mhe6EL7a3+9FY020yq71lVNgueplJGr221b4wP6ykwPVtoaAiNf+lIrRRYkW8DC81auhmjd2DYpND1w==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/keys@2.3.0': resolution: {integrity: sha512-ZVVdga79pNH+2pVcm6fr2sWz9HTwfopDVhYb0Lh3dh+WBmJjwkabXEIHey2rUES7NjFa/G7sV8lrUn/v8LDCCQ==} engines: {node: '>=20.18.0'} @@ -6618,12 +6718,24 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/keys@4.0.0': + resolution: {integrity: sha512-aPz+LF9QK3EHjuklYBnnalcLVHUNz5s4m4DXNVGAtjJD7Q9zEu2dBUm9mRKwlLbQibNOEGa1m86HCjcboqXdjg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/kit@2.3.0': resolution: {integrity: sha512-sb6PgwoW2LjE5oTFu4lhlS/cGt/NB3YrShEyx7JgWFWysfgLdJnhwWThgwy/4HjNsmtMrQGWVls0yVBHcMvlMQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/kit@4.0.0': + resolution: {integrity: sha512-5c4qMRL+ciWewEtNZ2gX4wf4VpscZYXbWnU2kBiyQhWiqj8zzFIh6iCHbqMX/Myx3pOHfQs/m/iQCnQHPOag9Q==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/nominal-types@2.3.0': resolution: {integrity: sha512-uKlMnlP4PWW5UTXlhKM8lcgIaNj8dvd8xO4Y9l+FVvh9RvW2TO0GwUO6JCo7JBzCB0PSqRJdWWaQ8pu1Ti/OkA==} engines: {node: '>=20.18.0'} @@ -6636,6 +6748,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/nominal-types@4.0.0': + resolution: {integrity: sha512-zIjHZY+5uboigbzsNhHmF3AlP/xACYxbB0Cb1VAI9i+eFShMeu/3VIrj7x1vbq9hfQKGSFHNFGFqQTivdzpbLw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/options@2.0.0-rc.1': resolution: {integrity: sha512-mLUcR9mZ3qfHlmMnREdIFPf9dpMc/Bl66tLSOOWxw4ml5xMT2ohFn7WGqoKcu/UHkT9CrC6+amEdqCNvUqI7AA==} peerDependencies: @@ -6647,18 +6765,36 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/options@4.0.0': + resolution: {integrity: sha512-QTjBh24a34At66mGfs0lVF1voug1KnA13IZkvcVPr52zFb90+xYiqYeKiICTaf3HkoeoKG+TC2Q0K64+se0+CQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/programs@2.3.0': resolution: {integrity: sha512-UXKujV71VCI5uPs+cFdwxybtHZAIZyQkqDiDnmK+DawtOO9mBn4Nimdb/6RjR2CXT78mzO9ZCZ3qfyX+ydcB7w==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/programs@4.0.0': + resolution: {integrity: sha512-tJCNoKyDKfipGTsQtUO6R9EXk4l4ai+gYuD2R3NubJgMaLPBqIv3IMSCeDSvhuSCDuN2lQ1mLkQrDnE3lm0/iQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/promises@2.3.0': resolution: {integrity: sha512-GjVgutZKXVuojd9rWy1PuLnfcRfqsaCm7InCiZc8bqmJpoghlyluweNc7ml9Y5yQn1P2IOyzh9+p/77vIyNybQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/promises@4.0.0': + resolution: {integrity: sha512-zEh815+n2OrrQunZ6m1iuNcoZRc9YnQaTeivBSgl1SYfPaq/Qj/rRiK5DID25Njo4L44p5quu7aal3Bk/eR+tQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-api@2.3.0': resolution: {integrity: sha512-UUdiRfWoyYhJL9PPvFeJr4aJ554ob2jXcpn4vKmRVn9ire0sCbpQKYx6K8eEKHZWXKrDW8IDspgTl0gT/aJWVg==} engines: {node: '>=20.18.0'} @@ -6671,6 +6807,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-api@4.0.0': + resolution: {integrity: sha512-nfQkTJCIW3qzUDRrhvr9MBm9jKQ+dZn4ypK35UDPrV+QB5Gc9UmPJ6prvpPtDq8WoU7wqUzswKeY3k7qtgYjEg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-parsed-types@2.3.0': resolution: {integrity: sha512-B5pHzyEIbBJf9KHej+zdr5ZNAdSvu7WLU2lOUPh81KHdHQs6dEb310LGxcpCc7HVE8IEdO20AbckewDiAN6OCg==} engines: {node: '>=20.18.0'} @@ -6683,6 +6825,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-parsed-types@4.0.0': + resolution: {integrity: sha512-aOjwJwen5D0aDXoSths+ekdBO4mu7nmM+yASqCVW2PLN6v7NZmRBzV1/PgMFjDTiymVQj25ipCUvL395s1wsKg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec-types@2.3.0': resolution: {integrity: sha512-xQsb65lahjr8Wc9dMtP7xa0ZmDS8dOE2ncYjlvfyw/h4mpdXTUdrSMi6RtFwX33/rGuztQ7Hwaid5xLNSLvsFQ==} engines: {node: '>=20.18.0'} @@ -6695,6 +6843,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec-types@4.0.0': + resolution: {integrity: sha512-rpFMIaetpubeyDXIlxV08vtmiDt7ME9527kCI61slHj6O2rbj+7fABhmlN6J4YDCcL/kfnMCxZyNna94DovHZA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-spec@2.3.0': resolution: {integrity: sha512-fA2LMX4BMixCrNB2n6T83AvjZ3oUQTu7qyPLyt8gHQaoEAXs8k6GZmu6iYcr+FboQCjUmRPgMaABbcr9j2J9Sw==} engines: {node: '>=20.18.0'} @@ -6707,12 +6861,24 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-spec@4.0.0': + resolution: {integrity: sha512-9PFTFWjdgA/KFG4rgzbgA7gm9+aRDwsRJgI1aP7n3dGsGzYUp8vNgRQBhogWscEOETkgZNlsi/artLxgvHEHEg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions-api@2.3.0': resolution: {integrity: sha512-9mCjVbum2Hg9KGX3LKsrI5Xs0KX390lS+Z8qB80bxhar6MJPugqIPH8uRgLhCW9GN3JprAfjRNl7our8CPvsPQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions-api@4.0.0': + resolution: {integrity: sha512-6/MzQT9VkcD7Rh8ExoGdbERTSEubA5eI+Q0R9FRuujl/SIy2BsWaNxaBMuZS0DFmKbIHM+m1ptUFdjKAVjGQuw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions-channel-websocket@2.3.0': resolution: {integrity: sha512-2oL6ceFwejIgeWzbNiUHI2tZZnaOxNTSerszcin7wYQwijxtpVgUHiuItM/Y70DQmH9sKhmikQp+dqeGalaJxw==} engines: {node: '>=20.18.0'} @@ -6720,18 +6886,37 @@ packages: typescript: '>=5.3.3' ws: ^8.18.0 + '@solana/rpc-subscriptions-channel-websocket@4.0.0': + resolution: {integrity: sha512-dc4cGfkQJEdkux/CXpItffuytnSU6wktReHEBL+2xaYmF+yGMBeBLzTvkCJ9BbGGfBMf06c5y5QH8X48W5CJdg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + ws: ^8.18.0 + '@solana/rpc-subscriptions-spec@2.3.0': resolution: {integrity: sha512-rdmVcl4PvNKQeA2l8DorIeALCgJEMSu7U8AXJS1PICeb2lQuMeaR+6cs/iowjvIB0lMVjYN2sFf6Q3dJPu6wWg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions-spec@4.0.0': + resolution: {integrity: sha512-2ROfFymoy/TjDAlEPpsmSQAr6LZwG4l/UIhkW7+/VraRu7QPAycuWfSopJnG8D7F3fksICFSeQNwwgBXTN1TWA==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-subscriptions@2.3.0': resolution: {integrity: sha512-Uyr10nZKGVzvCOqwCZgwYrzuoDyUdwtgQRefh13pXIrdo4wYjVmoLykH49Omt6abwStB0a4UL5gX9V4mFdDJZg==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-subscriptions@4.0.0': + resolution: {integrity: sha512-rM+R4Xpsym0tYF3sGAEpdY+D+c6fOMk/fhCEewR+veqdubRfvI5QEhq4kHs8qdKKuRbcpGmedPC306H+PQ6Hmg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-transformers@2.3.0': resolution: {integrity: sha512-UuHYK3XEpo9nMXdjyGKkPCOr7WsZsxs7zLYDO1A5ELH3P3JoehvrDegYRAGzBS2VKsfApZ86ZpJToP0K3PhmMA==} engines: {node: '>=20.18.0'} @@ -6744,6 +6929,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transformers@4.0.0': + resolution: {integrity: sha512-3B3C9zpqN2O76CJV9tethtybMFdT2ViN5b2u8sObftGNFqxPmjt7XmbOmPdn7zwLyRM5S2RuZShzfcVJpBf+yQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-transport-http@2.3.0': resolution: {integrity: sha512-HFKydmxGw8nAF5N+S0NLnPBDCe5oMDtI2RAmW8DMqP4U3Zxt2XWhvV1SNkAldT5tF0U1vP+is6fHxyhk4xqEvg==} engines: {node: '>=20.18.0'} @@ -6756,6 +6947,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-transport-http@4.0.0': + resolution: {integrity: sha512-RjXcQehF3wHm8eoIala+MrdmS3mDSPRl+xwEWzmA1QmBdQl44/XTNOdPJvNkqWXrzE+bAsZGfn0gVua/oCC+zQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc-types@2.3.0': resolution: {integrity: sha512-O09YX2hED2QUyGxrMOxQ9GzH1LlEwwZWu69QbL4oYmIf6P5dzEEHcqRY6L1LsDVqc/dzAdEs/E1FaPrcIaIIPw==} engines: {node: '>=20.18.0'} @@ -6768,6 +6965,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc-types@4.0.0': + resolution: {integrity: sha512-mY4W6DQVaLf3M8hSSzIEtaRsVgLg9zv5qdjjYvxkALw0fzjkLW55h3ctGbJ/k+dNpYm9gcKg7zatA7eBNnNmtQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/rpc@2.3.0': resolution: {integrity: sha512-ZWN76iNQAOCpYC7yKfb3UNLIMZf603JckLKOOLTHuy9MZnTN8XV6uwvDFhf42XvhglgUjGCEnbUqWtxQ9pa/pQ==} engines: {node: '>=20.18.0'} @@ -6780,12 +6983,24 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/rpc@4.0.0': + resolution: {integrity: sha512-KF91ghi7P48aeWd4eSY5Fly/ioYz9ww2loQd/YqV3eLQwo3/2HUWd6r6lpSHsLh/HUoUkm+EsYmVN8r/3mE5fg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/signers@2.3.0': resolution: {integrity: sha512-OSv6fGr/MFRx6J+ZChQMRqKNPGGmdjkqarKkRzkwmv7v8quWsIRnJT5EV8tBy3LI4DLO/A8vKiNSPzvm1TdaiQ==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/signers@4.0.0': + resolution: {integrity: sha512-r3ZrltruadsQXmx3fsGOSqAZ3SsgD7zq/QB8sT6IOVcg11Pgdvx48/CEv7djdy44wF4HVpqNCZLfi12EhoaSXQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/spl-token-group@0.0.7': resolution: {integrity: sha512-V1N/iX7Cr7H0uazWUT2uk27TMqlqedpXHRqqAbVO2gvmJyT0E0ummMEAVQeXZ05ZhQ/xF39DLSdBp90XebWEug==} engines: {node: '>=16'} @@ -6810,18 +7025,36 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/subscribable@4.0.0': + resolution: {integrity: sha512-lDI4HkDuGkmdnX7hSgvJsFFadkQxt0pLHIpZTxOt7/6KBDtNs63NTwJGd3d/EuA7ReXwYg5HDG0QtOm64divXQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/sysvars@2.3.0': resolution: {integrity: sha512-LvjADZrpZ+CnhlHqfI5cmsRzX9Rpyb1Ox2dMHnbsRNzeKAMhu9w4ZBIaeTdO322zsTr509G1B+k2ABD3whvUBA==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/sysvars@4.0.0': + resolution: {integrity: sha512-HUu2B8P7iRYWAt1KL/5a6nNTKp73y04cSxZ9PZf2Ap1/KE0/5D8WnkEfnurUQmU3zBner95d+szNOyWMNBOoTw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transaction-confirmation@2.3.0': resolution: {integrity: sha512-UiEuiHCfAAZEKdfne/XljFNJbsKAe701UQHKXEInYzIgBjRbvaeYZlBmkkqtxwcasgBTOmEaEKT44J14N9VZDw==} engines: {node: '>=20.18.0'} peerDependencies: typescript: '>=5.3.3' + '@solana/transaction-confirmation@4.0.0': + resolution: {integrity: sha512-DTBIMB5/UCOpVyL5E0xwswtxs/PGeSD1VL5+C1UCPlggpZNIOlhZoaQqFO56wrJDFASzPMx+dakda5BUuhQkBg==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transaction-messages@2.3.0': resolution: {integrity: sha512-bgqvWuy3MqKS5JdNLH649q+ngiyOu5rGS3DizSnWwYUd76RxZl1kN6CoqHSrrMzFMvis6sck/yPGG3wqrMlAww==} engines: {node: '>=20.18.0'} @@ -6834,6 +7067,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/transaction-messages@4.0.0': + resolution: {integrity: sha512-rQo0rRyvkrROFZHUT0uL3vqeBBtxTsNKDtx8pZo6BC3TgGA7V1MoSC3rVOLwYCK6rK5NJZiYNjmneHz/7hVpwQ==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/transactions@2.3.0': resolution: {integrity: sha512-LnTvdi8QnrQtuEZor5Msje61sDpPstTVwKg4y81tNxDhiyomjuvnSNLAq6QsB9gIxUqbNzPZgOG9IU4I4/Uaug==} engines: {node: '>=20.18.0'} @@ -6846,6 +7085,12 @@ packages: peerDependencies: typescript: '>=5.3.3' + '@solana/transactions@4.0.0': + resolution: {integrity: sha512-bmHIIVTQq+Wlqg4es91Ew4KSbOrvdfPsKg/pVha8ZR77huwvfqQMxRyYF4zMQ+Fm3QXGFKOU0RPVKKYic15jBw==} + engines: {node: '>=20.18.0'} + peerDependencies: + typescript: '>=5.3.3' + '@solana/wallet-adapter-base@0.9.23': resolution: {integrity: sha512-apqMuYwFp1jFi55NxDfvXUX2x1T0Zh07MxhZ/nCCTGys5raSfYUh82zen2BLv8BSDj/JxZ2P/s7jrQZGrX8uAw==} engines: {node: '>=16'} @@ -9194,6 +9439,10 @@ packages: resolution: {integrity: sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==} engines: {node: '>=20'} + commander@14.0.1: + resolution: {integrity: sha512-2JkV3gUZUVrbNA+1sjBOYLsMZ5cEEl8GTFP2a4AVz5hvasAMCQ1D2l2le/cX+pV4N6ZU17zjUahLpIXRrnWL8A==} + engines: {node: '>=20'} + commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} @@ -16742,7 +16991,7 @@ snapshots: react: 19.1.0 secp256k1: 5.0.1 viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - wagmi: 2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + wagmi: 2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) optionalDependencies: thirdweb: link:packages/thirdweb typescript: 5.8.3 @@ -20135,6 +20384,14 @@ snapshots: '@types/node': 22.14.1 optional: true + '@inquirer/confirm@5.1.14(@types/node@24.0.10)': + dependencies: + '@inquirer/core': 10.1.15(@types/node@24.0.10) + '@inquirer/type': 3.0.8(@types/node@24.0.10) + optionalDependencies: + '@types/node': 24.0.10 + optional: true + '@inquirer/core@10.1.14(@types/node@22.14.1)': dependencies: '@inquirer/figures': 1.0.12 @@ -20175,6 +20432,20 @@ snapshots: '@types/node': 22.14.1 optional: true + '@inquirer/core@10.1.15(@types/node@24.0.10)': + dependencies: + '@inquirer/figures': 1.0.13 + '@inquirer/type': 3.0.8(@types/node@24.0.10) + ansi-escapes: 4.3.2 + cli-width: 4.1.0 + mute-stream: 2.0.0 + signal-exit: 4.1.0 + wrap-ansi: 6.2.0 + yoctocolors-cjs: 2.1.2 + optionalDependencies: + '@types/node': 24.0.10 + optional: true + '@inquirer/editor@4.2.13(@types/node@22.14.1)': dependencies: '@inquirer/core': 10.1.14(@types/node@22.14.1) @@ -20273,6 +20544,11 @@ snapshots: '@types/node': 22.14.1 optional: true + '@inquirer/type@3.0.8(@types/node@24.0.10)': + optionalDependencies: + '@types/node': 24.0.10 + optional: true + '@internationalized/date@3.9.0': dependencies: '@swc/helpers': 0.5.17 @@ -21443,7 +21719,7 @@ snapshots: fflate: 0.8.2 viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) optionalDependencies: - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) '@privy-io/ethereum@0.0.2(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': dependencies: @@ -22984,7 +23260,7 @@ snapshots: estree-walker: 2.0.2 fdir: 6.4.6(picomatch@4.0.2) is-reference: 1.2.1 - magic-string: 0.30.17 + magic-string: 0.30.18 picomatch: 4.0.2 optionalDependencies: rollup: 4.35.0 @@ -23324,7 +23600,7 @@ snapshots: dependencies: '@phosphor-icons/core': 2.1.1 '@types/node': 22.14.1 - chalk: 5.5.0 + chalk: 5.6.2 vue: 3.5.21(typescript@5.8.3) transitivePeerDependencies: - typescript @@ -23602,7 +23878,7 @@ snapshots: '@sentry/core@9.34.0': {} - '@sentry/nextjs@9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9(esbuild@0.25.5))': + '@sentry/nextjs@9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9)': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.34.0 @@ -23613,7 +23889,7 @@ snapshots: '@sentry/opentelemetry': 9.34.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.34.0) '@sentry/react': 9.34.0(react@19.1.0) '@sentry/vercel-edge': 9.34.0 - '@sentry/webpack-plugin': 3.5.0(encoding@0.1.13)(webpack@5.99.9(esbuild@0.25.5)) + '@sentry/webpack-plugin': 3.5.0(encoding@0.1.13)(webpack@5.99.9) chalk: 3.0.0 next: 15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) resolve: 1.22.8 @@ -23690,12 +23966,12 @@ snapshots: '@opentelemetry/api': 1.9.0 '@sentry/core': 9.34.0 - '@sentry/webpack-plugin@3.5.0(encoding@0.1.13)(webpack@5.99.9(esbuild@0.25.5))': + '@sentry/webpack-plugin@3.5.0(encoding@0.1.13)(webpack@5.99.9)': dependencies: '@sentry/bundler-plugin-core': 3.5.0(encoding@0.1.13) unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.99.9(esbuild@0.25.5) + webpack: 5.99.9 transitivePeerDependencies: - encoding - supports-color @@ -24394,10 +24670,14 @@ snapshots: dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + '@solana-program/system@0.8.1(@solana/kit@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)))': + dependencies: + '@solana/kit': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: @@ -24415,6 +24695,18 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/accounts@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/addresses@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/assertions': 2.3.0(typescript@5.8.3) @@ -24437,6 +24729,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/addresses@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 4.0.0(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/assertions@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24447,6 +24750,11 @@ snapshots: '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/assertions@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/buffer-layout-utils@0.2.0(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10)': dependencies: '@solana/buffer-layout': 4.0.1 @@ -24480,6 +24788,11 @@ snapshots: '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/codecs-core@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/codecs-data-structures@2.0.0-rc.1(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24502,6 +24815,13 @@ snapshots: '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/codecs-data-structures@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/codecs-numbers@2.0.0-rc.1(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24521,6 +24841,12 @@ snapshots: '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/codecs-numbers@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/codecs-strings@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24546,6 +24872,14 @@ snapshots: fastestsmallesttextencoderdecoder: 1.0.22 typescript: 5.8.3 + '@solana/codecs-strings@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + fastestsmallesttextencoderdecoder: 1.0.22 + typescript: 5.8.3 + '@solana/codecs@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24569,16 +24903,27 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/codecs@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-data-structures': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/options': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/errors@2.0.0-rc.1(typescript@5.8.3)': dependencies: - chalk: 5.5.0 + chalk: 5.6.2 commander: 12.1.0 typescript: 5.8.3 optional: true '@solana/errors@2.3.0(typescript@5.8.3)': dependencies: - chalk: 5.5.0 + chalk: 5.6.2 commander: 14.0.0 typescript: 5.8.3 @@ -24588,6 +24933,12 @@ snapshots: commander: 14.0.0 typescript: 5.8.3 + '@solana/errors@4.0.0(typescript@5.8.3)': + dependencies: + chalk: 5.6.2 + commander: 14.0.1 + typescript: 5.8.3 + '@solana/fast-stable-stringify@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -24596,6 +24947,10 @@ snapshots: dependencies: typescript: 5.8.3 + '@solana/fast-stable-stringify@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/functional@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -24604,6 +24959,21 @@ snapshots: dependencies: typescript: 5.8.3 + '@solana/functional@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + + '@solana/instruction-plans@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/instructions': 4.0.0(typescript@5.8.3) + '@solana/promises': 4.0.0(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/instructions@2.3.0(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.3.0(typescript@5.8.3) @@ -24616,6 +24986,12 @@ snapshots: '@solana/errors': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/instructions@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/keys@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/assertions': 2.3.0(typescript@5.8.3) @@ -24638,6 +25014,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/keys@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/assertions': 4.0.0(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24663,6 +25050,32 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/kit@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + dependencies: + '@solana/accounts': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/instruction-plans': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/instructions': 4.0.0(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/programs': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-subscriptions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/signers': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/sysvars': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-confirmation': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/nominal-types@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -24671,6 +25084,10 @@ snapshots: dependencies: typescript: 5.8.3 + '@solana/nominal-types@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/options@2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs-core': 2.0.0-rc.1(typescript@5.8.3) @@ -24694,6 +25111,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/options@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-data-structures': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/programs@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24702,10 +25130,22 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/programs@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/promises@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 + '@solana/promises@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24740,6 +25180,23 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-api@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-parsed-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-transformers': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-parsed-types@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -24748,6 +25205,10 @@ snapshots: dependencies: typescript: 5.8.3 + '@solana/rpc-parsed-types@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-spec-types@2.3.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -24756,6 +25217,10 @@ snapshots: dependencies: typescript: 5.8.3 + '@solana/rpc-spec-types@4.0.0(typescript@5.8.3)': + dependencies: + typescript: 5.8.3 + '@solana/rpc-spec@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24768,6 +25233,12 @@ snapshots: '@solana/rpc-spec-types': 3.0.3(typescript@5.8.3) typescript: 5.8.3 + '@solana/rpc-spec@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/rpc-subscriptions-api@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24781,6 +25252,19 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-subscriptions-api@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-transformers': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24790,6 +25274,15 @@ snapshots: typescript: 5.8.3 ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + '@solana/rpc-subscriptions-channel-websocket@4.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/rpc-subscriptions-spec': 4.0.0(typescript@5.8.3) + '@solana/subscribable': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5) + '@solana/rpc-subscriptions-spec@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24798,6 +25291,14 @@ snapshots: '@solana/subscribable': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/rpc-subscriptions-spec@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/promises': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + '@solana/subscribable': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24816,6 +25317,24 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/rpc-subscriptions@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/promises': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-subscriptions-api': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions-channel-websocket': 4.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@solana/rpc-subscriptions-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-transformers': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/subscribable': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/rpc-transformers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24838,6 +25357,17 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-transformers@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc-transport-http@2.3.0(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24854,6 +25384,14 @@ snapshots: typescript: 5.8.3 undici-types: 7.16.0 + '@solana/rpc-transport-http@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + undici-types: 7.16.0 + '@solana/rpc-types@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24878,6 +25416,18 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc-types@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/rpc@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) @@ -24908,6 +25458,21 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/rpc@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/fast-stable-stringify': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/rpc-api': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-spec': 4.0.0(typescript@5.8.3) + '@solana/rpc-spec-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-transformers': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-transport-http': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/signers@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24922,6 +25487,20 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/signers@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/instructions': 4.0.0(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/spl-token-group@0.0.7(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/codecs': 2.0.0-rc.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24961,6 +25540,11 @@ snapshots: '@solana/errors': 2.3.0(typescript@5.8.3) typescript: 5.8.3 + '@solana/subscribable@4.0.0(typescript@5.8.3)': + dependencies: + '@solana/errors': 4.0.0(typescript@5.8.3) + typescript: 5.8.3 + '@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24971,6 +25555,16 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/accounts': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -24988,6 +25582,23 @@ snapshots: - fastestsmallesttextencoderdecoder - ws + '@solana/transaction-confirmation@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/promises': 4.0.0(typescript@5.8.3) + '@solana/rpc': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/rpc-subscriptions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transactions': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + - ws + '@solana/transaction-messages@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -25018,6 +25629,21 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transaction-messages@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-data-structures': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/instructions': 4.0.0(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/transactions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -25054,6 +25680,24 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder + '@solana/transactions@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': + dependencies: + '@solana/addresses': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/codecs-core': 4.0.0(typescript@5.8.3) + '@solana/codecs-data-structures': 4.0.0(typescript@5.8.3) + '@solana/codecs-numbers': 4.0.0(typescript@5.8.3) + '@solana/codecs-strings': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/errors': 4.0.0(typescript@5.8.3) + '@solana/functional': 4.0.0(typescript@5.8.3) + '@solana/instructions': 4.0.0(typescript@5.8.3) + '@solana/keys': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/nominal-types': 4.0.0(typescript@5.8.3) + '@solana/rpc-types': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/transaction-messages': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + typescript: 5.8.3 + transitivePeerDependencies: + - fastestsmallesttextencoderdecoder + '@solana/wallet-adapter-base@0.9.23(@solana/web3.js@1.98.2(bufferutil@4.0.9)(encoding@0.1.13)(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@solana/wallet-standard-features': 1.3.0 @@ -25181,9 +25825,9 @@ snapshots: ts-dedent: 2.2.0 vite: 7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) - '@storybook/builder-webpack5@9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': + '@storybook/builder-webpack5@9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': dependencies: - '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) + '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.3 css-loader: 6.11.0(webpack@5.99.9(esbuild@0.25.5)) @@ -25191,7 +25835,7 @@ snapshots: fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.8.3)(webpack@5.99.9(esbuild@0.25.5)) html-webpack-plugin: 5.6.3(webpack@5.99.9(esbuild@0.25.5)) magic-string: 0.30.17 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) style-loader: 3.3.4(webpack@5.99.9(esbuild@0.25.5)) terser-webpack-plugin: 5.3.14(esbuild@0.25.5)(webpack@5.99.9(esbuild@0.25.5)) ts-dedent: 2.2.0 @@ -25208,6 +25852,33 @@ snapshots: - uglify-js - webpack-cli + '@storybook/builder-webpack5@9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': + dependencies: + '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) + case-sensitive-paths-webpack-plugin: 2.4.0 + cjs-module-lexer: 1.4.3 + css-loader: 6.11.0(webpack@5.99.9) + es-module-lexer: 1.7.0 + fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.8.3)(webpack@5.99.9) + html-webpack-plugin: 5.6.3(webpack@5.99.9) + magic-string: 0.30.17 + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + style-loader: 3.3.4(webpack@5.99.9) + terser-webpack-plugin: 5.3.14(webpack@5.99.9) + ts-dedent: 2.2.0 + webpack: 5.99.9 + webpack-dev-middleware: 6.1.3(webpack@5.99.9) + webpack-hot-middleware: 2.26.1 + webpack-virtual-modules: 0.6.2 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@rspack/core' + - '@swc/core' + - esbuild + - uglify-js + - webpack-cli + '@storybook/builder-webpack5@9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': dependencies: '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) @@ -25262,7 +25933,7 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - '@storybook/nextjs@9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5))': + '@storybook/nextjs@9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) @@ -25278,9 +25949,9 @@ snapshots: '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) '@babel/runtime': 7.27.6 '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) - '@storybook/builder-webpack5': 9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@storybook/preset-react-webpack': 9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@storybook/builder-webpack5': 9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) + '@storybook/preset-react-webpack': 9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) + '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) '@types/semver': 7.7.0 babel-loader: 9.2.1(@babel/core@7.28.0)(webpack@5.99.9(esbuild@0.25.5)) css-loader: 6.11.0(webpack@5.99.9(esbuild@0.25.5)) @@ -25296,7 +25967,7 @@ snapshots: resolve-url-loader: 5.0.0 sass-loader: 14.2.1(webpack@5.99.9(esbuild@0.25.5)) semver: 7.7.2 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) style-loader: 3.3.4(webpack@5.99.9(esbuild@0.25.5)) styled-jsx: 5.1.7(@babel/core@7.28.0)(react@19.1.0) tsconfig-paths: 4.2.0 @@ -25322,6 +25993,66 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve + '@storybook/nextjs@9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9)': + dependencies: + '@babel/core': 7.28.0 + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.0) + '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) + '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) + '@babel/plugin-transform-runtime': 7.28.0(@babel/core@7.28.0) + '@babel/preset-env': 7.28.0(@babel/core@7.28.0) + '@babel/preset-react': 7.27.1(@babel/core@7.28.0) + '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) + '@babel/runtime': 7.27.6 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) + '@storybook/builder-webpack5': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@storybook/preset-react-webpack': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@types/semver': 7.7.0 + babel-loader: 9.2.1(@babel/core@7.28.0)(webpack@5.99.9) + css-loader: 6.11.0(webpack@5.99.9) + image-size: 2.0.2 + loader-utils: 3.3.1 + next: 15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + node-polyfill-webpack-plugin: 2.0.1(webpack@5.99.9) + postcss: 8.5.6 + postcss-loader: 8.1.1(postcss@8.5.6)(typescript@5.8.3)(webpack@5.99.9) + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + react-refresh: 0.14.2 + resolve-url-loader: 5.0.0 + sass-loader: 14.2.1(webpack@5.99.9) + semver: 7.7.2 + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + style-loader: 3.3.4(webpack@5.99.9) + styled-jsx: 5.1.7(@babel/core@7.28.0)(react@19.1.0) + tsconfig-paths: 4.2.0 + tsconfig-paths-webpack-plugin: 4.2.0 + optionalDependencies: + typescript: 5.8.3 + webpack: 5.99.9 + transitivePeerDependencies: + - '@rspack/core' + - '@swc/core' + - '@types/webpack' + - babel-plugin-macros + - esbuild + - node-sass + - sass + - sass-embedded + - sockjs-client + - supports-color + - type-fest + - uglify-js + - webpack-cli + - webpack-dev-server + - webpack-hot-middleware + - webpack-plugin-serve + '@storybook/nextjs@9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9)': dependencies: '@babel/core': 7.28.0 @@ -25382,9 +26113,9 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': + '@storybook/preset-react-webpack@9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': dependencies: - '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) + '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.99.9(esbuild@0.25.5)) '@types/semver': 7.7.0 find-up: 7.0.0 @@ -25394,7 +26125,7 @@ snapshots: react-dom: 19.1.0(react@19.1.0) resolve: 1.22.10 semver: 7.7.2 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) tsconfig-paths: 4.2.0 webpack: 5.99.9(esbuild@0.25.5) optionalDependencies: @@ -25406,6 +26137,30 @@ snapshots: - uglify-js - webpack-cli + '@storybook/preset-react-webpack@9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': + dependencies: + '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.99.9) + '@types/semver': 7.7.0 + find-up: 7.0.0 + magic-string: 0.30.17 + react: 19.1.0 + react-docgen: 7.1.1 + react-dom: 19.1.0(react@19.1.0) + resolve: 1.22.10 + semver: 7.7.2 + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) + tsconfig-paths: 4.2.0 + webpack: 5.99.9 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - supports-color + - uglify-js + - webpack-cli + '@storybook/preset-react-webpack@9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': dependencies: '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) @@ -26690,16 +27445,25 @@ snapshots: dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.18 optionalDependencies: msw: 2.10.2(@types/node@22.14.1)(typescript@5.8.3) vite: 7.0.1(@types/node@22.14.1)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + '@vitest/mocker@3.2.4(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(vite@7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.18 + optionalDependencies: + msw: 2.10.2(@types/node@24.0.10)(typescript@5.8.3) + vite: 7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + '@vitest/mocker@3.2.4(msw@2.7.5(@types/node@24.0.10)(typescript@5.8.3))(vite@7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 - magic-string: 0.30.17 + magic-string: 0.30.18 optionalDependencies: msw: 2.7.5(@types/node@24.0.10)(typescript@5.8.3) vite: 7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) @@ -26717,7 +27481,7 @@ snapshots: '@vitest/snapshot@3.2.4': dependencies: '@vitest/pretty-format': 3.2.4 - magic-string: 0.30.17 + magic-string: 0.30.18 pathe: 2.0.3 '@vitest/spy@3.2.4': @@ -26733,7 +27497,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@17.4.4)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.7.5(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -26851,7 +27615,7 @@ snapshots: - '@vue/composition-api' - vue - '@wagmi/connectors@5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': + '@wagmi/connectors@5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': dependencies: '@coinbase/wallet-sdk': 4.3.3 '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) @@ -26890,45 +27654,6 @@ snapshots: - utf-8-validate - zod - '@wagmi/connectors@5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75)': - dependencies: - '@coinbase/wallet-sdk': 4.3.3 - '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) - '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) - '@walletconnect/ethereum-provider': 2.21.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - cbw-sdk: '@coinbase/wallet-sdk@3.9.3' - viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - react - - supports-color - - uploadthing - - utf-8-validate - - zod - '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': dependencies: eventemitter3: 5.0.1 @@ -26944,21 +27669,6 @@ snapshots: - react - use-sync-external-store - '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': - dependencies: - eventemitter3: 5.0.1 - mipd: 0.0.7(typescript@5.8.3) - viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - zustand: 5.0.0(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) - optionalDependencies: - '@tanstack/query-core': 5.81.5 - typescript: 5.8.3 - transitivePeerDependencies: - - '@types/react' - - immer - - react - - use-sync-external-store - '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@6.0.5)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 @@ -29420,6 +30130,8 @@ snapshots: commander@14.0.0: {} + commander@14.0.1: {} + commander@2.20.3: {} commander@4.1.1: {} @@ -30511,8 +31223,8 @@ snapshots: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.8.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) eslint-plugin-react: 7.37.5(eslint@8.57.0) eslint-plugin-react-hooks: 5.2.0(eslint@8.57.0) @@ -30531,7 +31243,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1(supports-color@8.1.1) @@ -30542,7 +31254,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.10.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -30567,18 +31279,18 @@ snapshots: - bluebird - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.8.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -30589,7 +31301,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -33100,7 +33812,7 @@ snapshots: magic-string@0.30.8: dependencies: - '@jridgewell/sourcemap-codec': 1.5.4 + '@jridgewell/sourcemap-codec': 1.5.5 magicast@0.3.5: dependencies: @@ -34006,6 +34718,32 @@ snapshots: - '@types/node' optional: true + msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3): + dependencies: + '@bundled-es-modules/cookie': 2.0.1 + '@bundled-es-modules/statuses': 1.0.1 + '@bundled-es-modules/tough-cookie': 0.1.6 + '@inquirer/confirm': 5.1.14(@types/node@24.0.10) + '@mswjs/interceptors': 0.39.5 + '@open-draft/deferred-promise': 2.2.0 + '@open-draft/until': 2.1.0 + '@types/cookie': 0.6.0 + '@types/statuses': 2.0.6 + graphql: 16.11.0 + headers-polyfill: 4.0.3 + is-node-process: 1.2.0 + outvariant: 1.4.3 + path-to-regexp: 6.3.0 + picocolors: 1.1.1 + strict-event-emitter: 0.5.1 + type-fest: 4.41.0 + yargs: 17.7.2 + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@types/node' + optional: true + msw@2.7.5(@types/node@24.0.10)(typescript@5.8.3): dependencies: '@bundled-es-modules/cookie': 2.0.1 @@ -38106,7 +38844,7 @@ snapshots: chai: 5.2.0 debug: 4.4.1(supports-color@8.1.1) expect-type: 1.2.1 - magic-string: 0.30.17 + magic-string: 0.30.18 pathe: 2.0.3 picomatch: 4.0.2 std-env: 3.9.0 @@ -38150,7 +38888,7 @@ snapshots: chai: 5.2.0 debug: 4.4.1(supports-color@8.1.1) expect-type: 1.2.1 - magic-string: 0.30.17 + magic-string: 0.30.18 pathe: 2.0.3 picomatch: 4.0.2 std-env: 3.9.0 @@ -38181,6 +38919,50 @@ snapshots: - tsx - yaml + vitest@3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(vite@7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.2.0 + debug: 4.4.1(supports-color@8.1.1) + expect-type: 1.2.1 + magic-string: 0.30.18 + pathe: 2.0.3 + picomatch: 4.0.2 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.14 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + vite-node: 3.2.4(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/debug': 4.1.12 + '@types/node': 24.0.10 + '@vitest/ui': 3.2.4(vitest@3.2.4) + happy-dom: 18.0.1 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vlq@1.0.1: {} vm-browserify@1.1.2: {} @@ -38234,45 +39016,7 @@ snapshots: wagmi@2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): dependencies: '@tanstack/react-query': 5.81.5(react@19.1.0) - '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) - react: 19.1.0 - use-sync-external-store: 1.4.0(react@19.1.0) - viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@tanstack/query-core' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - immer - - ioredis - - supports-color - - uploadthing - - utf-8-validate - - zod - - wagmi@2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): - dependencies: - '@tanstack/react-query': 5.81.5(react@19.1.0) - '@wagmi/connectors': 5.8.5(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) react: 19.1.0 use-sync-external-store: 1.4.0(react@19.1.0) @@ -38653,12 +39397,12 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 6.0.5 - x402@0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + x402@0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: '@scure/base': 1.2.6 '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) From 07872274fef377e3c1d341a6e6c2b74bafb391a8 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Fri, 10 Oct 2025 11:08:24 +0530 Subject: [PATCH 03/10] solana access token permissions testing --- packages/vault-sdk/tests/solana.test.ts | 130 ++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/packages/vault-sdk/tests/solana.test.ts b/packages/vault-sdk/tests/solana.test.ts index eafaaa4725c..df2452eba64 100644 --- a/packages/vault-sdk/tests/solana.test.ts +++ b/packages/vault-sdk/tests/solana.test.ts @@ -21,6 +21,7 @@ import { getTransferSolInstruction } from "@solana-program/system"; import bs58 from "bs58"; import { beforeAll, describe, expect, it } from "vitest"; import { + createAccessToken, createServiceAccount, createSolanaAccount, createVaultClient, @@ -234,6 +235,135 @@ describe("Solana Vault Integration Tests", () => { }); }); + describe("Access Token - Solana Account Creation", () => { + it("should create a Solana account using an access token", async () => { + // Create an access token with solana:create permission + const expiresAt = new Date(Date.now() + 3600000).toISOString(); // 1 hour from now + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:create", + allowedMetadataPatterns: [ + { + key: "purpose", + rule: { pattern: ".*" }, // Allow any purpose + }, + { + key: "name", + rule: { pattern: ".*" }, + }, + ], + }, + { + type: "solana:read", + metadataPatterns: [ + { + key: "purpose", + rule: { pattern: ".*" }, // Allow reading any + }, + ], + }, + ], + expiresAt, + metadata: { + name: "Solana Access Token", + description: "Token for creating Solana accounts", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + expect(accessTokenResult.data?.accessToken).toBeTruthy(); + + const accessToken = accessTokenResult.data?.accessToken || ""; + console.log("\n=== Access Token Created ==="); + console.log(`Access Token ID: ${accessTokenResult.data?.id}`); + + // Use the access token to create a new Solana account + const accountResult = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + metadata: { + name: "Access Token Created Account", + purpose: "Testing access token creation", + }, + }, + }, + }); + + expect(accountResult.success).toBe(true); + expect(accountResult.data?.pubkey).toBeTruthy(); + expect(accountResult.data?.pubkey).toMatch( + /^[1-9A-HJ-NP-Za-km-z]{32,44}$/, + ); + + console.log("\n=== Account Created via Access Token ==="); + console.log(`Account pubkey: ${accountResult.data?.pubkey}`); + console.log( + `View account: ${getExplorerUrl(accountResult.data?.pubkey || "", "address")}`, + ); + console.log(`Created at: ${accountResult.data?.createdAt}`); + }); + + it("should fail to create account without proper permissions", async () => { + // Create an access token without solana:create permission (only read) + const expiresAt = new Date(Date.now() + 3600000).toISOString(); // 1 hour from now + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:read", + metadataPatterns: [ + { + key: "purpose", + rule: { pattern: ".*" }, + }, + ], + }, + ], + expiresAt, + metadata: { + name: "Read-Only Token", + description: "Token without create permission", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + // Attempt to create account should fail + const accountResult = await createSolanaAccount({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + metadata: { + name: "Should Fail", + purpose: "This should not work", + }, + }, + }, + }); + + expect(accountResult.success).toBe(false); + expect(accountResult.error).toBeTruthy(); + console.log("\n=== Expected Failure (No Create Permission) ==="); + console.log(`Error: ${accountResult.error}`); + }); + }); + describe("Transaction Creation and Signing", () => { it("should create a valid transfer transaction", async () => { const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible From 2cc51731d31c2bafae2a4655db2e3aa03dda645f Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 04:38:14 +0530 Subject: [PATCH 04/10] updated SDK for revised access control --- packages/vault-sdk/biome.json | 14 +- packages/vault-sdk/src/sdk.ts | 1032 ++++++++++---------- packages/vault-sdk/src/types.ts | 33 +- packages/vault-sdk/tests/solana.test.ts | 1162 ++++++++++++++++++++++- 4 files changed, 1658 insertions(+), 583 deletions(-) diff --git a/packages/vault-sdk/biome.json b/packages/vault-sdk/biome.json index 709230af37e..f9869db792f 100644 --- a/packages/vault-sdk/biome.json +++ b/packages/vault-sdk/biome.json @@ -1,16 +1,4 @@ { "$schema": "https://biomejs.dev/schemas/2.0.6/schema.json", - "extends": "//", - "overrides": [ - { - "assist": { - "actions": { - "source": { - "useSortedKeys": "off" - } - } - }, - "includes": ["package.json"] - } - ] + "extends": "//" } diff --git a/packages/vault-sdk/src/sdk.ts b/packages/vault-sdk/src/sdk.ts index 71082bd67b1..25bb00c0796 100644 --- a/packages/vault-sdk/src/sdk.ts +++ b/packages/vault-sdk/src/sdk.ts @@ -5,563 +5,563 @@ import { sha256 } from "@noble/hashes/sha256"; import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils"; import { - address, - getBase58Encoder, - getTransactionDecoder, - getTransactionEncoder, + address, + getBase58Encoder, + getTransactionDecoder, + getTransactionEncoder, } from "@solana/kit"; import type { TypedData } from "abitype"; import * as jose from "jose"; import type { - CheckedSignTypedDataPayload, - CreateAccessTokenPayload, - CreateEoaPayload, - CreateServiceAccountPayload, - CreateSolanaAccountPayload, - EncryptedPayload, - GetServiceAccountPayload, - ListAccessTokensPayload, - ListEoaPayload, - ListSolanaAccountsPayload, - Payload, - PingPayload, - PolicyComponent, - Prettify, - RevokeAccessTokenPayload, - RotateServiceAccountPayload, - SignAuthorizationPayload, - SignMessagePayload, - SignSolanaMessagePayload, - SignSolanaTransactionPayload, - SignStructuredMessagePayload, - SignTransactionPayload, - UnencryptedErrorResponse, + CheckedSignTypedDataPayload, + CreateAccessTokenPayload, + CreateEoaPayload, + CreateServiceAccountPayload, + CreateSolanaAccountPayload, + EncryptedPayload, + GetServiceAccountPayload, + ListAccessTokensPayload, + ListEoaPayload, + ListSolanaAccountsPayload, + Payload, + PingPayload, + PolicyComponent, + Prettify, + RevokeAccessTokenPayload, + RotateServiceAccountPayload, + SignAuthorizationPayload, + SignMessagePayload, + SignSolanaMessagePayload, + SignSolanaTransactionPayload, + SignStructuredMessagePayload, + SignTransactionPayload, + UnencryptedErrorResponse, } from "./types.js"; function encryptForEnclave( - payload: Payload["input"], - enclavePublicKey: Uint8Array, + payload: Payload["input"], + enclavePublicKey: Uint8Array, ): { encryptedPayload: EncryptedPayload; ephemeralPrivateKey: Uint8Array } { - const ephemeralPrivateKey = randomBytes(32); - // Generate ephemeral keypair - const ephemeralPublicKey = x25519.getPublicKey(ephemeralPrivateKey); - - // Derive shared secret using X25519 - const sharedSecret = x25519.getSharedSecret( - ephemeralPrivateKey, - enclavePublicKey, - ); - - // Key derivation - const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); - - // Convert message to bytes if it's not already - const messageBytes = - typeof payload === "string" - ? new TextEncoder().encode(payload) - : new TextEncoder().encode(JSON.stringify(payload)); - - // XChaCha20-Poly1305 encryption - const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 - const cipher = xchacha20poly1305(encryptionKey, nonce); - const ciphertext = cipher.encrypt(messageBytes); - - // Format the encrypted package - return { - encryptedPayload: { - ciphertext: bytesToHex(ciphertext), - ephemeralPublicKey: bytesToHex(ephemeralPublicKey), - nonce: bytesToHex(nonce), - }, - ephemeralPrivateKey: ephemeralPrivateKey, - }; + const ephemeralPrivateKey = randomBytes(32); + // Generate ephemeral keypair + const ephemeralPublicKey = x25519.getPublicKey(ephemeralPrivateKey); + + // Derive shared secret using X25519 + const sharedSecret = x25519.getSharedSecret( + ephemeralPrivateKey, + enclavePublicKey, + ); + + // Key derivation + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Convert message to bytes if it's not already + const messageBytes = + typeof payload === "string" + ? new TextEncoder().encode(payload) + : new TextEncoder().encode(JSON.stringify(payload)); + + // XChaCha20-Poly1305 encryption + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const ciphertext = cipher.encrypt(messageBytes); + + // Format the encrypted package + return { + encryptedPayload: { + ciphertext: bytesToHex(ciphertext), + ephemeralPublicKey: bytesToHex(ephemeralPublicKey), + nonce: bytesToHex(nonce), + }, + ephemeralPrivateKey: ephemeralPrivateKey, + }; } function isErrorResponse( - response: UnencryptedErrorResponse | EncryptedPayload, + response: UnencryptedErrorResponse | EncryptedPayload, ): response is UnencryptedErrorResponse { - return (response as UnencryptedErrorResponse).error !== undefined; + return (response as UnencryptedErrorResponse).error !== undefined; } function decryptFromEnclave( - encryptedPackage: EncryptedPayload, - ephemeralPrivateKey: Uint8Array, + encryptedPackage: EncryptedPayload, + ephemeralPrivateKey: Uint8Array, ) { - const { ephemeralPublicKey, nonce, ciphertext } = encryptedPackage; - - // Convert hex strings back to bytes - const pubKey = hexToBytes(ephemeralPublicKey); - const nonceBytes = hexToBytes(nonce); - const ciphertextBytes = hexToBytes(ciphertext); - - // Derive the same shared secret (from the enclave's ephemeral public key) - const sharedSecret = x25519.getSharedSecret(ephemeralPrivateKey, pubKey); - // Derive the same encryption key - const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); - - // Decrypt the ciphertext - const cipher = xchacha20poly1305(encryptionKey, nonceBytes); - const decrypted = cipher.decrypt(ciphertextBytes); - - // Convert bytes back to string and parse JSON if needed - const decryptedText = new TextDecoder().decode(decrypted); - try { - return JSON.parse(decryptedText); - } catch { - return decryptedText; - } + const { ephemeralPublicKey, nonce, ciphertext } = encryptedPackage; + + // Convert hex strings back to bytes + const pubKey = hexToBytes(ephemeralPublicKey); + const nonceBytes = hexToBytes(nonce); + const ciphertextBytes = hexToBytes(ciphertext); + + // Derive the same shared secret (from the enclave's ephemeral public key) + const sharedSecret = x25519.getSharedSecret(ephemeralPrivateKey, pubKey); + // Derive the same encryption key + const encryptionKey = hkdf(sha256, sharedSecret, undefined, "encryption", 32); + + // Decrypt the ciphertext + const cipher = xchacha20poly1305(encryptionKey, nonceBytes); + const decrypted = cipher.decrypt(ciphertextBytes); + + // Convert bytes back to string and parse JSON if needed + const decryptedText = new TextDecoder().decode(decrypted); + try { + return JSON.parse(decryptedText); + } catch { + return decryptedText; + } } export type VaultClient = { - baseUrl: string; - publicKey: Uint8Array; - headers: Record; + baseUrl: string; + publicKey: Uint8Array; + headers: Record; }; export async function createVaultClient(clientOptions?: { - baseUrl?: string; - secretKey?: string; + baseUrl?: string; + secretKey?: string; }): Promise { - const baseUrl = clientOptions?.baseUrl ?? "https://engine.thirdweb.com"; - // Construct the full URL for the fetch call - const url = new URL("api/v1/enclave", baseUrl).toString(); - - type IntrospectionResponse = { - publicKey: string; - }; - - const headers = { - // Indicate we accept JSON responses - Accept: "application/json", - ...(clientOptions?.secretKey - ? { "x-secret-key": clientOptions?.secretKey } - : {}), - }; - - try { - const response = await fetch(url, { - headers, - method: "GET", - }); - - // fetch doesn't throw on HTTP errors (like 4xx, 5xx) by default. - // Check if the request was successful (status in the range 200-299). - if (!response.ok) { - // You might want more sophisticated error handling here, - // potentially trying to parse an error message from the response body. - throw new Error( - `Failed to fetch enclave public key: ${response.status} ${response.statusText}`, - ); - } - - // Parse the JSON response body - const data = (await response.json()) as IntrospectionResponse; - - if (!data.publicKey) { - throw new Error("Invalid response format: publicKey missing"); - } - - const publicKeyBytes = hexToBytes(data.publicKey); - - return { - baseUrl, // Store baseUrl - headers, - publicKey: publicKeyBytes, - }; - } catch (error) { - // Handle network errors or JSON parsing errors - throw new Error(`Failed to fetch enclave public key: ${error}`); // Re-throw or handle as appropriate for your application - } + const baseUrl = clientOptions?.baseUrl ?? "https://engine.thirdweb.com"; + // Construct the full URL for the fetch call + const url = new URL("api/v1/enclave", baseUrl).toString(); + + type IntrospectionResponse = { + publicKey: string; + }; + + const headers = { + // Indicate we accept JSON responses + Accept: "application/json", + ...(clientOptions?.secretKey + ? { "x-secret-key": clientOptions?.secretKey } + : {}), + }; + + try { + const response = await fetch(url, { + headers, + method: "GET", + }); + + // fetch doesn't throw on HTTP errors (like 4xx, 5xx) by default. + // Check if the request was successful (status in the range 200-299). + if (!response.ok) { + // You might want more sophisticated error handling here, + // potentially trying to parse an error message from the response body. + throw new Error( + `Failed to fetch enclave public key: ${response.status} ${response.statusText}`, + ); + } + + // Parse the JSON response body + const data = (await response.json()) as IntrospectionResponse; + + if (!data.publicKey) { + throw new Error("Invalid response format: publicKey missing"); + } + + const publicKeyBytes = hexToBytes(data.publicKey); + + return { + baseUrl, // Store baseUrl + headers, + publicKey: publicKeyBytes, + }; + } catch (error) { + // Handle network errors or JSON parsing errors + throw new Error(`Failed to fetch enclave public key: ${error}`); // Re-throw or handle as appropriate for your application + } } // ========== Main API function ========== type SendRequestParams

= { - request: P["input"]; - client: VaultClient; + request: P["input"]; + client: VaultClient; }; async function sendRequest

({ - request, - client, + request, + client, }: SendRequestParams

): Promise> { - const { encryptedPayload, ephemeralPrivateKey } = encryptForEnclave( - request, - client.publicKey, - ); - - // Construct the full URL using the client's baseUrl - const url = new URL("api/v1/enclave", client.baseUrl).toString(); - - try { - const response = await fetch(url, { - // Stringify the JSON payload for the request body - body: JSON.stringify(encryptedPayload), - headers: { - ...client.headers, - Accept: "application/json", - "Content-Type": "application/json", // Good practice to specify accept header - }, - method: "POST", - }); - - // IMPORTANT: Replicate ky's throwHttpErrors: false behavior. - // We proceed to parse the body regardless of response.ok status, - // as the body itself might contain the structured error (UnencryptedErrorResponse) - // or the encrypted success payload. - - let responseData: EncryptedPayload | UnencryptedErrorResponse; - try { - responseData = await response.json(); - } catch (parseError) { - // If JSON parsing fails (e.g., 500 error with HTML body), - // construct a generic error response. - return { - data: null, - error: { - code: "FETCH_PARSE_ERROR", - message: `Failed to parse response: ${ - response.status - } ${response.statusText}. ${ - parseError instanceof Error - ? parseError.message - : String(parseError) - }`, - }, - success: false, - } as Prettify; // Cast needed because error isn't strictly EncryptedError | UnencryptedError - } - - // Now check if the *parsed* response indicates an error - if (isErrorResponse(responseData)) { - console.error("🚨 Error response from enclave:", responseData); - return { - data: null, - error: responseData.error, - success: false, // Use the error from the response body - } as Prettify; - } - - // If it's not an error response, it must be the EncryptedPayload - const decryptedResponse = decryptFromEnclave( - responseData, // No need for 'as EncryptedPayload' if isErrorResponse is accurate - ephemeralPrivateKey, - ); - - // The decrypted response should match the expected success structure P["output"] - // which includes { success: true, data: ..., error: null } - return decryptedResponse as Prettify; - } catch (error) { - // Catch network errors during the fetch itself - return { - data: null, - error: { - code: "FETCH_NETWORK_ERROR", - message: - error instanceof Error ? error.message : "Unknown network error", - }, - success: false, - } as Prettify; // Cast needed - } + const { encryptedPayload, ephemeralPrivateKey } = encryptForEnclave( + request, + client.publicKey, + ); + + // Construct the full URL using the client's baseUrl + const url = new URL("api/v1/enclave", client.baseUrl).toString(); + + try { + const response = await fetch(url, { + // Stringify the JSON payload for the request body + body: JSON.stringify(encryptedPayload), + headers: { + ...client.headers, + Accept: "application/json", + "Content-Type": "application/json", // Good practice to specify accept header + }, + method: "POST", + }); + + // IMPORTANT: Replicate ky's throwHttpErrors: false behavior. + // We proceed to parse the body regardless of response.ok status, + // as the body itself might contain the structured error (UnencryptedErrorResponse) + // or the encrypted success payload. + + let responseData: EncryptedPayload | UnencryptedErrorResponse; + try { + responseData = await response.json(); + } catch (parseError) { + // If JSON parsing fails (e.g., 500 error with HTML body), + // construct a generic error response. + return { + data: null, + error: { + code: "FETCH_PARSE_ERROR", + message: `Failed to parse response: ${ + response.status + } ${response.statusText}. ${ + parseError instanceof Error + ? parseError.message + : String(parseError) + }`, + }, + success: false, + } as Prettify; // Cast needed because error isn't strictly EncryptedError | UnencryptedError + } + + // Now check if the *parsed* response indicates an error + if (isErrorResponse(responseData)) { + console.error("🚨 Error response from enclave:", responseData); + return { + data: null, + error: responseData.error, + success: false, // Use the error from the response body + } as Prettify; + } + + // If it's not an error response, it must be the EncryptedPayload + const decryptedResponse = decryptFromEnclave( + responseData, // No need for 'as EncryptedPayload' if isErrorResponse is accurate + ephemeralPrivateKey, + ); + + // The decrypted response should match the expected success structure P["output"] + // which includes { success: true, data: ..., error: null } + return decryptedResponse as Prettify; + } catch (error) { + // Catch network errors during the fetch itself + return { + data: null, + error: { + code: "FETCH_NETWORK_ERROR", + message: + error instanceof Error ? error.message : "Unknown network error", + }, + success: false, + } as Prettify; // Cast needed + } } // ========== Generic Helper Params ========== type PayloadParams

= { - request: Prettify>; - client: VaultClient; + request: Prettify>; + client: VaultClient; }; // ========== Helper functions ========== export function ping({ client, request: options }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "ping", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "ping", + ...options, + }, + }); } export function createServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:create", + ...options, + }, + }); } export function getServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:get", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:get", + ...options, + }, + }); } export function rotateServiceAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "serviceAccount:rotate", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "serviceAccount:rotate", + ...options, + }, + }); } export function createEoa({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:create", + ...options, + }, + }); } export function listEoas({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:list", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:list", + ...options, + }, + }); } export function signTransaction({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signTransaction", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signTransaction", + ...options, + }, + }); } export function signMessage({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signMessage", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signMessage", + ...options, + }, + }); } export function createAccessToken({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:create", + ...options, + }, + }); } export function signTypedData< - Types extends TypedData, - PrimaryType extends keyof Types, + Types extends TypedData, + PrimaryType extends keyof Types, >({ - client, - request: options, + client, + request: options, }: PayloadParams>) { - return sendRequest>({ - client, - request: { - auth: options.auth, - operation: "eoa:signTypedData", - options: { - from: options.options.from, - typedData: options.options.typedData, - }, - }, - }); + return sendRequest>({ + client, + request: { + auth: options.auth, + operation: "eoa:signTypedData", + options: { + from: options.options.from, + typedData: options.options.typedData, + }, + }, + }); } export function revokeAccessToken({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:revoke", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:revoke", + ...options, + }, + }); } export function signAuthorization({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signAuthorization", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signAuthorization", + ...options, + }, + }); } export function signStructuredMessage({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "eoa:signStructuredMessage", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "eoa:signStructuredMessage", + ...options, + }, + }); } export function listAccessTokens({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "accessToken:list", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "accessToken:list", + ...options, + }, + }); } // ========== Solana Functions ========== export function createSolanaAccount({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "solana:create", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "solana:create", + ...options, + }, + }); } export function listSolanaAccounts({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "solana:list", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "solana:list", + ...options, + }, + }); } export function signSolanaTransaction({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "solana:signTransaction", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "solana:signTransaction", + ...options, + }, + }); } /** * Reconstruct a signed solana transaction from the vault signature using @solana/kit */ export function reconstructSolanaSignedTransaction( - base64Transaction: string, - base58Signature: string, - signerPubkey: string, + base64Transaction: string, + base58Signature: string, + signerPubkey: string, ): Uint8Array { - // Decode the base64 transaction into bytes - const base64TransactionBytes = new Uint8Array( - Buffer.from(base64Transaction, "base64"), - ); - // Decode the transaction to get its structure - const transactionDecoder = getTransactionDecoder(); - const transaction = transactionDecoder.decode(base64TransactionBytes); - - // Decode the base58 signature to bytes - const base58Encoder = getBase58Encoder(); - const signatureBytes = base58Encoder.encode(base58Signature); - - // Add the signature to the transaction - const signedTransaction = { - ...transaction, - signatures: { - ...transaction.signatures, - [address(signerPubkey)]: signatureBytes, - }, - }; - - // Re-encode the signed transaction - const transactionEncoder = getTransactionEncoder(); - const signedTransactionBytes = transactionEncoder.encode(signedTransaction); - - return new Uint8Array(signedTransactionBytes); + // Decode the base64 transaction into bytes + const base64TransactionBytes = new Uint8Array( + Buffer.from(base64Transaction, "base64"), + ); + // Decode the transaction to get its structure + const transactionDecoder = getTransactionDecoder(); + const transaction = transactionDecoder.decode(base64TransactionBytes); + + // Decode the base58 signature to bytes + const base58Encoder = getBase58Encoder(); + const signatureBytes = base58Encoder.encode(base58Signature); + + // Add the signature to the transaction + const signedTransaction = { + ...transaction, + signatures: { + ...transaction.signatures, + [address(signerPubkey)]: signatureBytes, + }, + }; + + // Re-encode the signed transaction + const transactionEncoder = getTransactionEncoder(); + const signedTransactionBytes = transactionEncoder.encode(signedTransaction); + + return new Uint8Array(signedTransactionBytes); } export function signSolanaMessage({ - client, - request: options, + client, + request: options, }: PayloadParams) { - return sendRequest({ - client, - request: { - operation: "solana:signMessage", - ...options, - }, - }); + return sendRequest({ + client, + request: { + operation: "solana:signMessage", + ...options, + }, + }); } const SIGNED_TOKEN_PREFIX = "vt_sat_"; const DEFAULT_SIGNING_CONTEXT = "encryption"; // Default context for HKDF export interface CreateSignedAccessTokenParams { - /** The VaultClient instance (used to get the enclave public key). */ - vaultClient: VaultClient; - /** The base access token string obtained from the createAccessToken API call. */ - baseAccessToken: string; - /** The specific policies to embed in the signed token's claims. */ - additionalPolicies: PolicyComponent[]; - /** The desired expiration time for the signed token (Unix timestamp in seconds). */ - expiryTimestamp: number; - /** Optional: The context string for HKDF key derivation. Defaults to "encryption". MUST match server expectation. */ - signingContext?: string; + /** The VaultClient instance (used to get the enclave public key). */ + vaultClient: VaultClient; + /** The base access token string obtained from the createAccessToken API call. */ + baseAccessToken: string; + /** The specific policies to embed in the signed token's claims. */ + additionalPolicies: PolicyComponent[]; + /** The desired expiration time for the signed token (Unix timestamp in seconds). */ + expiryTimestamp: number; + /** Optional: The context string for HKDF key derivation. Defaults to "encryption". MUST match server expectation. */ + signingContext?: string; } /** @@ -577,88 +577,88 @@ export interface CreateSignedAccessTokenParams { * @throws If any cryptographic operation or JWT signing fails. */ export async function createSignedAccessToken({ - vaultClient, - baseAccessToken, - additionalPolicies, - expiryTimestamp, - signingContext = DEFAULT_SIGNING_CONTEXT, + vaultClient, + baseAccessToken, + additionalPolicies, + expiryTimestamp, + signingContext = DEFAULT_SIGNING_CONTEXT, }: CreateSignedAccessTokenParams): Promise { - if (!vaultClient || !vaultClient.publicKey) { - throw new Error("Vault client or enclave public key is missing."); - } - if (!baseAccessToken) { - throw new Error("Base access token is required."); - } - if (!additionalPolicies) { - throw new Error("Additional policies are required."); - } - if (typeof expiryTimestamp !== "number" || expiryTimestamp <= 0) { - throw new Error("Valid expiry timestamp is required."); - } - - try { - const enclavePublicKey = vaultClient.publicKey; - const contextBytes = new TextEncoder().encode(signingContext); - - // 1. Generate client ephemeral keys for this operation - const clientEphemeralPrivateKey = randomBytes(32); - const clientEphemeralPublicKey = x25519.getPublicKey( - clientEphemeralPrivateKey, - ); - - // 2. Derive shared secret (Client Ephemeral Private Key + Enclave Public Key) - const sharedSecret = x25519.getSharedSecret( - clientEphemeralPrivateKey, - enclavePublicKey, - ); - - // 3. Derive encryption key using HKDF - const encryptionKey = hkdf( - sha256, - sharedSecret, - undefined, // No salt - contextBytes, // Use the provided or default context - 32, // 32 bytes key length - ); - - // 4. Encrypt the base access token string - const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 - const cipher = xchacha20poly1305(encryptionKey, nonce); - const baseTokenBytes = new TextEncoder().encode(baseAccessToken); - const ciphertext = cipher.encrypt(baseTokenBytes); - - // 5. Prepare JWT Signing Key (SHA-256 hash of the base token) - const secretBytes = new TextEncoder().encode(baseAccessToken); - const hashBuffer = await crypto.subtle.digest("SHA-256", secretBytes); - const jwtSigningKey = new Uint8Array(hashBuffer); - - // 6. Prepare JWT Claims - const claims = { - encrypted_token: bytesToHex(ciphertext), - ephemeral_public_key: bytesToHex(clientEphemeralPublicKey), - // Match Rust SignedTokenClaims struct (ensure names match server expectation) - exp: expiryTimestamp, - iat: Math.floor(Date.now() / 1000), - nonce: bytesToHex(nonce), - policies: additionalPolicies, - }; - - // 7. Sign the JWT using HS256 - const jwt = await new jose.SignJWT(claims) - .setProtectedHeader({ alg: "HS256" }) - // .setIssuedAt(claims.iat) // Included in claims - // .setExpirationTime(claims.exp) // Included in claims - .sign(jwtSigningKey); - - // 8. Prepend the prefix - const signedAccessToken = `${SIGNED_TOKEN_PREFIX}${jwt}`; - return signedAccessToken; - } catch (error) { - console.error("Error during signed access token creation:", error); - throw new Error( - `Failed to create signed access token: ${ - error instanceof Error ? error.message : String(error) - }`, - ); - } + if (!vaultClient || !vaultClient.publicKey) { + throw new Error("Vault client or enclave public key is missing."); + } + if (!baseAccessToken) { + throw new Error("Base access token is required."); + } + if (!additionalPolicies) { + throw new Error("Additional policies are required."); + } + if (typeof expiryTimestamp !== "number" || expiryTimestamp <= 0) { + throw new Error("Valid expiry timestamp is required."); + } + + try { + const enclavePublicKey = vaultClient.publicKey; + const contextBytes = new TextEncoder().encode(signingContext); + + // 1. Generate client ephemeral keys for this operation + const clientEphemeralPrivateKey = randomBytes(32); + const clientEphemeralPublicKey = x25519.getPublicKey( + clientEphemeralPrivateKey, + ); + + // 2. Derive shared secret (Client Ephemeral Private Key + Enclave Public Key) + const sharedSecret = x25519.getSharedSecret( + clientEphemeralPrivateKey, + enclavePublicKey, + ); + + // 3. Derive encryption key using HKDF + const encryptionKey = hkdf( + sha256, + sharedSecret, + undefined, // No salt + contextBytes, // Use the provided or default context + 32, // 32 bytes key length + ); + + // 4. Encrypt the base access token string + const nonce = randomBytes(24); // 24-byte nonce for XChaCha20 + const cipher = xchacha20poly1305(encryptionKey, nonce); + const baseTokenBytes = new TextEncoder().encode(baseAccessToken); + const ciphertext = cipher.encrypt(baseTokenBytes); + + // 5. Prepare JWT Signing Key (SHA-256 hash of the base token) + const secretBytes = new TextEncoder().encode(baseAccessToken); + const hashBuffer = await crypto.subtle.digest("SHA-256", secretBytes); + const jwtSigningKey = new Uint8Array(hashBuffer); + + // 6. Prepare JWT Claims + const claims = { + encrypted_token: bytesToHex(ciphertext), + ephemeral_public_key: bytesToHex(clientEphemeralPublicKey), + // Match Rust SignedTokenClaims struct (ensure names match server expectation) + exp: expiryTimestamp, + iat: Math.floor(Date.now() / 1000), + nonce: bytesToHex(nonce), + policies: additionalPolicies, + }; + + // 7. Sign the JWT using HS256 + const jwt = await new jose.SignJWT(claims) + .setProtectedHeader({ alg: "HS256" }) + // .setIssuedAt(claims.iat) // Included in claims + // .setExpirationTime(claims.exp) // Included in claims + .sign(jwtSigningKey); + + // 8. Prepend the prefix + const signedAccessToken = `${SIGNED_TOKEN_PREFIX}${jwt}`; + return signedAccessToken; + } catch (error) { + console.error("Error during signed access token creation:", error); + throw new Error( + `Failed to create signed access token: ${ + error instanceof Error ? error.message : String(error) + }`, + ); + } } diff --git a/packages/vault-sdk/src/types.ts b/packages/vault-sdk/src/types.ts index 64d60c00ff1..4d1b07a7128 100644 --- a/packages/vault-sdk/src/types.ts +++ b/packages/vault-sdk/src/types.ts @@ -58,7 +58,7 @@ export type UnencryptedErrorResponse = { type EncryptedError = { code: string; message: string; - details?: string; + details?: string | { reason: string }; }; type GenericSuccessResponse = { @@ -373,7 +373,7 @@ export type PolicyComponent = allowlist?: string[]; // Use string for Solana addresses metadataPatterns?: MetadataRule[]; payloadPatterns?: Record; - requiredCosigners?: string[]; // Use string for Solana addresses + transactionPatterns?: SolanaTransactionPatterns; } | { type: "solana:signMessage"; @@ -387,6 +387,35 @@ export type PolicyComponent = revealSensitive: boolean; }; +// Solana transaction patterns +export type SolanaTransactionPatterns = { + programs?: ProgramAccessControl; + writableAccounts?: AccountAccessControl; + requiredCosigners?: string[]; + maxInstructions?: number; + canPayFees?: boolean; +}; + +export type ProgramAccessControl = + | { + type: "allow"; + programs: string[]; + } + | { + type: "deny"; + programs: string[]; + }; + +export type AccountAccessControl = + | { + type: "allow"; + accounts: string[]; + } + | { + type: "deny"; + accounts: string[]; + }; + type OwnerType = string; // Define based on your eoa models type CreateAccessTokenOptions = { diff --git a/packages/vault-sdk/tests/solana.test.ts b/packages/vault-sdk/tests/solana.test.ts index df2452eba64..2cf3dc7dd01 100644 --- a/packages/vault-sdk/tests/solana.test.ts +++ b/packages/vault-sdk/tests/solana.test.ts @@ -46,56 +46,6 @@ function getExplorerUrl(path: string, type: "address" | "tx" = "tx"): string { return `https://explorer.solana.com/${type}/${path}?cluster=custom&customUrl=${encodedRpcUrl}`; } -// /** -// * Reconstruct a signed transaction from the vault signature -// */ -// function reconstructSignedTransaction( -// base64Transaction: string, -// base58Signature: string, -// ): Uint8Array { -// // Decode the base64 unsigned transaction -// const transactionBytes = new Uint8Array( -// Buffer.from(base64Transaction, "base64"), -// ); - -// // Decode the base58 signature -// const signatureBytes = bs58.decode(base58Signature); - -// if (signatureBytes.length !== 64) { -// throw new Error( -// `Invalid signature length: ${signatureBytes.length}, expected 64`, -// ); -// } - -// // Wire format structure: -// // [1 byte: signature count][64 bytes per signature][message bytes] - -// // Read the signature count -// const signatureCount = transactionBytes[0]; - -// // Calculate where the message starts (after all signature slots) -// const messageStart = 1 + signatureCount * 64; - -// // Create the signed transaction buffer -// const signedTransaction = new Uint8Array(transactionBytes.length); - -// // Copy signature count -// signedTransaction[0] = signatureCount; - -// // Copy the signature into the first signature slot -// signedTransaction.set(signatureBytes, 1); - -// // Copy any remaining signature slots (should be empty/zeros) -// if (signatureCount > 1) { -// signedTransaction.set(transactionBytes.slice(1 + 64, messageStart), 1 + 64); -// } - -// // Copy the message bytes -// signedTransaction.set(transactionBytes.slice(messageStart), messageStart); - -// return signedTransaction; -// } - /** * Send a signed transaction to the Solana network */ @@ -359,8 +309,6 @@ describe("Solana Vault Integration Tests", () => { expect(accountResult.success).toBe(false); expect(accountResult.error).toBeTruthy(); - console.log("\n=== Expected Failure (No Create Permission) ==="); - console.log(`Error: ${accountResult.error}`); }); }); @@ -639,4 +587,1114 @@ describe("Solana Vault Integration Tests", () => { } }, 60000); // 60 second timeout }); + + describe("Access Token - Transaction Pattern Policies", () => { + // Helper to create a simple transfer transaction + const createTransferTransaction = async ( + from: string, + to: string, + amount: bigint, + ) => { + const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); + const signer = createNoopSigner(address(from)); + + const transferInstruction = getTransferSolInstruction({ + source: signer, + destination: address(to), + amount: lamports(amount), + }); + + const transactionMessage = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayer(address(from), tx), + (tx) => + setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstruction(transferInstruction, tx), + ); + + const compiledTransaction = compileTransaction(transactionMessage); + return getBase64EncodedWireTransaction(compiledTransaction); + }; + + describe("Program Access Control", () => { + it("should allow transaction with allowed program", async () => { + // System program ID (used for transfers) + const systemProgramId = "11111111111111111111111111111111"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "allow", + programs: [systemProgramId], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Allow System Program Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction with non-allowed program", async () => { + // Only allow a different program (not system program) + const fakeProgramId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "allow", + programs: [fakeProgramId], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Restricted Program Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + + it("should allow transaction when program is not in deny list", async () => { + // Deny a different program (not system program) + const fakeProgramId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "deny", + programs: [fakeProgramId], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Deny List Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction when program is in deny list", async () => { + // Deny system program + const systemProgramId = "11111111111111111111111111111111"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "deny", + programs: [systemProgramId], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Deny System Program Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + }); + + describe("Can Pay Fees", () => { + it("should allow fee payment when canPayFees is true", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + canPayFees: true, + }, + }, + ], + expiresAt, + metadata: { + name: "Allow Fees Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny fee payment when canPayFees is false", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + canPayFees: false, + }, + }, + ], + expiresAt, + metadata: { + name: "No Fees Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + + expect( + typeof signatureResult.error?.details === "object" + ? signatureResult.error?.details.reason + : "", + ).toContain("not authorized to pay transaction fees"); + }); + + it("should allow fee payment by default (no transactionPatterns)", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + // No transactionPatterns means default behavior (allow fees) + }, + ], + expiresAt, + metadata: { + name: "Default Behavior Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + }); + + describe("Max Instructions", () => { + it("should allow transaction within instruction limit", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + maxInstructions: 5, // Allow up to 5 instructions + }, + }, + ], + expiresAt, + metadata: { + name: "Max 5 Instructions Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + // Create transaction with 1 instruction + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction exceeding instruction limit", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + maxInstructions: 0, // No instructions allowed + }, + }, + ], + expiresAt, + metadata: { + name: "Zero Instructions Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + // Create transaction with 1 instruction (exceeds limit of 0) + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + }); + + describe("Combined Transaction Patterns", () => { + it("should enforce multiple patterns together", async () => { + const systemProgramId = "11111111111111111111111111111111"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "allow", + programs: [systemProgramId], + }, + maxInstructions: 5, + canPayFees: true, + }, + }, + ], + expiresAt, + metadata: { + name: "Combined Patterns Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should fail if any pattern is violated", async () => { + const systemProgramId = "11111111111111111111111111111111"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + programs: { + type: "allow", + programs: [systemProgramId], + }, + maxInstructions: 5, + canPayFees: false, // This will cause failure + }, + }, + ], + expiresAt, + metadata: { + name: "Combined Patterns (Violation) Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + }); + + describe("Writable Accounts Access Control", () => { + it("should allow transaction with allowed writable account", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + writableAccounts: { + type: "allow", + accounts: [senderPubkey, receiverPubkey], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Allow Writable Accounts Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction with non-allowed writable account", async () => { + // Only allow sender to be writable, not receiver + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + writableAccounts: { + type: "allow", + accounts: [senderPubkey], // Only sender, not receiver + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Restricted Writable Accounts Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + + it("should allow transaction when writable account is not in deny list", async () => { + // Deny a different account (not sender or receiver) + const fakeAccount = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + writableAccounts: { + type: "deny", + accounts: [fakeAccount], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Deny List Writable Accounts Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction when writable account is in deny list", async () => { + // Deny receiver as writable + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + writableAccounts: { + type: "deny", + accounts: [receiverPubkey], + }, + }, + }, + ], + expiresAt, + metadata: { + name: "Deny Receiver Writable Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + }); + + describe("Required Cosigners", () => { + it("should allow transaction without cosigners when none required", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + requiredCosigners: [], // No cosigners required + }, + }, + ], + expiresAt, + metadata: { + name: "No Cosigners Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny transaction when required cosigner is missing", async () => { + // Require receiver as cosigner (but it won't be in the transaction) + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + requiredCosigners: [receiverPubkey], + }, + }, + ], + expiresAt, + metadata: { + name: "Required Cosigner Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + + it("should deny transaction when multiple required cosigners are missing", async () => { + // Require multiple cosigners that won't be in the transaction + const fakeCosigner1 = "CosignerAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; + const fakeCosigner2 = "CosignerBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"; + + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + transactionPatterns: { + requiredCosigners: [fakeCosigner1, fakeCosigner2], + }, + }, + ], + expiresAt, + metadata: { + name: "Multiple Cosigners Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + + it("should allow transaction by default when no cosigners specified", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], + // No requiredCosigners field means any transaction is allowed + }, + ], + expiresAt, + metadata: { + name: "Default Cosigners Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + }); + + describe("Allowlist", () => { + it("should allow signing from account in allowlist", async () => { + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [senderPubkey], // Explicitly allow sender + }, + ], + expiresAt, + metadata: { + name: "Allowlist Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(true); + expect(signatureResult.data?.signature).toBeTruthy(); + }); + + it("should deny signing from account not in allowlist", async () => { + // Create allowlist with only receiver (not sender) + const expiresAt = new Date(Date.now() + 3600000).toISOString(); + const accessTokenResult = await createAccessToken({ + client: vaultClient, + request: { + auth: { adminKey }, + options: { + policies: [ + { + type: "solana:signTransaction", + allowlist: [receiverPubkey], // Only allow receiver, not sender + }, + ], + expiresAt, + metadata: { + name: "Restricted Allowlist Token", + }, + }, + }, + }); + + expect(accessTokenResult.success).toBe(true); + const accessToken = accessTokenResult.data?.accessToken || ""; + + const base64Transaction = await createTransferTransaction( + senderPubkey, + receiverPubkey, + 1n, + ); + + const signatureResult = await signSolanaTransaction({ + client: vaultClient, + request: { + auth: { accessToken }, + options: { + transaction: base64Transaction, + from: senderPubkey, + }, + }, + }); + + expect(signatureResult.success).toBe(false); + expect(signatureResult.error).toBeTruthy(); + }); + }); + }); }); From b22e3ff00d6d78e31a577b6eb8e05a59c0948bca Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 05:40:42 +0530 Subject: [PATCH 05/10] add .env loading --- packages/vault-sdk/package.json | 2 +- packages/vault-sdk/tests/env-setup.ts | 4 + packages/vault-sdk/vitest.config.ts | 3 + pnpm-lock.yaml | 230 ++++++++++---------------- 4 files changed, 94 insertions(+), 145 deletions(-) create mode 100644 packages/vault-sdk/tests/env-setup.ts diff --git a/packages/vault-sdk/package.json b/packages/vault-sdk/package.json index 85fdec9234c..71c12200587 100644 --- a/packages/vault-sdk/package.json +++ b/packages/vault-sdk/package.json @@ -9,10 +9,10 @@ "@noble/hashes": "1.7.2", "@solana/addresses": "^3.0.0", "@solana/keys": "^3.0.0", + "@solana/kit": "^4.0.0", "@solana/rpc": "^3.0.0", "@solana/transactions": "^3.0.0", "abitype": "1.0.8", - "@solana/kit": "^4.0.0", "jose": "6.0.11" }, "devDependencies": { diff --git a/packages/vault-sdk/tests/env-setup.ts b/packages/vault-sdk/tests/env-setup.ts new file mode 100644 index 00000000000..20c6faeb214 --- /dev/null +++ b/packages/vault-sdk/tests/env-setup.ts @@ -0,0 +1,4 @@ +import { join } from "node:path"; +import { cwd, loadEnvFile } from "node:process"; + +loadEnvFile(join(cwd(), "tests", ".env")); diff --git a/packages/vault-sdk/vitest.config.ts b/packages/vault-sdk/vitest.config.ts index b6cf1201e83..58f6496a323 100644 --- a/packages/vault-sdk/vitest.config.ts +++ b/packages/vault-sdk/vitest.config.ts @@ -1,3 +1,4 @@ +import { join } from "node:path"; import { defineConfig } from "vitest/config"; export default defineConfig({ @@ -10,5 +11,7 @@ export default defineConfig({ sequence: { shuffle: false, // Run tests in order }, + // load .env.test + setupFiles: [join(__dirname, "./tests/env-setup.ts")], }, }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e40e83ec327..652e0e2ded4 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -120,7 +120,7 @@ importers: version: 1.2.7(@types/react-dom@19.1.6(@types/react@19.1.8))(@types/react@19.1.8)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@sentry/nextjs': specifier: 9.34.0 - version: 9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9) + version: 9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9(esbuild@0.25.5)) '@shazow/whatsabi': specifier: 0.22.2 version: 0.22.2(@noble/hashes@1.8.0)(typescript@5.8.3)(zod@3.25.75) @@ -319,7 +319,7 @@ importers: version: 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) '@storybook/nextjs': specifier: 9.0.15 - version: 9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) + version: 9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) '@types/color': specifier: 4.2.0 version: 4.2.0 @@ -1631,7 +1631,7 @@ importers: version: 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) '@storybook/nextjs': specifier: 9.0.15 - version: 9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) + version: 9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) '@types/react': specifier: 19.1.8 version: 19.1.8 @@ -1671,6 +1671,9 @@ importers: '@solana/keys': specifier: ^3.0.0 version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) + '@solana/kit': + specifier: ^4.0.0 + version: 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) '@solana/rpc': specifier: ^3.0.0 version: 3.0.3(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -1693,9 +1696,6 @@ importers: '@solana-program/system': specifier: ^0.8.1 version: 0.8.1(@solana/kit@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))) - '@solana/kit': - specifier: ^4.0.0 - version: 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) bs58: specifier: ^6.0.0 version: 6.0.0 @@ -16991,7 +16991,7 @@ snapshots: react: 19.1.0 secp256k1: 5.0.1 viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - wagmi: 2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + wagmi: 2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) optionalDependencies: thirdweb: link:packages/thirdweb typescript: 5.8.3 @@ -21719,7 +21719,7 @@ snapshots: fflate: 0.8.2 viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) optionalDependencies: - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) '@privy-io/ethereum@0.0.2(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': dependencies: @@ -23878,7 +23878,7 @@ snapshots: '@sentry/core@9.34.0': {} - '@sentry/nextjs@9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9)': + '@sentry/nextjs@9.34.0(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(encoding@0.1.13)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react@19.1.0)(webpack@5.99.9(esbuild@0.25.5))': dependencies: '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.34.0 @@ -23889,7 +23889,7 @@ snapshots: '@sentry/opentelemetry': 9.34.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/core@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.57.2(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.30.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.34.0) '@sentry/react': 9.34.0(react@19.1.0) '@sentry/vercel-edge': 9.34.0 - '@sentry/webpack-plugin': 3.5.0(encoding@0.1.13)(webpack@5.99.9) + '@sentry/webpack-plugin': 3.5.0(encoding@0.1.13)(webpack@5.99.9(esbuild@0.25.5)) chalk: 3.0.0 next: 15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) resolve: 1.22.8 @@ -23966,12 +23966,12 @@ snapshots: '@opentelemetry/api': 1.9.0 '@sentry/core': 9.34.0 - '@sentry/webpack-plugin@3.5.0(encoding@0.1.13)(webpack@5.99.9)': + '@sentry/webpack-plugin@3.5.0(encoding@0.1.13)(webpack@5.99.9(esbuild@0.25.5))': dependencies: '@sentry/bundler-plugin-core': 3.5.0(encoding@0.1.13) unplugin: 1.0.1 uuid: 9.0.1 - webpack: 5.99.9 + webpack: 5.99.9(esbuild@0.25.5) transitivePeerDependencies: - encoding - supports-color @@ -25825,9 +25825,9 @@ snapshots: ts-dedent: 2.2.0 vite: 7.0.1(@types/node@24.0.10)(jiti@2.4.2)(lightningcss@1.30.1)(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) - '@storybook/builder-webpack5@9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': + '@storybook/builder-webpack5@9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': dependencies: - '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) + '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) case-sensitive-paths-webpack-plugin: 2.4.0 cjs-module-lexer: 1.4.3 css-loader: 6.11.0(webpack@5.99.9(esbuild@0.25.5)) @@ -25835,7 +25835,7 @@ snapshots: fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.8.3)(webpack@5.99.9(esbuild@0.25.5)) html-webpack-plugin: 5.6.3(webpack@5.99.9(esbuild@0.25.5)) magic-string: 0.30.17 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) style-loader: 3.3.4(webpack@5.99.9(esbuild@0.25.5)) terser-webpack-plugin: 5.3.14(esbuild@0.25.5)(webpack@5.99.9(esbuild@0.25.5)) ts-dedent: 2.2.0 @@ -25852,33 +25852,6 @@ snapshots: - uglify-js - webpack-cli - '@storybook/builder-webpack5@9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': - dependencies: - '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) - case-sensitive-paths-webpack-plugin: 2.4.0 - cjs-module-lexer: 1.4.3 - css-loader: 6.11.0(webpack@5.99.9) - es-module-lexer: 1.7.0 - fork-ts-checker-webpack-plugin: 8.0.0(typescript@5.8.3)(webpack@5.99.9) - html-webpack-plugin: 5.6.3(webpack@5.99.9) - magic-string: 0.30.17 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) - style-loader: 3.3.4(webpack@5.99.9) - terser-webpack-plugin: 5.3.14(webpack@5.99.9) - ts-dedent: 2.2.0 - webpack: 5.99.9 - webpack-dev-middleware: 6.1.3(webpack@5.99.9) - webpack-hot-middleware: 2.26.1 - webpack-virtual-modules: 0.6.2 - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - '@rspack/core' - - '@swc/core' - - esbuild - - uglify-js - - webpack-cli - '@storybook/builder-webpack5@9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': dependencies: '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) @@ -25933,7 +25906,7 @@ snapshots: react: 19.1.0 react-dom: 19.1.0(react@19.1.0) - '@storybook/nextjs@9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5))': + '@storybook/nextjs@9.0.15(esbuild@0.25.5)(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5))': dependencies: '@babel/core': 7.28.0 '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) @@ -25949,9 +25922,9 @@ snapshots: '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) '@babel/runtime': 7.27.6 '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-hot-middleware@2.26.1)(webpack@5.99.9(esbuild@0.25.5)) - '@storybook/builder-webpack5': 9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) - '@storybook/preset-react-webpack': 9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) - '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3) + '@storybook/builder-webpack5': 9.0.15(esbuild@0.25.5)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@storybook/preset-react-webpack': 9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) + '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) '@types/semver': 7.7.0 babel-loader: 9.2.1(@babel/core@7.28.0)(webpack@5.99.9(esbuild@0.25.5)) css-loader: 6.11.0(webpack@5.99.9(esbuild@0.25.5)) @@ -25967,7 +25940,7 @@ snapshots: resolve-url-loader: 5.0.0 sass-loader: 14.2.1(webpack@5.99.9(esbuild@0.25.5)) semver: 7.7.2 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) + storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) style-loader: 3.3.4(webpack@5.99.9(esbuild@0.25.5)) styled-jsx: 5.1.7(@babel/core@7.28.0)(react@19.1.0) tsconfig-paths: 4.2.0 @@ -25993,66 +25966,6 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/nextjs@9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9)': - dependencies: - '@babel/core': 7.28.0 - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.28.0) - '@babel/plugin-syntax-import-assertions': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-class-properties': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-export-namespace-from': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-numeric-separator': 7.27.1(@babel/core@7.28.0) - '@babel/plugin-transform-object-rest-spread': 7.28.0(@babel/core@7.28.0) - '@babel/plugin-transform-runtime': 7.28.0(@babel/core@7.28.0) - '@babel/preset-env': 7.28.0(@babel/core@7.28.0) - '@babel/preset-react': 7.27.1(@babel/core@7.28.0) - '@babel/preset-typescript': 7.27.1(@babel/core@7.28.0) - '@babel/runtime': 7.27.6 - '@pmmmwh/react-refresh-webpack-plugin': 0.5.17(react-refresh@0.14.2)(type-fest@4.41.0)(webpack-hot-middleware@2.26.1)(webpack@5.99.9) - '@storybook/builder-webpack5': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@storybook/preset-react-webpack': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@storybook/react': 9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3) - '@types/semver': 7.7.0 - babel-loader: 9.2.1(@babel/core@7.28.0)(webpack@5.99.9) - css-loader: 6.11.0(webpack@5.99.9) - image-size: 2.0.2 - loader-utils: 3.3.1 - next: 15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - node-polyfill-webpack-plugin: 2.0.1(webpack@5.99.9) - postcss: 8.5.6 - postcss-loader: 8.1.1(postcss@8.5.6)(typescript@5.8.3)(webpack@5.99.9) - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - react-refresh: 0.14.2 - resolve-url-loader: 5.0.0 - sass-loader: 14.2.1(webpack@5.99.9) - semver: 7.7.2 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) - style-loader: 3.3.4(webpack@5.99.9) - styled-jsx: 5.1.7(@babel/core@7.28.0)(react@19.1.0) - tsconfig-paths: 4.2.0 - tsconfig-paths-webpack-plugin: 4.2.0 - optionalDependencies: - typescript: 5.8.3 - webpack: 5.99.9 - transitivePeerDependencies: - - '@rspack/core' - - '@swc/core' - - '@types/webpack' - - babel-plugin-macros - - esbuild - - node-sass - - sass - - sass-embedded - - sockjs-client - - supports-color - - type-fest - - uglify-js - - webpack-cli - - webpack-dev-server - - webpack-hot-middleware - - webpack-plugin-serve - '@storybook/nextjs@9.0.15(next@15.3.5(@babel/core@7.28.0)(@opentelemetry/api@1.9.0)(@playwright/test@1.53.2)(react-dom@19.1.0(react@19.1.0))(react@19.1.0))(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(type-fest@4.41.0)(typescript@5.8.3)(webpack-hot-middleware@2.26.1)(webpack@5.99.9)': dependencies: '@babel/core': 7.28.0 @@ -26113,34 +26026,10 @@ snapshots: - webpack-hot-middleware - webpack-plugin-serve - '@storybook/preset-react-webpack@9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5))(typescript@5.8.3)': - dependencies: - '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5)) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.99.9(esbuild@0.25.5)) - '@types/semver': 7.7.0 - find-up: 7.0.0 - magic-string: 0.30.17 - react: 19.1.0 - react-docgen: 7.1.1 - react-dom: 19.1.0(react@19.1.0) - resolve: 1.22.10 - semver: 7.7.2 - storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@6.0.5) - tsconfig-paths: 4.2.0 - webpack: 5.99.9(esbuild@0.25.5) - optionalDependencies: - typescript: 5.8.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - supports-color - - uglify-js - - webpack-cli - - '@storybook/preset-react-webpack@9.0.15(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': + '@storybook/preset-react-webpack@9.0.15(esbuild@0.25.5)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10))(typescript@5.8.3)': dependencies: '@storybook/core-webpack': 9.0.15(storybook@9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10)) - '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.99.9) + '@storybook/react-docgen-typescript-plugin': 1.0.6--canary.9.0c3f3b7.0(typescript@5.8.3)(webpack@5.99.9(esbuild@0.25.5)) '@types/semver': 7.7.0 find-up: 7.0.0 magic-string: 0.30.17 @@ -26151,7 +26040,7 @@ snapshots: semver: 7.7.2 storybook: 9.0.15(@testing-library/dom@10.4.0)(bufferutil@4.0.9)(prettier@3.6.2)(utf-8-validate@5.0.10) tsconfig-paths: 4.2.0 - webpack: 5.99.9 + webpack: 5.99.9(esbuild@0.25.5) optionalDependencies: typescript: 5.8.3 transitivePeerDependencies: @@ -27497,7 +27386,7 @@ snapshots: sirv: 3.0.1 tinyglobby: 0.2.14 tinyrainbow: 2.0.0 - vitest: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) + vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.14.1)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@22.14.1)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) '@vitest/utils@3.2.4': dependencies: @@ -27621,7 +27510,7 @@ snapshots: '@metamask/sdk': 0.32.0(bufferutil@4.0.9)(encoding@0.1.13)(utf-8-validate@5.0.10) '@safe-global/safe-apps-provider': 0.18.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) '@safe-global/safe-apps-sdk': 9.1.0(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) - '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) '@walletconnect/ethereum-provider': 2.21.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) cbw-sdk: '@coinbase/wallet-sdk@3.9.3' viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) @@ -27669,6 +27558,21 @@ snapshots: - react - use-sync-external-store + '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))': + dependencies: + eventemitter3: 5.0.1 + mipd: 0.0.7(typescript@5.8.3) + viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + zustand: 5.0.0(@types/react@19.1.8)(react@19.1.0)(use-sync-external-store@1.5.0(react@19.1.0)) + optionalDependencies: + '@tanstack/query-core': 5.81.5 + typescript: 5.8.3 + transitivePeerDependencies: + - '@types/react' + - immer + - react + - use-sync-external-store + '@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@6.0.5)(zod@3.25.76))': dependencies: eventemitter3: 5.0.1 @@ -31223,8 +31127,8 @@ snapshots: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.8.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0) - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.0) eslint-plugin-react: 7.37.5(eslint@8.57.0) eslint-plugin-react-hooks: 5.2.0(eslint@8.57.0) @@ -31243,7 +31147,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0): + eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.1(supports-color@8.1.1) @@ -31254,7 +31158,7 @@ snapshots: tinyglobby: 0.2.14 unrs-resolver: 1.10.1 optionalDependencies: - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0) + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color @@ -31279,18 +31183,18 @@ snapshots: - bluebird - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0))(eslint@8.57.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 7.14.1(eslint@8.57.0)(typescript@5.8.3) eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1)(eslint@8.57.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -31301,7 +31205,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0)(eslint@8.57.0))(eslint@8.57.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.1(eslint-plugin-import@2.32.0(@typescript-eslint/parser@7.14.1(eslint@8.57.0)(typescript@5.8.3))(eslint@8.57.0))(eslint@8.57.0))(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -39014,6 +38918,44 @@ snapshots: w3c-keyname@2.2.8: {} wagmi@2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): + dependencies: + '@tanstack/react-query': 5.81.5(react@19.1.0) + '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) + '@wagmi/core': 2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.5.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)) + react: 19.1.0 + use-sync-external-store: 1.4.0(react@19.1.0) + viem: 2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) + optionalDependencies: + typescript: 5.8.3 + transitivePeerDependencies: + - '@azure/app-configuration' + - '@azure/cosmos' + - '@azure/data-tables' + - '@azure/identity' + - '@azure/keyvault-secrets' + - '@azure/storage-blob' + - '@capacitor/preferences' + - '@deno/kv' + - '@netlify/blobs' + - '@planetscale/database' + - '@react-native-async-storage/async-storage' + - '@tanstack/query-core' + - '@types/react' + - '@upstash/redis' + - '@vercel/blob' + - '@vercel/kv' + - aws4fetch + - bufferutil + - db0 + - encoding + - immer + - ioredis + - supports-color + - uploadthing + - utf-8-validate + - zod + + wagmi@2.15.6(@tanstack/query-core@5.81.5)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75): dependencies: '@tanstack/react-query': 5.81.5(react@19.1.0) '@wagmi/connectors': 5.8.5(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.0)(@babel/preset-env@7.28.0(@babel/core@7.28.0))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@types/react@19.1.8)(@wagmi/core@2.17.3(@tanstack/query-core@5.81.5)(@types/react@19.1.8)(react@19.1.0)(typescript@5.8.3)(use-sync-external-store@1.4.0(react@19.1.0))(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75)))(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.33.2(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) From 2ab9ce3fb9a9f7f6867eacde616f042d58e0bf9d Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 05:49:36 +0530 Subject: [PATCH 06/10] remove tsx dependency and add changeset --- .changeset/soft-cameras-lay.md | 5 +++++ packages/vault-sdk/package.json | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 .changeset/soft-cameras-lay.md diff --git a/.changeset/soft-cameras-lay.md b/.changeset/soft-cameras-lay.md new file mode 100644 index 00000000000..3e7a273320e --- /dev/null +++ b/.changeset/soft-cameras-lay.md @@ -0,0 +1,5 @@ +--- +"@thirdweb-dev/vault-sdk": minor +--- + +Added Vault operations support for Solana. diff --git a/packages/vault-sdk/package.json b/packages/vault-sdk/package.json index 71c12200587..4f9bfc55248 100644 --- a/packages/vault-sdk/package.json +++ b/packages/vault-sdk/package.json @@ -20,7 +20,6 @@ "@solana-program/system": "^0.8.1", "bs58": "^6.0.0", "rimraf": "6.0.1", - "tsx": "^4.0.0", "vitest": "3.2.4" }, "engines": { From 742624550de9b25e2842b4b9bc493fca74555824 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 05:52:17 +0530 Subject: [PATCH 07/10] relative file loading --- packages/vault-sdk/tests/env-setup.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packages/vault-sdk/tests/env-setup.ts b/packages/vault-sdk/tests/env-setup.ts index 20c6faeb214..29a586750ac 100644 --- a/packages/vault-sdk/tests/env-setup.ts +++ b/packages/vault-sdk/tests/env-setup.ts @@ -1,4 +1,6 @@ -import { join } from "node:path"; -import { cwd, loadEnvFile } from "node:process"; +import { dirname, join } from "node:path"; +import { loadEnvFile } from "node:process"; +import { fileURLToPath } from "node:url"; -loadEnvFile(join(cwd(), "tests", ".env")); +const __dirname = dirname(fileURLToPath(import.meta.url)); +loadEnvFile(join(__dirname, ".env")); From 4398de39a03022bd4b4302a597e07404b2446e05 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 05:54:54 +0530 Subject: [PATCH 08/10] remove misleading comments --- packages/vault-sdk/tests/solana.test.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/vault-sdk/tests/solana.test.ts b/packages/vault-sdk/tests/solana.test.ts index 2cf3dc7dd01..9b136f36777 100644 --- a/packages/vault-sdk/tests/solana.test.ts +++ b/packages/vault-sdk/tests/solana.test.ts @@ -314,7 +314,7 @@ describe("Solana Vault Integration Tests", () => { describe("Transaction Creation and Signing", () => { it("should create a valid transfer transaction", async () => { - const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + const transferAmount = lamports(100_000_000n); // Get latest blockhash const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); @@ -348,7 +348,7 @@ describe("Solana Vault Integration Tests", () => { }); it("should sign transaction with vault and return valid signature", async () => { - const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + const transferAmount = lamports(100_000_000n); // Get latest blockhash const { value: latestBlockhash } = await rpc.getLatestBlockhash().send(); @@ -404,7 +404,7 @@ describe("Solana Vault Integration Tests", () => { describe("End-to-End Transfer", () => { it("should create, sign, and broadcast a SOL transfer", async () => { - const transferAmount = lamports(100_000_000n); // 1 lamport - minimum possible + const transferAmount = lamports(100_000_000n); // Get sender's initial balance const initialBalance = await rpc.getBalance(address(senderPubkey)).send(); @@ -510,7 +510,7 @@ describe("Solana Vault Integration Tests", () => { describe("Multiple Transfers", () => { it("should handle multiple sequential transfers", async () => { const numTransfers = 3; - const transferAmount = lamports(100_000_000n); // 1 lamport each - minimum possible + const transferAmount = lamports(100_000_000n); const signatures: string[] = []; From bae3f7b305240c1b67992babefe89705d4a7b3eb Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 05:57:54 +0530 Subject: [PATCH 09/10] update lockfile --- pnpm-lock.yaml | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 67395c388bd..ce60bbea88e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1444,7 +1444,7 @@ importers: version: 2.37.9(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) x402: specifier: 0.6.1 - version: 0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.4)(@babel/preset-env@7.28.0(@babel/core@7.28.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.2)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + version: 0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.4)(@babel/preset-env@7.28.0(@babel/core@7.28.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.2)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) zod: specifier: 3.25.75 version: 3.25.75 @@ -1751,9 +1751,6 @@ importers: rimraf: specifier: 6.0.1 version: 6.0.1 - tsx: - specifier: ^4.0.0 - version: 4.20.3 vitest: specifier: 3.2.4 version: 3.2.4(@types/debug@4.1.12)(@types/node@24.0.10)(@vitest/ui@3.2.4)(happy-dom@18.0.1)(jiti@2.4.2)(lightningcss@1.30.1)(msw@2.10.2(@types/node@24.0.10)(typescript@5.8.3))(terser@5.43.1)(tsx@4.20.3)(yaml@2.8.0) @@ -26346,22 +26343,22 @@ snapshots: '@socket.io/component-emitter@3.1.2': {} - '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana-program/system@0.8.1(@solana/kit@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)))': dependencies: '@solana/kit': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5)) - '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/sysvars': 4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': + '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/accounts@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)': dependencies: @@ -26705,7 +26702,7 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -26718,11 +26715,11 @@ snapshots: '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-parsed-types': 2.3.0(typescript@5.8.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) typescript: 5.8.3 @@ -26945,14 +26942,14 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) '@solana/functional': 2.3.0(typescript@5.8.3) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) '@solana/subscribable': 2.3.0(typescript@5.8.3) typescript: 5.8.3 - ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10) + ws: 8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10) '@solana/rpc-subscriptions-channel-websocket@4.0.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@6.0.5))': dependencies: @@ -26979,7 +26976,7 @@ snapshots: '@solana/subscribable': 4.0.0(typescript@5.8.3) typescript: 5.8.3 - '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/errors': 2.3.0(typescript@5.8.3) '@solana/fast-stable-stringify': 2.3.0(typescript@5.8.3) @@ -26987,7 +26984,7 @@ snapshots: '@solana/promises': 2.3.0(typescript@5.8.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.8.3) '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.8.3) '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -27245,7 +27242,7 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))': + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -27253,7 +27250,7 @@ snapshots: '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/promises': 2.3.0(typescript@5.8.3) '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3) @@ -42143,14 +42140,14 @@ snapshots: bufferutil: 4.0.9 utf-8-validate: 6.0.5 - x402@0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.4)(@babel/preset-env@7.28.0(@babel/core@7.28.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.2)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)): + x402@0.6.1(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.4)(@babel/preset-env@7.28.0(@babel/core@7.28.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3))(@tanstack/query-core@5.90.2)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(fastestsmallesttextencoderdecoder@1.0.22)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)): dependencies: '@scure/base': 1.2.6 - '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))) - '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) - '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10))) + '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)))(@solana/sysvars@4.0.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.8.3)(ws@8.18.3(bufferutil@4.0.9)(utf-8-validate@5.0.10)) viem: 2.37.9(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75) wagmi: 2.15.6(@react-native-async-storage/async-storage@2.2.0(react-native@0.78.1(@babel/core@7.28.4)(@babel/preset-env@7.28.0(@babel/core@7.28.4))(@types/react@19.1.8)(bufferutil@4.0.9)(react@19.1.0)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.90.2)(@tanstack/react-query@5.81.5(react@19.1.0))(@types/react@19.1.8)(aws4fetch@1.0.20)(bufferutil@4.0.9)(encoding@0.1.13)(ioredis@5.6.1)(react@19.1.0)(typescript@5.8.3)(utf-8-validate@5.0.10)(viem@2.37.9(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.75))(zod@3.25.75) zod: 3.25.75 From 04560599117ec68549e635aeb3316ea4f9513656 Mon Sep 17 00:00:00 2001 From: Prithvish Baidya Date: Sat, 11 Oct 2025 06:03:52 +0530 Subject: [PATCH 10/10] skip vault tests on CI --- packages/vault-sdk/package.json | 2 +- packages/vault-sdk/tests/env-setup.ts | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/vault-sdk/package.json b/packages/vault-sdk/package.json index 4f9bfc55248..90b449be013 100644 --- a/packages/vault-sdk/package.json +++ b/packages/vault-sdk/package.json @@ -59,7 +59,7 @@ "build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json", "build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap", "clean": "rimraf dist", - "test": "vitest", + "test:solana": "vitest ./tests/solana.test.ts", "dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch", "fix": "biome check ./src --fix", "format": "biome format ./src --write", diff --git a/packages/vault-sdk/tests/env-setup.ts b/packages/vault-sdk/tests/env-setup.ts index 29a586750ac..afc7d9be561 100644 --- a/packages/vault-sdk/tests/env-setup.ts +++ b/packages/vault-sdk/tests/env-setup.ts @@ -3,4 +3,9 @@ import { loadEnvFile } from "node:process"; import { fileURLToPath } from "node:url"; const __dirname = dirname(fileURLToPath(import.meta.url)); -loadEnvFile(join(__dirname, ".env")); + +try { + loadEnvFile(join(__dirname, ".env")); +} catch (_error) { + console.warn("No .env file found, using default values"); +}