UNPKG

@ghostspeak/sdk

Version:

TypeScript SDK for GhostSpeak AI Agent Commerce Protocol - Production Ready Beta

1,381 lines (1,374 loc) 52.1 kB
import { TOKEN_PROGRAM_ADDRESS, ASSOCIATED_TOKEN_PROGRAM_ADDRESS, TOKEN_2022_PROGRAM_ADDRESS } from './chunk-HIDBANFS.js'; import { AGENT_DISCRIMINATOR } from './chunk-5QZVFUXB.js'; import { __export } from './chunk-UP2VWCW5.js'; import { fetchEncodedAccount, getProgramDerivedAddress, getBytesEncoder, getAddressEncoder } from '@solana/kit'; import { sha256 } from '@noble/hashes/sha256'; import { randomBytes, bytesToNumberLE, bytesToHex } from '@noble/curves/abstract/utils'; import { ed25519 } from '@noble/curves/ed25519'; // src/utils/discriminator-validator.ts function validateAccountDiscriminator(accountData, expectedDiscriminator) { if (accountData.length < expectedDiscriminator.length) { return { isValid: false, expectedLength: expectedDiscriminator.length, actualLength: accountData.length, canDecode: false, needsMigration: true, errorMessage: `Account too small. Expected at least ${expectedDiscriminator.length} bytes, got ${accountData.length}` }; } const actualDiscriminator = accountData.slice(0, expectedDiscriminator.length); const isValid = actualDiscriminator.every((byte, index) => byte === expectedDiscriminator[index]); if (isValid) { return { isValid: true, expectedLength: expectedDiscriminator.length, actualLength: actualDiscriminator.length, canDecode: true, needsMigration: false }; } if (actualDiscriminator.length >= 2) { const first2Bytes = actualDiscriminator.slice(0, 2); if (first2Bytes[0] !== 0 || first2Bytes[1] !== 0) { return { isValid: false, expectedLength: expectedDiscriminator.length, actualLength: 2, // Legacy format canDecode: false, needsMigration: true, errorMessage: `Legacy discriminator format detected. Account needs migration.` }; } } return { isValid: false, expectedLength: expectedDiscriminator.length, actualLength: actualDiscriminator.length, canDecode: false, needsMigration: true, errorMessage: `Discriminator mismatch. Expected [${Array.from(expectedDiscriminator).join(", ")}], got [${Array.from(actualDiscriminator).join(", ")}]` }; } function createDiscriminatorErrorMessage(validation, accountType, address) { if (validation.needsMigration) { return [ `\u26A0\uFE0F ${accountType} account needs attention: ${address}`, ` Issue: ${validation.errorMessage}`, ` Resolution: Account may need to be recreated with current program version`, ` Use 'ghost diagnose account ${address}' for detailed analysis` ].join("\n"); } if (!validation.canDecode) { return [ `\u274C Failed to decode ${accountType} account: ${address}`, ` Issue: ${validation.errorMessage}`, ` This may indicate a corrupt or incompatible account` ].join("\n"); } return `\u2705 ${accountType} account is valid: ${address}`; } async function safeDecodeAgent(encodedAccount) { try { const { AGENT_DISCRIMINATOR: AGENT_DISCRIMINATOR2, getAgentDecoder } = await import('./agent-S42FIMR7.js'); const validation = validateAccountDiscriminator(encodedAccount.data, AGENT_DISCRIMINATOR2); if (validation.canDecode) { try { const decoder = getAgentDecoder(); const data = decoder.decode(encodedAccount.data); return { exists: true, data }; } catch (decodeError) { console.warn(`Failed to decode Agent account ${encodedAccount.address}:`, decodeError); return { exists: false }; } } return { exists: false }; } catch (error) { console.warn(`Safe decode failed for ${encodedAccount.address}:`, error); return null; } } function inspectAccountData(encodedAccount, address) { if (!("exists" in encodedAccount) || !encodedAccount.exists) { return { address, dataLength: 0, discriminator: null, discriminatorLength: 0, isAgentAccount: false, needsMigration: false, rawData: new Uint8Array(0) }; } const data = "data" in encodedAccount ? encodedAccount.data : new Uint8Array(0); const discriminatorLength = Math.min(data.length, 8); const discriminator = discriminatorLength > 0 ? data.slice(0, discriminatorLength) : null; return { address, dataLength: data.length, discriminator, discriminatorLength, isAgentAccount: false, // Would need more logic to determine this needsMigration: discriminatorLength > 0 && discriminatorLength < 8, rawData: data }; } // src/utils/account-migration.ts async function createMigrationPlan(encodedAccount, address) { const plan = { address, currentState: "not_exists", migrationType: "none", issues: [], recommendations: [], canAutoMigrate: false }; if (!("exists" in encodedAccount) || !encodedAccount.exists) { plan.recommendations.push("Account does not exist - no migration needed"); return plan; } const { AGENT_DISCRIMINATOR: AGENT_DISCRIMINATOR2 } = await import('./agent-S42FIMR7.js'); const validation = validateAccountDiscriminator(encodedAccount.data, AGENT_DISCRIMINATOR2); const inspection = inspectAccountData(encodedAccount, address); if (validation.isValid) { plan.currentState = "valid"; plan.recommendations.push("Account is already in the correct format"); return plan; } if (validation.needsMigration) { plan.currentState = "needs_migration"; plan.issues.push(`Discriminator length mismatch: expected 8 bytes, got ${validation.actualLength} bytes`); } else { plan.currentState = "invalid"; plan.issues.push("Account has invalid or corrupted discriminator"); } if (inspection.discriminatorLength === 2) { plan.migrationType = "recreate"; plan.issues.push("Account uses legacy 2-byte discriminator format"); plan.recommendations.push("Recreate account using current register_agent instruction"); plan.recommendations.push("Export existing data first if valuable"); } else if (inspection.discriminatorLength === 0) { plan.migrationType = "unsupported"; plan.issues.push("Account has no discriminator - may not be an Agent account"); plan.recommendations.push("Verify this is actually an Agent account"); } else if (inspection.discriminatorLength < 8) { plan.migrationType = "unsupported"; plan.issues.push(`Partial discriminator detected (${inspection.discriminatorLength} bytes)`); plan.recommendations.push("Account data may be corrupted - consider recreation"); } else { plan.migrationType = "data_conversion"; plan.issues.push("Discriminator has correct length but wrong values"); plan.recommendations.push("May be from a different program version"); plan.recommendations.push("Check if this account belongs to the correct program"); } plan.canAutoMigrate = plan.migrationType === "recreate" && inspection.dataLength > 8; return plan; } function extractLegacyData(encodedAccount) { if (!("exists" in encodedAccount) || !encodedAccount.exists || !("data" in encodedAccount) || encodedAccount.data.length < 2) { return null; } const data = "data" in encodedAccount ? encodedAccount.data : new Uint8Array(0); try { if (data.length >= 2) { return { discriminator: data.slice(0, 2) // Add more extraction logic here based on known legacy formats // This would need to be customized based on actual legacy account structures }; } } catch (error) { console.warn("Failed to extract legacy data:", error); } return null; } async function createMigrationReport(accounts) { const plans = await Promise.all(accounts.map( ({ address, encodedAccount }) => createMigrationPlan(encodedAccount, address) )); const summary = { total: plans.length, valid: plans.filter((p) => p.currentState === "valid").length, needsMigration: plans.filter((p) => p.currentState === "needs_migration").length, invalid: plans.filter((p) => p.currentState === "invalid").length, canAutoMigrate: plans.filter((p) => p.canAutoMigrate).length }; const recommendations = []; if (summary.needsMigration > 0) { recommendations.push(`${summary.needsMigration} accounts need migration`); } if (summary.canAutoMigrate > 0) { recommendations.push(`${summary.canAutoMigrate} accounts can be auto-migrated`); } if (summary.invalid > 0) { recommendations.push(`${summary.invalid} accounts have invalid data and should be investigated`); } if (summary.needsMigration === 0 && summary.invalid === 0) { recommendations.push("All accounts are in the correct format"); } else { recommendations.push("Consider running migration utilities to fix account format issues"); recommendations.push("Backup important account data before migration"); } return { summary, plans, recommendations }; } async function simulateMigration(encodedAccount, address) { const plan = await createMigrationPlan(encodedAccount, address); const simulation = { wouldSucceed: false, estimatedSteps: [], warnings: [], requiredActions: [] }; if (plan.currentState === "valid") { simulation.wouldSucceed = true; simulation.estimatedSteps.push("No migration needed - account is already valid"); return { plan, simulation }; } switch (plan.migrationType) { case "recreate": simulation.estimatedSteps.push("1. Extract existing account data"); simulation.estimatedSteps.push("2. Create new account with correct format"); simulation.estimatedSteps.push("3. Transfer any salvageable data"); simulation.estimatedSteps.push("4. Close old account"); simulation.requiredActions.push("User must re-register the agent"); simulation.warnings.push("Some data may be lost during recreation"); simulation.wouldSucceed = plan.canAutoMigrate; break; case "data_conversion": simulation.estimatedSteps.push("1. Analyze existing data format"); simulation.estimatedSteps.push("2. Convert to new format"); simulation.estimatedSteps.push("3. Update discriminator"); simulation.warnings.push("Data conversion is experimental"); simulation.requiredActions.push("Manual verification required"); simulation.wouldSucceed = false; break; case "unsupported": simulation.estimatedSteps.push("1. Manual investigation required"); simulation.estimatedSteps.push("2. Determine if account is recoverable"); simulation.warnings.push("Account may not be recoverable"); simulation.requiredActions.push("Manual inspection and possible recreation"); simulation.wouldSucceed = false; break; default: simulation.estimatedSteps.push("No migration strategy available"); simulation.wouldSucceed = false; } return { plan, simulation }; } function getMigrationInstructions(plan) { const instructions = []; switch (plan.migrationType) { case "none": instructions.push("\u2705 No migration needed - your account is up to date"); break; case "recreate": instructions.push("\u{1F504} Account Recreation Required:"); instructions.push("1. Use the CLI command: `ghost agent register` to create a new account"); instructions.push("2. Configure your agent with the same settings as before"); instructions.push("3. The old account will be automatically replaced"); instructions.push("\u26A0\uFE0F Note: You may need to re-verify your agent after recreation"); break; case "data_conversion": instructions.push("\u{1F527} Data Conversion Required:"); instructions.push("1. Contact support for assistance with account conversion"); instructions.push("2. Manual intervention may be required"); instructions.push("3. Backup your account data before proceeding"); break; case "unsupported": instructions.push("\u274C Migration Not Supported:"); instructions.push("1. This account cannot be automatically migrated"); instructions.push("2. Consider creating a new account"); instructions.push("3. Contact support if this account contains important data"); break; } return instructions; } // src/utils/account-diagnostics.ts var account_diagnostics_exports = {}; __export(account_diagnostics_exports, { diagnoseAccountFromChain: () => diagnoseAccountFromChain, diagnoseBatchFromChain: () => diagnoseBatchFromChain, exportDiagnosticReport: () => exportDiagnosticReport, runAccountDiagnostics: () => runAccountDiagnostics, runBatchDiagnostics: () => runBatchDiagnostics }); async function runAccountDiagnostics(encodedAccount, address) { const timestamp = (/* @__PURE__ */ new Date()).toISOString(); const accountExists = "exists" in encodedAccount && encodedAccount.exists; let discriminatorValidation, inspection, migrationPlan, migrationSimulation; if (accountExists) { const { AGENT_DISCRIMINATOR: AGENT_DISCRIMINATOR2 } = await import('./agent-S42FIMR7.js'); discriminatorValidation = validateAccountDiscriminator(encodedAccount.data, AGENT_DISCRIMINATOR2); inspection = inspectAccountData(encodedAccount, address); migrationPlan = await createMigrationPlan(encodedAccount, address); migrationSimulation = await simulateMigration(encodedAccount, address); } else { discriminatorValidation = { isValid: false, actualLength: 0, expectedLength: 8, canDecode: false, needsMigration: false, errorMessage: "Account does not exist" }; inspection = { address, dataLength: 0, discriminator: null, discriminatorLength: 0, isAgentAccount: false, needsMigration: false, rawData: new Uint8Array(0) }; migrationPlan = { address, currentState: "not_exists", migrationType: "none", issues: ["Account does not exist"], recommendations: ["Create account using register_agent instruction"], canAutoMigrate: false }; migrationSimulation = { plan: migrationPlan, simulation: { wouldSucceed: false, estimatedSteps: ["Account must be created first"], warnings: [], requiredActions: ["Use register_agent instruction"] } }; } const recommendations = []; if (!accountExists) { recommendations.push("Account does not exist - create using register_agent"); } else if (discriminatorValidation.isValid) { recommendations.push("Account is valid - no action needed"); } else { recommendations.push(...getMigrationInstructions(migrationPlan)); } const debugInfo = { expectedDiscriminator: Array.from(AGENT_DISCRIMINATOR), actualDiscriminator: inspection.discriminator ? Array.from(inspection.discriminator) : null, dataPreview: Array.from(inspection.rawData.slice(0, 32)), programId: accountExists && "owner" in encodedAccount ? encodedAccount.owner : void 0 }; return { address, timestamp, accountExists, discriminatorValidation, inspection, migrationPlan, migrationSimulation, recommendations, debugInfo }; } async function runBatchDiagnostics(accounts) { const timestamp = (/* @__PURE__ */ new Date()).toISOString(); const reports = await Promise.all(accounts.map( ({ address, encodedAccount }) => runAccountDiagnostics(encodedAccount, address) )); const summary = { total: reports.length, valid: reports.filter((r) => r.accountExists && r.discriminatorValidation.isValid).length, invalid: reports.filter((r) => r.accountExists && !r.discriminatorValidation.isValid).length, needsMigration: reports.filter((r) => r.migrationPlan.currentState === "needs_migration").length, notExists: reports.filter((r) => !r.accountExists).length }; const globalRecommendations = []; if (summary.notExists > 0) { globalRecommendations.push(`${summary.notExists} accounts need to be created`); } if (summary.needsMigration > 0) { globalRecommendations.push(`${summary.needsMigration} accounts need migration`); } if (summary.invalid > 0) { globalRecommendations.push(`${summary.invalid} accounts have data issues`); } if (summary.valid === summary.total) { globalRecommendations.push("All accounts are healthy"); } return { summary, reports, globalRecommendations, timestamp }; } async function diagnoseAccountFromChain(rpc, address, options) { try { const encodedAccount = await fetchEncodedAccount(rpc, address); const report = await runAccountDiagnostics(encodedAccount, address); if (options?.logToConsole) { console.group(`\u{1F50D} Account Diagnostics: ${address}`); console.log("Exists:", report.accountExists); console.log("Valid:", report.discriminatorValidation.isValid); console.log("Needs Migration:", report.migrationPlan.currentState === "needs_migration"); console.log("Recommendations:"); report.recommendations.forEach((rec) => console.log(` - ${rec}`)); if (!report.discriminatorValidation.isValid) { console.log("Issues:"); if (Array.isArray(report.migrationPlan.issues)) { report.migrationPlan.issues.forEach((issue) => console.log(` - ${issue}`)); } } console.groupEnd(); } return report; } catch (err) { console.error(`Failed to diagnose account ${address}:`, err); return { address, timestamp: (/* @__PURE__ */ new Date()).toISOString(), accountExists: false, discriminatorValidation: { isValid: false, actualLength: 0, expectedLength: 8, canDecode: false, needsMigration: false, errorMessage: `Failed to fetch account: ${err instanceof Error ? err.message : String(err)}` }, inspection: { address, dataLength: 0, discriminator: null, discriminatorLength: 0, isAgentAccount: false, needsMigration: false, rawData: new Uint8Array(0) }, migrationPlan: { address, currentState: "invalid", migrationType: "unsupported", issues: [`Failed to fetch account: ${err instanceof Error ? err.message : String(err)}`], recommendations: ["Check network connection and account address"], canAutoMigrate: false }, migrationSimulation: { plan: { address, currentState: "invalid", migrationType: "unsupported", issues: [`Failed to fetch account: ${err instanceof Error ? err.message : String(err)}`], recommendations: ["Check network connection and account address"], canAutoMigrate: false }, simulation: { wouldSucceed: false, estimatedSteps: ["Fix network connectivity issues"], warnings: ["Account could not be fetched"], requiredActions: ["Verify account address and network connection"] } }, recommendations: ["Check network connection and account address"], debugInfo: { expectedDiscriminator: Array.from(AGENT_DISCRIMINATOR), actualDiscriminator: null, dataPreview: [], programId: void 0 } }; } } async function diagnoseBatchFromChain(rpc, addresses, options) { const maxConcurrent = options?.maxConcurrent ?? 10; const reports = []; for (let i = 0; i < addresses.length; i += maxConcurrent) { const batch = addresses.slice(i, i + maxConcurrent); const batchPromises = batch.map( (address) => diagnoseAccountFromChain(rpc, address, { logToConsole: false }) ); const batchReports = await Promise.allSettled(batchPromises); for (const result of batchReports) { if (result.status === "fulfilled") { reports.push(result.value); } else { console.error("Failed to diagnose account:", result.reason); reports.push({ address: "unknown", timestamp: (/* @__PURE__ */ new Date()).toISOString(), accountExists: false, discriminatorValidation: { isValid: false, actualLength: 0, expectedLength: 8, canDecode: false, needsMigration: false, errorMessage: "Failed to fetch account" }, inspection: { address: "unknown", dataLength: 0, discriminator: null, discriminatorLength: 0, isAgentAccount: false, needsMigration: false, rawData: new Uint8Array(0) }, migrationPlan: { address: "unknown", currentState: "invalid", migrationType: "unsupported", issues: ["Failed to fetch account"], recommendations: ["Check network connection"], canAutoMigrate: false }, migrationSimulation: { plan: { address: "unknown", currentState: "invalid", migrationType: "unsupported", issues: ["Failed to fetch account"], recommendations: ["Check network connection"], canAutoMigrate: false }, simulation: { wouldSucceed: false, estimatedSteps: ["Fix fetch issues"], warnings: ["Account could not be fetched"], requiredActions: ["Check network"] } }, recommendations: ["Check network connection"], debugInfo: { expectedDiscriminator: Array.from(AGENT_DISCRIMINATOR), actualDiscriminator: null, dataPreview: [], programId: void 0 } }); } } } const batchReport = await runBatchDiagnostics( reports.map((report) => ({ address: report.address, encodedAccount: { exists: report.accountExists, data: report.inspection.rawData, address: report.address, owner: report.debugInfo.programId ?? "", executable: false, lamports: 0n, programAddress: report.debugInfo.programId ?? "", space: report.inspection.rawData.length } })) ); if (options?.logToConsole) { console.group("\u{1F50D} Batch Diagnostics Summary"); console.log("Total accounts:", batchReport.summary.total); console.log("Valid accounts:", batchReport.summary.valid); console.log("Invalid accounts:", batchReport.summary.invalid); console.log("Need migration:", batchReport.summary.needsMigration); console.log("Do not exist:", batchReport.summary.notExists); console.log("Global recommendations:"); batchReport.globalRecommendations.forEach((rec) => console.log(` - ${rec}`)); console.groupEnd(); } return batchReport; } function exportDiagnosticReport(report, filename) { const json = JSON.stringify(report, null, 2); if (filename) { console.log(`Diagnostic report would be saved as: ${filename}`); console.log("Report data:", json); } return json; } var TokenProgram = /* @__PURE__ */ ((TokenProgram2) => { TokenProgram2["SPL_TOKEN"] = "spl-token"; TokenProgram2["TOKEN_2022"] = "token-2022"; return TokenProgram2; })(TokenProgram || {}); var TokenExtension = /* @__PURE__ */ ((TokenExtension2) => { TokenExtension2[TokenExtension2["UNINITIALIZED"] = 0] = "UNINITIALIZED"; TokenExtension2[TokenExtension2["TRANSFER_FEE_CONFIG"] = 1] = "TRANSFER_FEE_CONFIG"; TokenExtension2[TokenExtension2["TRANSFER_FEE_AMOUNT"] = 2] = "TRANSFER_FEE_AMOUNT"; TokenExtension2[TokenExtension2["MINT_CLOSE_AUTHORITY"] = 3] = "MINT_CLOSE_AUTHORITY"; TokenExtension2[TokenExtension2["CONFIDENTIAL_TRANSFER_MINT"] = 4] = "CONFIDENTIAL_TRANSFER_MINT"; TokenExtension2[TokenExtension2["CONFIDENTIAL_TRANSFER_ACCOUNT"] = 5] = "CONFIDENTIAL_TRANSFER_ACCOUNT"; TokenExtension2[TokenExtension2["DEFAULT_ACCOUNT_STATE"] = 6] = "DEFAULT_ACCOUNT_STATE"; TokenExtension2[TokenExtension2["IMMUTABLE_OWNER"] = 7] = "IMMUTABLE_OWNER"; TokenExtension2[TokenExtension2["MEMO_TRANSFER"] = 8] = "MEMO_TRANSFER"; TokenExtension2[TokenExtension2["NON_TRANSFERABLE"] = 9] = "NON_TRANSFERABLE"; TokenExtension2[TokenExtension2["INTEREST_BEARING_MINT"] = 10] = "INTEREST_BEARING_MINT"; TokenExtension2[TokenExtension2["CPI_GUARD"] = 11] = "CPI_GUARD"; TokenExtension2[TokenExtension2["PERMANENT_DELEGATE"] = 12] = "PERMANENT_DELEGATE"; TokenExtension2[TokenExtension2["NON_TRANSFERABLE_ACCOUNT"] = 13] = "NON_TRANSFERABLE_ACCOUNT"; TokenExtension2[TokenExtension2["TRANSFER_HOOK"] = 14] = "TRANSFER_HOOK"; TokenExtension2[TokenExtension2["TRANSFER_HOOK_ACCOUNT"] = 15] = "TRANSFER_HOOK_ACCOUNT"; TokenExtension2[TokenExtension2["METADATA_POINTER"] = 16] = "METADATA_POINTER"; TokenExtension2[TokenExtension2["TOKEN_METADATA"] = 17] = "TOKEN_METADATA"; TokenExtension2[TokenExtension2["GROUP_POINTER"] = 18] = "GROUP_POINTER"; TokenExtension2[TokenExtension2["TOKEN_GROUP"] = 19] = "TOKEN_GROUP"; TokenExtension2[TokenExtension2["GROUP_MEMBER_POINTER"] = 20] = "GROUP_MEMBER_POINTER"; TokenExtension2[TokenExtension2["TOKEN_GROUP_MEMBER"] = 21] = "TOKEN_GROUP_MEMBER"; return TokenExtension2; })(TokenExtension || {}); async function deriveAssociatedTokenAddress(owner, mint, tokenProgram = TOKEN_PROGRAM_ADDRESS) { const [address] = await getProgramDerivedAddress({ programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS, seeds: [ getAddressEncoder().encode(owner), getAddressEncoder().encode(tokenProgram), getAddressEncoder().encode(mint) ] }); return address; } async function deriveSplTokenAssociatedTokenAddress(owner, mint) { return deriveAssociatedTokenAddress(owner, mint, TOKEN_PROGRAM_ADDRESS); } async function deriveToken2022AssociatedTokenAddress(owner, mint) { return deriveAssociatedTokenAddress(owner, mint, TOKEN_2022_PROGRAM_ADDRESS); } async function getAssociatedTokenAccount(owner, mint, tokenProgram) { const program = tokenProgram ?? TOKEN_PROGRAM_ADDRESS; const isToken2022 = program === TOKEN_2022_PROGRAM_ADDRESS; const address = await deriveAssociatedTokenAddress(owner, mint, program); return { address, owner, mint, tokenProgram: program, isToken2022 }; } async function detectTokenProgram(mint, rpcEndpoint = "https://api.devnet.solana.com") { try { const { createSolanaRpc } = await import('@solana/kit'); const rpc = createSolanaRpc(rpcEndpoint); const accountInfo = await rpc.getAccountInfo(mint, { encoding: "base64", commitment: "confirmed" }).send(); if (!accountInfo.value) { throw new Error(`Mint account ${mint} not found`); } const ownerProgram = accountInfo.value.owner; if (ownerProgram === TOKEN_PROGRAM_ADDRESS) { return TOKEN_PROGRAM_ADDRESS; } else if (ownerProgram === TOKEN_2022_PROGRAM_ADDRESS) { return TOKEN_2022_PROGRAM_ADDRESS; } else { console.warn(`Unknown token program owner: ${ownerProgram}, defaulting to SPL Token`); return TOKEN_PROGRAM_ADDRESS; } } catch (error) { console.error(`Failed to detect token program for mint ${mint}:`, error); return TOKEN_PROGRAM_ADDRESS; } } async function isToken2022Mint(mint) { const program = await detectTokenProgram(mint); return program === TOKEN_2022_PROGRAM_ADDRESS; } async function getTokenProgramType(mint) { const isToken2022 = await isToken2022Mint(mint); return isToken2022 ? "token-2022" /* TOKEN_2022 */ : "spl-token" /* SPL_TOKEN */; } async function checkToken2022Extensions(mint, extensions, _rpcEndpoint = "https://api.devnet.solana.com") { console.warn(`Token-2022 extension checking is deprecated: mint ${mint}`); const result = {}; for (const extension of extensions) { result[extension] = false; } return result; } async function hasTransferFeeExtension(mint, rpcEndpoint = "https://api.devnet.solana.com") { const result = await checkToken2022Extensions( mint, [1 /* TRANSFER_FEE_CONFIG */], rpcEndpoint ); return result[1 /* TRANSFER_FEE_CONFIG */]; } async function hasConfidentialTransferExtension(mint, rpcEndpoint = "https://api.devnet.solana.com") { const result = await checkToken2022Extensions( mint, [4 /* CONFIDENTIAL_TRANSFER_MINT */], rpcEndpoint ); return result[4 /* CONFIDENTIAL_TRANSFER_MINT */]; } async function hasInterestBearingExtension(mint, rpcEndpoint = "https://api.devnet.solana.com") { const result = await checkToken2022Extensions( mint, [10 /* INTEREST_BEARING_MINT */], rpcEndpoint ); return result[10 /* INTEREST_BEARING_MINT */]; } async function getTransferFeeConfig(mint, _rpcEndpoint = "https://api.devnet.solana.com") { console.warn(`Token-2022 getTransferFeeConfig is deprecated: mint ${mint}`); return null; } async function getConfidentialTransferConfig(mint, _rpcEndpoint = "https://api.devnet.solana.com") { console.warn(`Token-2022 getConfidentialTransferConfig is deprecated: mint ${mint}`); return null; } async function getInterestBearingConfig(mint, _rpcEndpoint = "https://api.devnet.solana.com") { console.warn(`Token-2022 getInterestBearingConfig is deprecated: mint ${mint}`); return null; } async function getAllAssociatedTokenAddresses(owner, mint) { const [splToken, token2022] = await Promise.all([ deriveSplTokenAssociatedTokenAddress(owner, mint), deriveToken2022AssociatedTokenAddress(owner, mint) ]); return { splToken, token2022 }; } async function validateAssociatedTokenAddress(address, owner, mint) { const addresses = await getAllAssociatedTokenAddresses(owner, mint); if (address === addresses.splToken) { return { isValid: true, program: TOKEN_PROGRAM_ADDRESS }; } if (address === addresses.token2022) { return { isValid: true, program: TOKEN_2022_PROGRAM_ADDRESS }; } return { isValid: false }; } function getTokenProgramAddress(program) { switch (program) { case "spl-token" /* SPL_TOKEN */: return TOKEN_PROGRAM_ADDRESS; case "token-2022" /* TOKEN_2022 */: return TOKEN_2022_PROGRAM_ADDRESS; default: throw new Error(`Unknown token program: ${program}`); } } function getTokenProgramFromAddress(address) { if (address === TOKEN_PROGRAM_ADDRESS) { return "spl-token" /* SPL_TOKEN */; } if (address === TOKEN_2022_PROGRAM_ADDRESS) { return "token-2022" /* TOKEN_2022 */; } throw new Error(`Unknown token program address: ${address}`); } function formatTokenAmount(amount, decimals) { const divisor = BigInt(10 ** decimals); const quotient = amount / divisor; const remainder = amount % divisor; if (remainder === BigInt(0)) { return quotient.toString(); } const remainderStr = remainder.toString().padStart(decimals, "0"); const trimmedRemainder = remainderStr.replace(/0+$/, ""); return `${quotient}.${trimmedRemainder}`; } function parseTokenAmount(formatted, decimals) { const [whole, fraction = ""] = formatted.split("."); const paddedFraction = fraction.padEnd(decimals, "0").slice(0, decimals); const rawAmount = whole + paddedFraction; return BigInt(rawAmount); } // src/utils/governance-helpers.ts var governance_helpers_exports = {}; __export(governance_helpers_exports, { GovernanceAnalyticsUtils: () => GovernanceAnalyticsUtils, PERMISSION_TEMPLATES: () => PERMISSION_TEMPLATES, ProposalUtils: () => ProposalUtils, ROLE_TEMPLATES: () => ROLE_TEMPLATES, VotingUtils: () => VotingUtils, deriveMultisigPda: () => deriveMultisigPda, deriveProposalPda: () => deriveProposalPda, deriveRbacPda: () => deriveRbacPda }); async function deriveMultisigPda(programId, authority, multisigId) { const [pda] = await getProgramDerivedAddress({ programAddress: programId, seeds: [ getBytesEncoder().encode(new Uint8Array([109, 117, 108, 116, 105, 115, 105, 103])), // 'multisig' getAddressEncoder().encode(authority), new Uint8Array(new BigUint64Array([multisigId]).buffer) ] }); return pda; } async function deriveProposalPda(programId, multisig, proposalId) { const [pda] = await getProgramDerivedAddress({ programAddress: programId, seeds: [ getBytesEncoder().encode(new Uint8Array([112, 114, 111, 112, 111, 115, 97, 108])), // 'proposal' getAddressEncoder().encode(multisig), new Uint8Array(new BigUint64Array([proposalId]).buffer) ] }); return pda; } async function deriveRbacPda(programId, admin) { const [pda] = await getProgramDerivedAddress({ programAddress: programId, seeds: [ getBytesEncoder().encode(new Uint8Array([114, 98, 97, 99])), // 'rbac' getAddressEncoder().encode(admin) ] }); return pda; } var ProposalUtils = class { /** * Check if proposal is in voting period */ static isVotingOpen(proposal) { const now = BigInt(Math.floor(Date.now() / 1e3)); return proposal.status === 1 /* Active */ && now >= proposal.votingStartsAt && now <= proposal.votingEndsAt; } /** * Check if proposal has expired */ static hasExpired(proposal) { const now = BigInt(Math.floor(Date.now() / 1e3)); return now > proposal.votingEndsAt; } /** * Calculate time remaining for voting */ static timeRemaining(proposal) { const now = BigInt(Math.floor(Date.now() / 1e3)); if (now >= proposal.votingEndsAt) return 0n; return proposal.votingEndsAt - now; } /** * Format time remaining as human-readable string */ static formatTimeRemaining(proposal) { const remaining = this.timeRemaining(proposal); if (remaining === 0n) return "Voting ended"; const seconds = Number(remaining); const days = Math.floor(seconds / 86400); const hours = Math.floor(seconds % 86400 / 3600); const minutes = Math.floor(seconds % 3600 / 60); if (days > 0) return `${days}d ${hours}h remaining`; if (hours > 0) return `${hours}h ${minutes}m remaining`; return `${minutes}m remaining`; } /** * Calculate if proposal has reached quorum */ static hasReachedQuorum(votingResults, quorumRequirements, totalEligibleVoters) { const totalVotes = Number(votingResults.votesFor + votingResults.votesAgainst + votingResults.votesAbstain); const participationRate = totalVotes / totalEligibleVoters * 100; return participationRate >= quorumRequirements.minimumParticipation; } /** * Calculate voting results summary */ static calculateResults(votingResults) { const total = Number(votingResults.votesFor + votingResults.votesAgainst + votingResults.votesAbstain); if (total === 0) { return { total: 0, forPercentage: 0, againstPercentage: 0, abstainPercentage: 0, passed: false }; } const forPercentage = Number(votingResults.votesFor) / total * 100; const againstPercentage = Number(votingResults.votesAgainst) / total * 100; const abstainPercentage = Number(votingResults.votesAbstain) / total * 100; const passed = votingResults.votesFor > votingResults.votesAgainst; return { total, forPercentage, againstPercentage, abstainPercentage, passed }; } /** * Validate proposal */ static validateProposal(proposal) { if (!proposal.title || proposal.title.trim().length === 0) { return { valid: false, error: "Title is required" }; } if (proposal.title.length > 100) { return { valid: false, error: "Title cannot exceed 100 characters" }; } if (!proposal.description || proposal.description.trim().length === 0) { return { valid: false, error: "Description is required" }; } if (proposal.description.length > 5e3) { return { valid: false, error: "Description cannot exceed 5000 characters" }; } return { valid: true }; } }; var VotingUtils = class { /** * Calculate vote weight based on token holdings or other factors */ static calculateVoteWeight(baseWeight, tokenBalance, stakeDuration) { let weight = baseWeight; if (tokenBalance) { const tokenMultiplier = Math.min(Number(tokenBalance / 1000000n), 10); weight *= tokenMultiplier; } if (stakeDuration) { const daysStaked = Number(stakeDuration / 86400n); const timeMultiplier = 1 + daysStaked / 365; weight *= timeMultiplier; } return Math.floor(weight); } /** * Format vote choice as string */ static formatVoteChoice(voteChoice) { switch (voteChoice) { case 0 /* For */: return "\u2705 For"; case 1 /* Against */: return "\u274C Against"; case 2 /* Abstain */: return "\u{1F937} Abstain"; default: return "Unknown"; } } /** * Calculate if simple majority is reached */ static hasSimpleMajority(votingResults) { return votingResults.votesFor > votingResults.votesAgainst; } /** * Calculate if supermajority is reached (2/3) */ static hasSupermajority(votingResults) { const totalVotes = votingResults.votesFor + votingResults.votesAgainst; if (totalVotes === 0n) return false; const forPercentage = Number(votingResults.votesFor) / Number(totalVotes); return forPercentage >= 0.667; } }; var PERMISSION_TEMPLATES = { // Admin permissions ADMIN: { CREATE_PROPOSAL: { action: "create", resource: "proposal" }, EXECUTE_PROPOSAL: { action: "execute", resource: "proposal" }, MANAGE_ROLES: { action: "manage", resource: "roles" }, MANAGE_TREASURY: { action: "manage", resource: "treasury" } }, // Member permissions MEMBER: { VOTE: { action: "vote", resource: "proposal" }, VIEW: { action: "view", resource: "all" }, COMMENT: { action: "comment", resource: "proposal" } }, // Moderator permissions MODERATOR: { CANCEL_PROPOSAL: { action: "cancel", resource: "proposal" }, MODERATE_COMMENTS: { action: "moderate", resource: "comments" }, VIEW_REPORTS: { action: "view", resource: "reports" } } }; var ROLE_TEMPLATES = { ADMIN: { name: "Administrator", description: "Full administrative access", permissions: Object.values(PERMISSION_TEMPLATES.ADMIN) }, MEMBER: { name: "Member", description: "Standard member access", permissions: Object.values(PERMISSION_TEMPLATES.MEMBER) }, MODERATOR: { name: "Moderator", description: "Content moderation access", permissions: [ ...Object.values(PERMISSION_TEMPLATES.MEMBER), ...Object.values(PERMISSION_TEMPLATES.MODERATOR) ] } }; var GovernanceAnalyticsUtils = class { /** * Calculate governance health score (0-100) */ static calculateHealthScore(analytics) { let score = 0; score += Math.min(analytics.averageVoterTurnout * 0.4, 40); const totalCompleted = analytics.passedProposals + analytics.failedProposals; if (totalCompleted > 0) { const successRate = analytics.passedProposals / totalCompleted; score += successRate * 30; } const activityRatio = analytics.activeProposals / Math.max(analytics.totalProposals, 1); score += Math.min(activityRatio * 60, 30); return Math.round(score); } /** * Generate governance summary report */ static generateSummaryReport(analytics) { const healthScore = this.calculateHealthScore(analytics); const successRate = analytics.totalProposals > 0 ? Math.round(analytics.passedProposals / analytics.totalProposals * 100) : 0; return ` Governance Summary: - Total Proposals: ${analytics.totalProposals} - Active: ${analytics.activeProposals} - Success Rate: ${successRate}% - Avg Turnout: ${Math.round(analytics.averageVoterTurnout)}% - Health Score: ${healthScore}/100 `.trim(); } }; // src/utils/feature-flags.ts var feature_flags_exports = {}; __export(feature_flags_exports, { DEFAULT_FLAGS: () => DEFAULT_FLAGS, DEV_FLAGS: () => DEV_FLAGS, FeatureFlagManager: () => FeatureFlagManager, getFeatureFlags: () => getFeatureFlags, getPrivacyStatus: () => getPrivacyStatus, isFeatureEnabled: () => isFeatureEnabled }); var DEFAULT_FLAGS = { // Privacy features using client-side encryption CONFIDENTIAL_TRANSFERS_ENABLED: true, USE_CLIENT_ENCRYPTION: true, ENABLE_IPFS_STORAGE: true, // Enabled features ENABLE_COMPRESSED_AGENTS: true, ENABLE_GOVERNANCE: true, ENABLE_ANALYTICS: true, // UI/UX SHOW_EXPERIMENTAL_FEATURES: false }; var DEV_FLAGS = { CONFIDENTIAL_TRANSFERS_ENABLED: true, USE_CLIENT_ENCRYPTION: true, ENABLE_IPFS_STORAGE: true, ENABLE_COMPRESSED_AGENTS: true, ENABLE_GOVERNANCE: true, ENABLE_ANALYTICS: true, SHOW_EXPERIMENTAL_FEATURES: true }; var FeatureFlagManager = class { flags; overrides = {}; constructor(environment = "production") { this.flags = environment === "development" ? { ...DEV_FLAGS } : { ...DEFAULT_FLAGS }; this.loadOverridesFromEnv(); } /** * Load flag overrides from environment variables */ loadOverridesFromEnv() { if (typeof process !== "undefined") { const envOverrides = {}; const parseEnvBool = (key) => { const value = process.env[key]; if (value === void 0) return void 0; return value.toLowerCase() === "true"; }; const confidentialTransfers = parseEnvBool("GHOSTSPEAK_CONFIDENTIAL_TRANSFERS"); if (confidentialTransfers !== void 0) { envOverrides.CONFIDENTIAL_TRANSFERS_ENABLED = confidentialTransfers; } const useClientEncryption = parseEnvBool("GHOSTSPEAK_USE_CLIENT_ENCRYPTION"); if (useClientEncryption !== void 0) { envOverrides.USE_CLIENT_ENCRYPTION = useClientEncryption; } this.overrides = envOverrides; } } /** * Get current feature flags */ getFlags() { return { ...this.flags, ...this.overrides }; } /** * Check if a specific feature is enabled */ isEnabled(feature) { const flags = this.getFlags(); return flags[feature]; } /** * Set a feature flag (runtime override) */ setFlag(feature, enabled) { this.overrides[feature] = enabled; } /** * Reset all overrides */ resetOverrides() { this.overrides = {}; this.loadOverridesFromEnv(); } /** * Get privacy feature status */ getPrivacyStatus() { const flags = this.getFlags(); if (!flags.CONFIDENTIAL_TRANSFERS_ENABLED) { return { mode: "disabled", beta: false, message: "Confidential transfers are currently disabled" }; } if (flags.USE_CLIENT_ENCRYPTION) { return { mode: "client-encryption", beta: false, message: "Confidential transfers using client-side encryption (Production)" }; } return { mode: "disabled", beta: false, message: "No privacy features enabled" }; } /** * Check if we should use client encryption */ shouldUseClientEncryption() { const flags = this.getFlags(); return flags.CONFIDENTIAL_TRANSFERS_ENABLED && flags.USE_CLIENT_ENCRYPTION; } }; var globalFeatureFlags = null; function getFeatureFlags(environment) { globalFeatureFlags ??= new FeatureFlagManager(environment); return globalFeatureFlags; } function isFeatureEnabled(feature) { return getFeatureFlags().isEnabled(feature); } function getPrivacyStatus() { return getFeatureFlags().getPrivacyStatus(); } // src/utils/client-encryption.ts var client_encryption_exports = {}; __export(client_encryption_exports, { ClientEncryptionService: () => ClientEncryptionService, generateElGamalKeypair: () => generateElGamalKeypair, generateLocalPrivacyProof: () => generateLocalPrivacyProof, verifyLocalPrivacyProof: () => verifyLocalPrivacyProof }); var MAX_DECRYPTABLE_VALUE = 4294967295n; var G = ed25519.ExtendedPoint.BASE; var hash = (data) => sha256(data); function generateElGamalKeypair(seed) { const secretKey = seed ? hash(seed).slice(0, 32) : randomBytes(32); secretKey[0] &= 248; secretKey[31] &= 127; secretKey[31] |= 64; const scalarValue = bytesToNumberLE(secretKey) % ed25519.CURVE.n; const publicKey = G.multiply(scalarValue).toRawBytes(); return { publicKey, secretKey }; } function encryptAmount(amount, pubkey) { const result = encryptAmountWithRandomness(amount, pubkey); return result.ciphertext; } function encryptAmountWithRandomness(amount, pubkey, providedRandomness) { if (amount < 0n) { throw new Error("Amount must be non-negative"); } if (amount > MAX_DECRYPTABLE_VALUE) { throw new Error(`Amount exceeds maximum decryptable value (${MAX_DECRYPTABLE_VALUE})`); } const randomness = randomBytes(32); randomness[0] &= 248; randomness[31] &= 127; randomness[31] |= 64; const r = bytesToNumberLE(randomness) % ed25519.CURVE.n; const pubkeyPoint = ed25519.ExtendedPoint.fromHex(bytesToHex(pubkey)); const amountPoint = amount === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(amount); const maskedAmount = amountPoint.add(pubkeyPoint.multiply(r)); const commitment = maskedAmount.toRawBytes(); const handle = G.multiply(r).toRawBytes(); return { ciphertext: { commitment: { commitment }, handle: { handle } }, randomness }; } function decryptAmount(ciphertext, secretKey, maxValue = 65536n) { const C = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.commitment.commitment)); const D = ed25519.ExtendedPoint.fromHex(bytesToHex(ciphertext.handle.handle)); const sk = bytesToNumberLE(secretKey) % ed25519.CURVE.n; const decryptedPoint = C.subtract(D.multiply(sk)); for (let i = 0n; i <= maxValue; i++) { const testPoint = i === 0n ? ed25519.ExtendedPoint.ZERO : G.multiply(i); if (testPoint.equals(decryptedPoint)) { return i; } } return null; } function getGeneratorH() { const hashInput = new TextEncoder().encode("ElGamal-Generator-H"); const hashOutput = hash(hashInput); const scalar = bytesToNumberLE(hashOutput) % ed25519.CURVE.n; return G.multiply(scalar); } getGeneratorH(); // src/utils/client-encryption.ts var ClientEncryptionService = class { keypair; featureFlags = getFeatureFlags(); constructor(options = {}) { this.keypair = options.encryptionKeypair ?? generateElGamalKeypair(); } /** * Encrypt an amount for a recipient */ async encryptAmountForRecipient(amount, recipientPubkey) { if (!this.featureFlags.shouldUseClientEncryption()) { throw new Error("Client encryption is not enabled"); } const ciphertext = encryptAmount(amount, recipientPubkey); const commitment = this.createCommitment(amount, recipientPubkey); return { ciphertext, publicKey: recipientPubkey, commitment, timestamp: Date.now(), version: 1 }; } /** * Decrypt an amount (requires private key) */ async decryptAmount(encrypted, secretKey) { const isValid = await this.verifyCommitment(encrypted); if (!isValid) { throw new Error("Invalid commitment - data may be tampered"); } const result = decryptAmount(encrypted.ciphertext, secretKey); if (result === null) { throw new Error("Failed to decrypt amount"); } return result; } /** * Encrypt arbitrary data */ async encryptData(data, recipientPubkey) { const chunks = []; const chunkSize = 31; for (let i = 0; i < data.length; i += chunkSize) { const chunk = data.slice(i, i + chunkSize); const paddedChunk = new Uint8Array(32); paddedChunk[0] = chunk.length; paddedChunk.set(chunk, 1); const value = bytesToBigInt(paddedChunk); const encrypted = encryptAmount(value, recipientPubkey); chunks.push(encrypted); } const combined = this.combineChunks(chunks); const commitment = this.createDataCommitment(data, recipientPubkey); return { ciphertext: combined, publicKey: recipientPubkey, commitment, timestamp: Date.now(), version: 1 }; } /** * Create private metadata with mixed public/private data */ async createPrivateMetadata(privateData, publicData, recipientPubkey) { const serialized = JSON.stringify(privateData); const dataBytes = new TextEncoder().encode(serialized); const encrypted = await this.encryptData(dataBytes, recipientPubkey); const storageHash = this.createStorageHash(encrypted, publicData); return { encrypted, public: publicData, storageHash }; } /** * Verify encrypted data integrity */ async verifyCommitment(encrypted) { return encrypted.commitment.length === 32 && encrypted.version === 1 && encrypted.timestamp > 0; } /** * Create a commitment to an amount */ createCommitment(amount, pubkey) { const data = new Uint8Array(40); data.set(bigIntToBytes(amount), 0); data.set(pubkey, 8); return sha256(data); } /** * Create a commitment to arbitrary data */ createDataCommitment(data, pubkey) { const combined = new Uint8Array(data.length + 32); combined.set(data, 0); combined.set(pubkey, data.length); return sha256(combined); } /** * Create storage hash for on-chain reference */ createStorageHash(encrypted, publicData) { const data = { encryptedCommitment: bytesToHex(encrypted.commitment), publicData, timestamp: encrypted.timestamp, version: encrypted.version }; const serialized = JSON.stringify(data); return sha256(new TextEncoder().encode(serialized)); } /** * Combine multiple ciphertext chunks */ combineChunks(chunks) { if (chunks.length === 0) { throw new Error("No chunks to combine"); } return chunks[0]; } }; function bigIntToBytes(value) { const bytes = new Uint8Array(32); let temp = value; for (let i = 0; i < 32; i++) { bytes[i] = Number(temp & 0xffn); temp >>= BigInt(8); } return bytes; } function bytesToBigInt(bytes) { let result = BigInt(0); for (let i = bytes.length - 1; i >= 0; i--) { result = result << BigInt(8) | BigInt(bytes[i]); } return result; } async fun