@ghostspeak/sdk
Version:
TypeScript SDK for GhostSpeak AI Agent Commerce Protocol - Production Ready Beta
1,581 lines (1,576 loc) • 57.9 kB
JavaScript
import { CredentialModule, BaseModule, generateDidString, validateDidString, deriveDidDocumentPda, parseDidString, didDocumentToJson, exportAsW3CDidDocument, isDidActive, createEd25519VerificationMethod, createServiceEndpoint, AgentModule, GhostModule, GovernanceModule, MultisigModule, ReputationModule, init_MultiSourceAggregator, MultiSourceAggregator_exports, StakingModule } from './chunk-63A7F2YP.js';
import { createSignedAuthorization, verifyAuthorizationSignature, isAuthorizationExpired, isAuthorizationExhausted, serializeAuthorization, deserializeAuthorization, getAuthorizationId } from './chunk-QWQTPTZ4.js';
import { PRIVACY_CONSTANTS, PrivacyPresets, init_reputation_tag_engine, reputation_tag_engine_exports } from './chunk-HIDBANFS.js';
import { GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS } from './chunk-AWMGX3OX.js';
import { CrossmintVCClient } from './chunk-RIZZPLLB.js';
import { __toCommonJS } from './chunk-UP2VWCW5.js';
import { address } from '@solana/addresses';
// src/modules/credentials/UnifiedCredentialService.ts
var UnifiedCredentialService = class {
constructor(config) {
this.config = config;
this.credentialModule = new CredentialModule(config.programId);
if (config.crossmint) {
this.crossmintClient = new CrossmintVCClient(config.crossmint);
}
}
credentialModule;
crossmintClient;
/**
* Issue an Agent Identity credential.
* Note: logic simplified for SDK usage (mocking the on-chain part for now as per original implementation)
*/
async issueAgentIdentityCredential(params) {
const subjectData = CredentialModule.buildAgentIdentitySubject({
agentId: params.agentId,
owner: params.owner,
name: params.name,
capabilities: params.capabilities,
serviceEndpoint: params.serviceEndpoint,
frameworkOrigin: params.frameworkOrigin,
x402Enabled: params.x402Enabled,
registeredAt: params.registeredAt,
verifiedAt: params.verifiedAt
});
const credentialId = this.credentialModule.generateCredentialId(
"AgentIdentity" /* AgentIdentity */,
params.owner
);
const subjectDataHash = this.credentialModule.hashSubjectData(subjectData);
const credential = {
template: "11111111111111111111111111111111",
// Placeholder Address
subject: params.owner,
issuer: params.owner,
// Self-issued for agent identity usually, or program
credentialId,
subjectDataHash,
subjectDataUri: `ipfs://placeholder/${credentialId}`,
status: "Active" /* Active */,
signature: params.signature,
// Use provided signature
issuedAt: Math.floor(Date.now() / 1e3),
expiresAt: void 0,
revokedAt: void 0,
crossmintCredentialId: void 0
};
const mockType = {
authority: "11111111111111111111111111111111",
name: "AgentIdentity",
kind: "AgentIdentity" /* AgentIdentity */,
schemaUri: "https://ghostspeak.io/schemas/agent-identity.json",
description: "Verified AI agent identity on GhostSpeak Protocol",
isActive: true,
totalIssued: 1,
createdAt: Math.floor(Date.now() / 1e3)
};
const mockTemplate = {
credentialType: "11111111111111111111111111111111",
name: "GhostSpeak Agent Identity",
imageUri: "https://www.ghostspeak.io/assets/credential-agent.png",
issuer: params.owner,
isActive: true,
totalIssued: 1,
createdAt: Math.floor(Date.now() / 1e3),
crossmintTemplateId: this.config.crossmintTemplates?.agentIdentity
};
const w3cCredential = this.credentialModule.exportAsW3CCredential(
credential,
mockTemplate,
mockType,
subjectData
);
const result = {
solanaCredential: {
credentialId
},
w3cCredential
};
if (params.syncToCrossmint && this.crossmintClient && params.recipientEmail) {
if (!mockTemplate.crossmintTemplateId) {
result.crossmintSync = { status: "failed", error: "No template ID configured" };
} else {
try {
const crossmintResult = await this.crossmintClient.issueCredential(
mockTemplate.crossmintTemplateId,
params.recipientEmail,
subjectData
// enrichedSubject... logic handled here or in client?
// In web it was in syncToCrossmint.
);
result.crossmintSync = {
status: "synced",
credentialId: crossmintResult.credentialId,
chain: this.config.crossmint?.chain
};
} catch (error) {
result.crossmintSync = {
status: "failed",
error: error instanceof Error ? error.message : "Unknown error"
};
}
}
}
return result;
}
};
var DidModule = class extends BaseModule {
constructor(config) {
super(config);
}
// ============================================================================
// DID CRUD Operations
// ============================================================================
/**
* Create a new DID document
*
* @param signer - Transaction signer (will be the controller)
* @param params - DID creation parameters
* @returns Transaction signature
*
* @example
* ```typescript
* const signature = await didModule.create(signer, {
* controller: signer.address,
* network: 'devnet',
* verificationMethods: [{
* id: 'key-1',
* methodType: VerificationMethodType.Ed25519VerificationKey2020,
* controller: 'did:sol:devnet:...',
* publicKeyMultibase: 'z...',
* relationships: [VerificationRelationship.Authentication],
* createdAt: Date.now() / 1000,
* revoked: false
* }]
* })
* ```
*/
async create(signer, params) {
const network = params.network || "devnet";
const didString = generateDidString(network, params.controller);
validateDidString(didString);
const [didDocumentPda] = await deriveDidDocumentPda(
this.programId,
params.controller
);
const instructionGetter = async () => {
return this.buildCreateDidInstruction(
didDocumentPda,
params.controller,
didString,
params.verificationMethods || [],
params.serviceEndpoints || []
);
};
return this.execute(
"createDidDocument",
instructionGetter,
[signer]
);
}
/**
* Update an existing DID document
*
* @param signer - Transaction signer (must be the controller)
* @param params - Update parameters
* @returns Transaction signature
*
* @example
* ```typescript
* const signature = await didModule.update(signer, {
* didDocument: didPda,
* addVerificationMethod: {
* id: 'key-2',
* methodType: VerificationMethodType.X25519KeyAgreementKey2020,
* controller: 'did:sol:devnet:...',
* publicKeyMultibase: 'z...',
* relationships: [VerificationRelationship.KeyAgreement],
* createdAt: Date.now() / 1000,
* revoked: false
* }
* })
* ```
*/
async update(signer, params) {
const instructionGetter = async () => {
return this.buildUpdateDidInstruction(
params.didDocument,
signer.address,
params.addVerificationMethod || null,
params.removeVerificationMethodId || null,
params.addServiceEndpoint || null,
params.removeServiceEndpointId || null
);
};
return this.execute(
"updateDidDocument",
instructionGetter,
[signer]
);
}
/**
* Deactivate a DID document (irreversible)
*
* @param signer - Transaction signer (must be the controller)
* @param params - Deactivation parameters
* @returns Transaction signature
*
* @example
* ```typescript
* const signature = await didModule.deactivate(signer, {
* didDocument: didPda
* })
* ```
*/
async deactivate(signer, params) {
const instructionGetter = async () => {
return this.buildDeactivateDidInstruction(
params.didDocument,
signer.address
);
};
return this.execute(
"deactivateDidDocument",
instructionGetter,
[signer]
);
}
/**
* Resolve a DID document
*
* @param didOrController - DID string or controller address
* @returns DID document or null if not found
*
* @example
* ```typescript
* // Resolve by controller address
* const didDoc = await didModule.resolve(controllerAddress)
*
* // Resolve by DID string
* const didDoc = await didModule.resolve('did:sol:devnet:5VKz...')
* ```
*/
async resolve(didOrController) {
let controllerAddress;
if (typeof didOrController === "string" && didOrController.startsWith("did:sol:")) {
const { identifier } = parseDidString(didOrController);
controllerAddress = address(identifier);
} else {
controllerAddress = typeof didOrController === "string" ? address(didOrController) : didOrController;
}
const [didDocumentPda] = await deriveDidDocumentPda(
this.programId,
controllerAddress
);
return this.getAccount(didDocumentPda, "getDidDocumentDecoder");
}
// ============================================================================
// W3C Export
// ============================================================================
/**
* Export a DID document as W3C-compliant JSON
*
* @param didOrController - DID string or controller address
* @param pretty - Whether to pretty-print the JSON
* @returns W3C DID document JSON string
*
* @example
* ```typescript
* const json = await didModule.exportW3C(controllerAddress, true)
* console.log(json)
* ```
*/
async exportW3C(didOrController, pretty = true) {
const didDoc = await this.resolve(didOrController);
if (!didDoc) return null;
return didDocumentToJson(didDoc, pretty);
}
/**
* Get W3C DID document object
*
* @param didOrController - DID string or controller address
* @returns W3C DID document object or null
*/
async getW3CDocument(didOrController) {
const didDoc = await this.resolve(didOrController);
if (!didDoc) return null;
return exportAsW3CDidDocument(didDoc);
}
// ============================================================================
// Helper Methods
// ============================================================================
/**
* Derive DID document PDA for a controller
*
* @param controller - Controller address
* @returns DID document PDA and bump
*/
async deriveDidPda(controller) {
return deriveDidDocumentPda(this.programId, controller);
}
/**
* Generate a DID string for a controller
*
* @param controller - Controller address
* @param network - Network identifier
* @returns DID string
*/
generateDid(controller, network = "devnet") {
return generateDidString(network, controller);
}
/**
* Validate a DID string
*
* @param did - DID string to validate
* @returns True if valid, throws error if invalid
*/
validateDid(did) {
validateDidString(did);
return true;
}
/**
* Check if a DID is active
*
* @param didOrController - DID string or controller address
* @returns True if active, false if deactivated or not found
*/
async isActive(didOrController) {
const didDoc = await this.resolve(didOrController);
if (!didDoc) return false;
return isDidActive(didDoc);
}
// ============================================================================
// Manual Instruction Builders (until code generation)
// ============================================================================
/**
* Build create DID instruction manually
* Note: This is temporary until DID instructions are generated from IDL
*/
buildCreateDidInstruction(didDocument, controller, didString, verificationMethods, serviceEndpoints) {
throw new Error(
"DID instructions are not yet generated. Please run: bun run generate:client after adding DID instructions to the program."
);
}
/**
* Build update DID instruction manually
* Note: This is temporary until DID instructions are generated from IDL
*/
buildUpdateDidInstruction(didDocument, controller, addVerificationMethod, removeVerificationMethodId, addServiceEndpoint, removeServiceEndpointId) {
throw new Error(
"DID instructions are not yet generated. Please run: bun run generate:client after adding DID instructions to the program."
);
}
/**
* Build deactivate DID instruction manually
* Note: This is temporary until DID instructions are generated from IDL
*/
buildDeactivateDidInstruction(didDocument, controller) {
throw new Error(
"DID instructions are not yet generated. Please run: bun run generate:client after adding DID instructions to the program."
);
}
// ============================================================================
// Exported Helper Functions (re-export for convenience)
// ============================================================================
/**
* Create an Ed25519 verification method
*/
static createVerificationMethod = createEd25519VerificationMethod;
/**
* Create a service endpoint
*/
static createServiceEndpoint = createServiceEndpoint;
};
// src/modules/privacy/privacy-helpers.ts
function calculateVisibleScore(score, privacyMode, hasAccess) {
if (hasAccess || privacyMode === "Public" /* Public */) {
return {
exactScore: score,
tier: getReputationTier(score),
scoreRange: getScoreRange(score)
};
}
switch (privacyMode) {
case "TierOnly" /* TierOnly */:
return {
tier: getReputationTier(score)
};
case "RangeOnly" /* RangeOnly */:
return {
scoreRange: getScoreRange(score)
};
case "Confidential" /* Confidential */:
return {};
case "Custom" /* Custom */:
return {
tier: getReputationTier(score),
scoreRange: getScoreRange(score)
};
default:
return {};
}
}
function getReputationTier(score) {
if (score >= PRIVACY_CONSTANTS.TIER_THRESHOLDS.PLATINUM) {
return "Platinum" /* Platinum */;
} else if (score >= PRIVACY_CONSTANTS.TIER_THRESHOLDS.GOLD) {
return "Gold" /* Gold */;
} else if (score >= PRIVACY_CONSTANTS.TIER_THRESHOLDS.SILVER) {
return "Silver" /* Silver */;
} else if (score >= PRIVACY_CONSTANTS.TIER_THRESHOLDS.BRONZE) {
return "Bronze" /* Bronze */;
}
return "None" /* None */;
}
function getScoreRange(score) {
const ranges = PRIVACY_CONSTANTS.SCORE_RANGES;
if (score >= ranges.VERY_HIGH.min) {
return "VeryHigh" /* VeryHigh */;
} else if (score >= ranges.HIGH.min) {
return "High" /* High */;
} else if (score >= ranges.MEDIUM.min) {
return "Medium" /* Medium */;
} else if (score >= ranges.LOW.min) {
return "Low" /* Low */;
}
return "VeryLow" /* VeryLow */;
}
function canViewerAccess(viewerAddress, settings, agentAddress) {
if (viewerAddress === agentAddress) {
return true;
}
return settings.authorizedViewers.includes(viewerAddress);
}
function filterMetricsByVisibility(reputationData, metricVisibility, hasAccess) {
const result = {
agent: reputationData.agent
};
const isVisible = (level) => {
return hasAccess || level === "Public" /* Public */;
};
if (isVisible(metricVisibility.showScore)) {
result.exactScore = reputationData.overallScore;
}
if (isVisible(metricVisibility.showJobsCompleted)) {
result.totalJobsCompleted = reputationData.totalJobsCompleted;
}
if (isVisible(metricVisibility.showSuccessRate)) {
const total = reputationData.totalJobsCompleted + reputationData.totalJobsFailed;
result.successRate = total > 0 ? reputationData.totalJobsCompleted / total * 100 : 0;
}
if (isVisible(metricVisibility.showResponseTime)) {
result.avgResponseTime = reputationData.avgResponseTime;
}
if (isVisible(metricVisibility.showDisputes)) {
result.disputes = {
total: reputationData.disputesAgainst,
resolved: reputationData.disputesResolved
};
}
if (isVisible(metricVisibility.showEarnings) && reputationData.totalEarnings !== void 0) {
result.totalEarnings = reputationData.totalEarnings;
}
if (isVisible(metricVisibility.showRatings) && reputationData.avgRating !== void 0) {
result.avgRating = reputationData.avgRating;
}
if (isVisible(metricVisibility.showBadges) && reputationData.badges !== void 0) {
result.badges = reputationData.badges;
}
result.hasFullAccess = hasAccess;
return result;
}
function getDefaultMetricVisibility(mode) {
switch (mode) {
case "Public" /* Public */:
return {
showScore: "Public" /* Public */,
showJobsCompleted: "Public" /* Public */,
showSuccessRate: "Public" /* Public */,
showResponseTime: "Public" /* Public */,
showDisputes: "Public" /* Public */,
showEarnings: "Public" /* Public */,
showRatings: "Public" /* Public */,
showBadges: "Public" /* Public */
};
case "TierOnly" /* TierOnly */:
case "RangeOnly" /* RangeOnly */:
return {
showScore: "Private" /* Private */,
showJobsCompleted: "Private" /* Private */,
showSuccessRate: "Private" /* Private */,
showResponseTime: "Private" /* Private */,
showDisputes: "Private" /* Private */,
showEarnings: "Private" /* Private */,
showRatings: "Private" /* Private */,
showBadges: "Public" /* Public */
};
case "Confidential" /* Confidential */:
return {
showScore: "ZKProof" /* ZKProof */,
showJobsCompleted: "ZKProof" /* ZKProof */,
showSuccessRate: "ZKProof" /* ZKProof */,
showResponseTime: "ZKProof" /* ZKProof */,
showDisputes: "ZKProof" /* ZKProof */,
showEarnings: "ZKProof" /* ZKProof */,
showRatings: "ZKProof" /* ZKProof */,
showBadges: "ZKProof" /* ZKProof */
};
case "Custom" /* Custom */:
default:
return {
showScore: "Private" /* Private */,
showJobsCompleted: "Public" /* Public */,
showSuccessRate: "Public" /* Public */,
showResponseTime: "Public" /* Public */,
showDisputes: "Private" /* Private */,
showEarnings: "Private" /* Private */,
showRatings: "Public" /* Public */,
showBadges: "Public" /* Public */
};
}
}
function validatePrivacySettings(settings) {
const errors = [];
if (settings.authorizedViewers.length > PRIVACY_CONSTANTS.MAX_AUTHORIZED_VIEWERS) {
errors.push(
`Too many authorized viewers (max: ${PRIVACY_CONSTANTS.MAX_AUTHORIZED_VIEWERS})`
);
}
if (settings.mode === "Public" /* Public */) {
const hasPrivateMetric = Object.values(settings.metricVisibility).some(
(level) => level !== "Public" /* Public */
);
if (hasPrivateMetric) {
errors.push("Public mode cannot have private metrics");
}
}
return {
valid: errors.length === 0,
errors
};
}
function getTierDisplayName(tier) {
const names = {
["None" /* None */]: "Unranked",
["Bronze" /* Bronze */]: "Bronze",
["Silver" /* Silver */]: "Silver",
["Gold" /* Gold */]: "Gold",
["Platinum" /* Platinum */]: "Platinum"
};
return names[tier];
}
function getRangeDisplayString(range) {
const ranges = {
["VeryLow" /* VeryLow */]: "0-2000",
["Low" /* Low */]: "2000-5000",
["Medium" /* Medium */]: "5000-7500",
["High" /* High */]: "7500-9000",
["VeryHigh" /* VeryHigh */]: "9000-10000"
};
return ranges[range];
}
// src/modules/privacy/PrivacyModule.ts
var PrivacyModule = class extends BaseModule {
constructor(config) {
super(config);
}
/**
* Initialize privacy settings for an agent
*
* Sets up privacy controls for an agent's reputation data.
* By default, starts in Public mode with all metrics visible.
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Initialization parameters
* @returns Transaction signature
*
* @example
* ```typescript
* const signature = await privacyModule.initializePrivacy(signer, {
* agentAddress: agentPda,
* mode: PrivacyMode.TierOnly,
* metricVisibility: {
* showScore: VisibilityLevel.Private,
* showJobsCompleted: VisibilityLevel.Public,
* // ... other metrics
* }
* })
* ```
*/
async initializePrivacy(signer, params) {
const mode = params.mode ?? "Public" /* Public */;
params.metricVisibility ?? getDefaultMetricVisibility(mode);
const instructionGetter = async () => {
return {
programAddress: this.programId,
accounts: [],
data: new Uint8Array([0])
// Placeholder
};
};
return this.execute(
"initializePrivacy",
instructionGetter,
[signer]
);
}
/**
* Update privacy mode for an agent
*
* Changes how reputation data is displayed publicly.
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Update parameters
* @returns Transaction signature
*
* @example
* ```typescript
* // Switch to tier-only mode
* await privacyModule.updatePrivacyMode(signer, {
* agentAddress: agentPda,
* mode: PrivacyMode.TierOnly
* })
* ```
*/
async updatePrivacyMode(signer, params) {
const instructionGetter = async () => {
return {
programAddress: this.programId,
accounts: [],
data: new Uint8Array([1])
// Placeholder
};
};
return this.execute(
"updatePrivacyMode",
instructionGetter,
[signer]
);
}
/**
* Set metric visibility settings
*
* Configure selective disclosure for individual metrics.
* Only works in Custom privacy mode.
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Metric visibility parameters
* @returns Transaction signature
*
* @example
* ```typescript
* await privacyModule.setMetricVisibility(signer, {
* agentAddress: agentPda,
* metricVisibility: {
* showScore: VisibilityLevel.Private,
* showJobsCompleted: VisibilityLevel.Public,
* showSuccessRate: VisibilityLevel.Public,
* showResponseTime: VisibilityLevel.Public,
* showDisputes: VisibilityLevel.Private,
* showEarnings: VisibilityLevel.Private,
* showRatings: VisibilityLevel.Public,
* showBadges: VisibilityLevel.Public
* }
* })
* ```
*/
async setMetricVisibility(signer, params) {
const instructionGetter = async () => {
return {
programAddress: this.programId,
accounts: [],
data: new Uint8Array([2])
// Placeholder
};
};
return this.execute(
"setMetricVisibility",
instructionGetter,
[signer]
);
}
/**
* Grant viewer access to private reputation data
*
* Adds an address to the authorized viewers list, giving them
* full access to all private metrics.
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Grant access parameters
* @returns Transaction signature
*
* @example
* ```typescript
* // Grant access to a client
* await privacyModule.grantAccess(signer, {
* agentAddress: agentPda,
* viewer: clientAddress
* })
* ```
*/
async grantAccess(signer, params) {
const instructionGetter = async () => {
return {
programAddress: this.programId,
accounts: [],
data: new Uint8Array([3])
// Placeholder
};
};
return this.execute(
"grantAccess",
instructionGetter,
[signer]
);
}
/**
* Revoke viewer access to private reputation data
*
* Removes an address from the authorized viewers list.
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Revoke access parameters
* @returns Transaction signature
*
* @example
* ```typescript
* // Revoke access from a viewer
* await privacyModule.revokeAccess(signer, {
* agentAddress: agentPda,
* viewer: viewerAddress
* })
* ```
*/
async revokeAccess(signer, params) {
const instructionGetter = async () => {
return {
programAddress: this.programId,
accounts: [],
data: new Uint8Array([4])
// Placeholder
};
};
return this.execute(
"revokeAccess",
instructionGetter,
[signer]
);
}
/**
* Apply a privacy preset
*
* Quickly configure privacy settings using a predefined preset
* (Conservative, Balanced, or Open).
*
* @param signer - Transaction signer (must be agent owner)
* @param params - Preset parameters
* @returns Transaction signature
*
* @example
* ```typescript
* // Apply balanced preset
* await privacyModule.applyPreset(signer, {
* agentAddress: agentPda,
* preset: PrivacyPresets.BALANCED
* })
* ```
*/
async applyPreset(signer, params) {
const { preset } = params;
await this.updatePrivacyMode(signer, {
agentAddress: params.agentAddress,
mode: preset.mode
});
return this.setMetricVisibility(signer, {
agentAddress: params.agentAddress,
metricVisibility: preset.metricVisibility
});
}
/**
* Get privacy settings for an agent
*
* Fetches the current privacy configuration.
*
* @param agentAddress - Agent address
* @returns Privacy settings or null if not initialized
*
* @example
* ```typescript
* const settings = await privacyModule.getPrivacySettings(agentPda)
* if (settings) {
* console.log('Privacy mode:', settings.mode)
* console.log('Authorized viewers:', settings.authorizedViewers.length)
* }
* ```
*/
async getPrivacySettings(agentAddress) {
return {
agent: agentAddress,
mode: "Public" /* Public */,
metricVisibility: getDefaultMetricVisibility("Public" /* Public */),
authorizedViewers: [],
autoGrantClients: false,
updatedAt: Math.floor(Date.now() / 1e3)
};
}
/**
* Get visible reputation data (privacy-filtered)
*
* Fetches reputation data and applies privacy filters based on
* the viewer's access level.
*
* @param agentAddress - Agent address
* @param viewerAddress - Viewer address (for access check)
* @returns Privacy-filtered reputation data
*
* @example
* ```typescript
* // Get visible reputation for a specific viewer
* const visibleRep = await privacyModule.getVisibleReputation(
* agentPda,
* viewerAddress
* )
*
* console.log('Tier:', visibleRep.tier)
* console.log('Exact score:', visibleRep.exactScore) // Only if visible
* console.log('Has full access:', visibleRep.hasFullAccess)
* ```
*/
async getVisibleReputation(agentAddress, viewerAddress) {
let privacySettings = await this.getPrivacySettings(agentAddress);
if (!privacySettings) {
privacySettings = {
agent: agentAddress,
mode: "Public" /* Public */,
metricVisibility: getDefaultMetricVisibility("Public" /* Public */),
authorizedViewers: [],
autoGrantClients: false,
updatedAt: Math.floor(Date.now() / 1e3)
};
}
const hasAccess = canViewerAccess(viewerAddress, privacySettings, agentAddress);
const reputationData = {
agent: agentAddress,
overallScore: 7500,
// Mock data
totalJobsCompleted: 100,
totalJobsFailed: 5,
avgResponseTime: 250,
disputesAgainst: 2,
disputesResolved: 2,
totalEarnings: 5e4,
avgRating: 4.5,
badges: ["FirstJob", "TenJobs", "QuickResponder"]
};
const visibleScore = calculateVisibleScore(
reputationData.overallScore,
privacySettings.mode,
hasAccess
);
const filteredMetrics = filterMetricsByVisibility(
reputationData,
privacySettings.metricVisibility,
hasAccess
);
return {
...filteredMetrics,
privacyMode: privacySettings.mode,
...visibleScore,
hasFullAccess: hasAccess
};
}
// =====================================================
// HELPER METHODS
// =====================================================
/**
* Validate privacy settings before applying
*
* @param settings - Privacy settings to validate
* @returns Validation result
*/
validateSettings(settings) {
return validatePrivacySettings(settings);
}
/**
* Get available privacy presets
*
* @returns Record of available presets
*/
getAvailablePresets() {
return PrivacyPresets;
}
/**
* Get default metric visibility for a privacy mode
*
* @param mode - Privacy mode
* @returns Default metric visibility
*/
getDefaultVisibility(mode) {
return getDefaultMetricVisibility(mode);
}
/**
* Calculate reputation tier from score
*
* @param score - Reputation score
* @returns Reputation tier
*/
getTier(score) {
return getReputationTier(score);
}
/**
* Calculate score range from score
*
* @param score - Reputation score
* @returns Score range
*/
getRange(score) {
return getScoreRange(score);
}
// Private helper to derive privacy PDA (when privacy accounts are implemented)
async derivePrivacyPda(agentAddress) {
const { getProgramDerivedAddress, getAddressEncoder } = await import('@solana/addresses');
const addressEncoder = getAddressEncoder();
const agentBytes = addressEncoder.encode(agentAddress);
const [pda] = await getProgramDerivedAddress({
programAddress: this.programId,
seeds: [
new TextEncoder().encode("privacy_settings"),
agentBytes
]
});
return pda;
}
};
// src/modules/authorization/AuthorizationModule.ts
var DEFAULT_STORAGE_FEE = 2000000n;
var AuthorizationModule = class extends BaseModule {
constructor(config) {
super(config);
}
/**
* Create a signed authorization for a facilitator
*
* @param params - Authorization parameters
* @param agentKeypair - Agent's keypair for signing
* @returns Signed authorization
*
* @example
* ```typescript
* const authorization = await client.authorization.createAuthorization({
* authorizedSource: payAIFacilitatorAddress,
* indexLimit: 1000, // Allow 1000 reputation updates
* expiresIn: 30 * 24 * 60 * 60, // 30 days
* network: 'devnet',
* }, agentKeypair)
* ```
*/
async createAuthorization(params, agentKeypair) {
return await createSignedAuthorization(params, agentKeypair);
}
/**
* Store authorization on-chain (optional, ~0.002 SOL fee)
*
* Creates a PDA account storing the authorization for on-chain verification.
* This provides an immutable audit trail but costs rent (~0.002 SOL).
*
* **Cost vs Benefit:**
* - Off-chain (default): Free, but requires sharing signed authorization
* - On-chain: ~0.002 SOL, provides transparent audit trail
*
* **When to use on-chain storage:**
* - High-value authorizations where transparency is critical
* - Compliance/audit requirements
* - Public agent reputation systems
*
* @param authorization - Authorization to store
* @param agentSigner - Agent's signer (or facilitator if they pay fee)
* @param config - Optional storage configuration
* @returns Transaction signature
*
* @example
* ```typescript
* // Default: Agent pays ~0.002 SOL
* const sig = await client.authorization.storeAuthorizationOnChain(auth, agentSigner)
*
* // Custom fee structure
* const sig = await client.authorization.storeAuthorizationOnChain(auth, agentSigner, {
* storageFee: 1500000n, // 0.0015 SOL
* feePayedByAgent: false // Facilitator pays
* })
* ```
*/
async storeAuthorizationOnChain(authorization, agentSigner, config) {
const storageFee = this.calculateStorageFee(authorization, config);
const feePayedByAgent = config?.feePayedByAgent ?? true;
console.log(`\u{1F4B0} On-chain storage cost: ${Number(storageFee) / 1e9} SOL`);
console.log(` Fee payer: ${feePayedByAgent ? "Agent" : "Facilitator"}`);
const { getCreateAgentAuthorizationInstructionAsync } = await import('./createAgentAuthorization-KGZNXZBT.js');
const { getProgramDerivedAddress, getBytesEncoder, getAddressEncoder, getUtf8Encoder } = await import('@solana/kit');
const nonce = authorization.nonce ?? "default";
const [authorizationPda] = await getProgramDerivedAddress({
programAddress: this.getProgramId(),
seeds: [
getBytesEncoder().encode(new Uint8Array([97, 103, 101, 110, 116, 95, 97, 117, 116, 104])),
// 'agent_auth'
getAddressEncoder().encode(authorization.agentAddress),
getAddressEncoder().encode(authorization.authorizedSource),
getUtf8Encoder().encode(nonce)
// Raw bytes, no size prefix - matches Rust .as_bytes()
]
});
return await this.execute(
"createAgentAuthorization",
async () => {
return await getCreateAgentAuthorizationInstructionAsync({
agent: authorization.agentAddress,
authorization: authorizationPda,
// Provide manually derived PDA
authority: agentSigner,
authorizedSource: authorization.authorizedSource,
indexLimit: BigInt(authorization.indexLimit),
expiresAt: BigInt(authorization.expiresAt),
network: authorization.network === "mainnet-beta" ? 0 : authorization.network === "devnet" ? 1 : 2,
signature: authorization.signature,
nonce
// Pass the actual nonce value
});
},
[agentSigner]
);
}
/**
* Verify authorization signature
*
* @param authorization - Authorization to verify
* @returns True if signature is valid
*
* @example
* ```typescript
* const isValid = await client.authorization.verifySignature(authorization)
* if (!isValid) {
* throw new Error('Invalid authorization signature')
* }
* ```
*/
async verifySignature(authorization) {
return verifyAuthorizationSignature(authorization);
}
/**
* Check authorization status (without on-chain call)
*
* @param authorization - Authorization to check
* @param currentIndex - Current usage count (optional, defaults to authorization.currentIndex)
* @returns Authorization status
*/
getAuthorizationStatus(authorization, currentIndex) {
const now = Math.floor(Date.now() / 1e3);
const idx = currentIndex ?? 0;
if (isAuthorizationExpired(authorization, now)) {
return {
status: "expired",
isValid: false,
remainingUses: 0,
reason: "Authorization has expired"
};
}
if (isAuthorizationExhausted(authorization, idx)) {
return {
status: "exhausted",
isValid: false,
remainingUses: 0,
reason: "Index limit reached"
};
}
const remaining = authorization.indexLimit - idx;
return {
status: "active",
isValid: true,
remainingUses: remaining
};
}
/**
* Fetch authorization from on-chain PDA
*
* @param agentAddress - Agent's address
* @param authorizedSource - Authorized source address
* @param nonce - Optional nonce (must match creation)
* @returns Authorization with current on-chain status
*/
async fetchAuthorization(agentAddress, authorizedSource, nonce) {
throw new Error("On-chain fetch not yet implemented - pending Codama generation");
}
/**
* Update reputation using authorization
*
* Called by facilitators (e.g., PayAI) to update agent reputation
* using a pre-signed authorization.
*
* @param authorization - Authorization to use
* @param reputationChange - Reputation change to apply
* @param transactionSignature - Transaction signature for audit trail
* @param usageRecord - PDA for usage record (audit trail)
* @param metadata - Optional metadata
* @param facilitatorSigner - Facilitator's signer
* @returns Transaction signature
*/
async updateReputationWithAuth(authorization, reputationChange, transactionSignature, usageRecord, metadata, facilitatorSigner) {
const isValid = await this.verifySignature(authorization);
if (!isValid) {
throw new Error("Invalid authorization signature");
}
const status = this.getAuthorizationStatus(authorization);
if (!status.isValid) {
throw new Error(`Authorization is ${status.status}: ${status.reason}`);
}
const { getUpdateReputationWithAuthInstructionAsync } = await import('./updateReputationWithAuth-PCEUOCFV.js');
return await this.execute(
"updateReputationWithAuth",
async () => {
return await getUpdateReputationWithAuthInstructionAsync({
agent: authorization.agentAddress,
authorizedSource: facilitatorSigner,
usageRecord,
reputationChange: BigInt(reputationChange),
transactionSignature,
metadata: metadata ? JSON.stringify(metadata) : null,
nonce: authorization.nonce ?? null
});
},
[facilitatorSigner]
);
}
/**
* Revoke authorization
*
* Agent can revoke an authorization before it expires or is exhausted.
*
* @param agentAddress - Agent's address
* @param authorization - Authorization account PDA
* @param nonce - Optional nonce (must match creation)
* @param agentSigner - Agent's signer
* @returns Transaction signature
*/
async revokeAuthorization(agentAddress, authorization, nonce, agentSigner) {
const { getRevokeAuthorizationInstruction } = await import('./revokeAuthorization-2ZRO6GUZ.js');
return await this.execute(
"revokeAuthorization",
() => {
return getRevokeAuthorizationInstruction({
agent: agentAddress,
authorization,
authority: agentSigner,
nonce: nonce ?? null
});
},
[agentSigner]
);
}
/**
* List authorizations for an agent (filtering)
*
* @param filter - Filter criteria
* @returns List of authorizations
*/
async listAuthorizations(filter) {
throw new Error("Authorization listing not yet implemented - pending Codama generation");
}
/**
* Serialize authorization for storage/transmission
*
* @param authorization - Authorization to serialize
* @returns JSON-safe object
*/
serializeAuthorization(authorization) {
return serializeAuthorization(authorization);
}
/**
* Deserialize authorization from storage/transmission
*
* @param data - Serialized authorization data
* @returns Authorization object
*/
deserializeAuthorization(data) {
return deserializeAuthorization(data);
}
/**
* Get authorization ID (deterministic hash)
*
* @param authorization - Authorization to hash
* @returns Base58-encoded hash
*/
async getAuthorizationId(authorization) {
return getAuthorizationId(authorization);
}
/**
* Helper: Create authorization for PayAI facilitator
*
* Convenience method with sensible defaults for PayAI integration.
*
* @param payAIFacilitatorAddress - PayAI facilitator address
* @param agentKeypair - Agent's keypair
* @param options - Optional overrides
* @returns Signed authorization
*
* @example
* ```typescript
* const auth = await client.authorization.createPayAIAuthorization(
* 'PayAI...FacilitatorAddress',
* agentKeypair,
* { indexLimit: 5000 } // Optional overrides
* )
* ```
*/
async createPayAIAuthorization(payAIFacilitatorAddress, agentKeypair, options) {
const defaultParams = {
authorizedSource: payAIFacilitatorAddress,
indexLimit: 1e3,
// 1000 reputation updates
expiresIn: 30 * 24 * 60 * 60,
// 30 days
network: "devnet",
// TODO: detect from client
...options
};
return this.createAuthorization(defaultParams, agentKeypair);
}
/**
* Calculate storage fee based on authorization duration and custom fees
*
* @param authorization - Authorization to calculate fee for
* @param config - Storage configuration
* @returns Fee in lamports
*
* @example
* ```typescript
* // Default fee: 0.002 SOL
* const fee = module.calculateStorageFee(auth)
*
* // Custom fee for 30-day authorizations: 0.001 SOL
* const fee = module.calculateStorageFee(auth, {
* customFees: { 2592000: 1000000n } // 30 days = 0.001 SOL
* })
* ```
*/
calculateStorageFee(authorization, config) {
if (config?.storageFee !== void 0) {
return config.storageFee;
}
if (config?.customFees) {
const now = Math.floor(Date.now() / 1e3);
const duration = authorization.expiresAt - now;
const durations = Object.keys(config.customFees).map(Number).sort((a, b) => a - b);
for (const d of durations) {
if (duration <= d) {
return config.customFees[d];
}
}
const highestDuration = durations[durations.length - 1];
if (highestDuration && config.customFees[highestDuration]) {
return config.customFees[highestDuration];
}
}
return DEFAULT_STORAGE_FEE;
}
/**
* Estimate on-chain storage cost for an authorization
*
* @param params - Authorization parameters
* @param config - Optional storage configuration
* @returns Estimated cost in SOL
*
* @example
* ```typescript
* const costInSOL = await client.authorization.estimateStorageCost({
* authorizedSource: facilitatorAddress,
* expiresIn: 30 * 24 * 60 * 60 // 30 days
* })
* console.log(`On-chain storage will cost ${costInSOL} SOL`)
* ```
*/
async estimateStorageCost(params, config) {
const now = Math.floor(Date.now() / 1e3);
const mockAuth = {
agentAddress: "11111111111111111111111111111111",
// Placeholder
authorizedSource: params.authorizedSource,
indexLimit: params.indexLimit ?? 1e3,
expiresAt: params.expiresAt ?? now + (params.expiresIn ?? 30 * 24 * 60 * 60),
network: params.network ?? "devnet",
signature: new Uint8Array(64),
nonce: params.nonce
};
const feeInLamports = this.calculateStorageFee(mockAuth, config);
return Number(feeInLamports) / 1e9;
}
};
// src/core/GhostSpeakClient.ts
var GhostSpeakClient = class {
config;
constructor(config) {
this.config = {
programId: GHOSTSPEAK_MARKETPLACE_PROGRAM_ADDRESS,
commitment: "confirmed",
cluster: "devnet",
rpcEndpoint: config?.rpcEndpoint ?? this.getDefaultRpcEndpoint(config?.cluster ?? "devnet"),
...config,
rpc: config?.rpc ?? {}
};
}
/**
* Direct access to Agent Module for read operations
*/
get agents() {
return new AgentModule(this.config);
}
/**
* Direct access to Ghost Module for claiming external agents
*
* Ghosts are external AI agents (type 10) that exist on x402 facilitators.
* They can be claimed using Solana Attestation Service (SAS)
* for trustless ownership verification.
*/
get ghosts() {
return new GhostModule(this.config);
}
/**
* Direct access to Governance Module for read operations
*/
get governanceModule() {
return new GovernanceModule(this.config);
}
/**
* Direct access to Multisig Module for read operations
*/
get multisigModule() {
return new MultisigModule(this.config);
}
/**
* Agent operations
*/
agent() {
return new AgentBuilder(this.config);
}
/**
* Reputation operations
*/
reputation() {
return new ReputationModule(this.config);
}
/**
* Reputation Tag Engine (Pillar 2: Granular Tags)
*
* Automatic tag assignment and management based on agent metrics.
* Features confidence scoring, evidence tracking, and tag decay.
*/
tagEngine() {
const { ReputationTagEngine } = (init_reputation_tag_engine(), __toCommonJS(reputation_tag_engine_exports));
return new ReputationTagEngine();
}
/**
* Multi-Source Reputation Aggregator (Pillar 3: External Sources)
*
* Aggregate reputation data from multiple sources (x402, GitHub, custom webhooks)
* with weighted scoring and conflict detection.
*/
reputationAggregator() {
const { MultiSourceAggregator } = (init_MultiSourceAggregator(), __toCommonJS(MultiSourceAggregator_exports));
return new MultiSourceAggregator();
}
/**
* Privacy operations
*/
privacy() {
return new PrivacyModule(this.config);
}
/**
* Governance operations
*/
governance() {
return new GovernanceBuilder(this.config);
}
/**
* Multisig operations
*/
multisig() {
return new MultisigBuilder(this.config);
}
/**
* Unified Credential operations (Solana + Crossmint)
*/
credentials() {
return new UnifiedCredentialService({
programId: this.config.programId,
crossmint: this.config.credentials?.crossmintApiKey ? {
apiKey: this.config.credentials.crossmintApiKey,
environment: this.config.credentials.crossmintEnvironment,
chain: this.config.credentials.crossmintChain
} : void 0,
crossmintTemplates: this.config.credentials?.templates
});
}
/**
* DID operations (Decentralized Identifiers)
*/
did() {
return new DidModule(this.config);
}
/**
* Direct access to Authorization Module for read operations
*/
get authorization() {
return new AuthorizationModule(this.config);
}
/**
* Direct access to Staking Module for read operations
*/
get staking() {
return new StakingModule(this.config);
}
// H2A module has been removed - use A2A (Agent-to-Agent) instructions instead
/**
* Enable development mode features
*/
enableDevMode() {
console.log("\u{1F6E0}\uFE0F Development mode enabled");
console.log(" - Transaction simulation before sending");
console.log(" - Cost estimates for all operations");
console.log(" - Enhanced error messages");
this.config = {
...this.config
// Add dev mode flags
};
return this;
}
/**
* Configure network
*/
useNetwork(cluster) {
this.config.cluster = cluster;
this.config.rpcEndpoint = this.getDefaultRpcEndpoint(cluster);
return this;
}
/**
* Configure custom RPC
*/
useRpc(endpoint, wsEndpoint) {
this.config.rpcEndpoint = endpoint;
this.config.wsEndpoint = wsEndpoint;
return this;
}
/**
* Get default RPC endpoint for cluster
*/
getDefaultRpcEndpoint(cluster) {
switch (cluster) {
case "mainnet-beta":
return "https://api.mainnet-beta.solana.com";
case "devnet":
return "https://api.devnet.solana.com";
case "testnet":
return "https://api.testnet.solana.com";
case "localnet":
return "http://localhost:8899";
default:
return "https://api.devnet.solana.com";
}
}
};
var AgentBuilder = class {
module;
params = {};
constructor(config) {
this.module = new AgentModule(config);
}
create(params) {
this.params = {
...this.params,
agentType: 0,
// Default type
metadataUri: JSON.stringify(params),
agentId: params.name.toLowerCase().replace(/\s+/g, "-"),
name: params.name,
description: params.description || ""
};
return this;
}
withDescription(description) {
this.params.description = description;
return this;
}
withType(agentType) {
this.params.agentType = agentType;
return this;
}
withIPFS() {
this.params.forceIPFS = true;
return this;
}
compressed() {
this.params.compressed = true;
return this;
}
debug() {
this.module.debug();
return this;
}
withSigner(signer) {
this.params.signer = signer;
return this;
}
validateParams() {
if (!this.params.signer) {
throw new Error("Agent builder requires a signer. Call with signer first.");
}
if (!this.params.metadataUri) {
throw new Error("Agent builder requires metadata. Call create() first.");
}
if (!this.params.agentId) {
throw new Error("Agent builder requires agent ID. Call create() first.");
}
this.params.agentType ??= 0;
}
async getCost() {
this.validateParams();
return this.module.getCost("registerAgent", () => ({
programAddress: this.module.getProgramId(),
accounts: [],
data: new Uint8Array()
}));
}
async simulate() {
const instruction = () => ({
// Placeholder for actual instruction generation
programAddress: this.module.getProgramId(),
accounts: [],
data: new Uint8Array()
});
this.validateParams();
return this.module.simulateInstruction("registerAgent", instruction, [this.params.signer]);
}
async explain() {
this.validateParams();
return this.module.explain("registerAgent", () => ({
programAddress: this.module.getProgramId(),
accounts: [],
data: new Uint8Array()
}));
}
async execute() {
this.validateParams();
if (this.params.compressed) {
console.log("Creating compressed agent (5000x cheaper)...");
}
const signature = await this.module.register(this.params.signer, {
agentType: this.params.agentType,
name: this.params.name,
description: this.params.description,
metadataUri: this.params.metadataUri,
agentId: this.params.agentId
});
const address2 = await this.deriveAgentAddress(this.params.agentId, this.params.signer);
return { address: address2, signature };
}
async deriveAgentAddress(agentId, signer) {
const { deriveAgentPda } = await import('./pda-4KP7CURF.js');
const [address2] = await deriveAgentPda({
programA