@ghostspeak/sdk
Version:
TypeScript SDK for GhostSpeak AI Agent Commerce Protocol - Production Ready Beta
343 lines (342 loc) • 11.4 kB
JavaScript
// src/modules/credentials/CrossmintVCClient.ts
var CROSSMINT_STAGING_URL = "https://staging.crossmint.com";
var CROSSMINT_PROD_URL = "https://www.crossmint.com";
var GHOSTSPEAK_CREDENTIAL_TYPES = {
AGENT_IDENTITY: "GhostSpeakAgentIdentity",
REPUTATION_SCORE: "GhostSpeakReputation",
JOB_COMPLETION: "GhostSpeakJobCompletion"
};
var CrossmintVCClient = class {
apiKey;
baseUrl;
chain;
constructor(options) {
this.apiKey = options.apiKey;
this.baseUrl = options.environment === "production" ? CROSSMINT_PROD_URL : CROSSMINT_STAGING_URL;
this.chain = options.chain || "base-sepolia";
}
// ===================================
// Types & Templates
// ===================================
/**
* Create the GhostSpeak Agent Identity credential type
*/
async createAgentIdentityType() {
const typeName = GHOSTSPEAK_CREDENTIAL_TYPES.AGENT_IDENTITY;
const schema = {
$schema: "https://json-schema.org/draft/2020-12/schema",
title: "GhostSpeak Agent Identity",
description: "Verified AI agent identity on the GhostSpeak Protocol",
type: "object",
properties: {
credentialSubject: {
type: "object",
properties: {
agentId: { type: "string" },
owner: { type: "string" },
capabilities: { type: "array", items: { type: "string" } },
registeredAt: { type: "string" },
reputationScore: { type: "number" },
totalJobsCompleted: { type: "integer" },
verified: { type: "boolean" },
id: { type: "string" }
// Auto-added by Crossmint
},
required: ["agentId", "owner", "capabilities", "registeredAt", "verified"],
additionalProperties: false
}
}
};
return this.createCredentialType(typeName, schema);
}
/**
* Create the GhostSpeak Reputation credential type
*/
async createReputationType() {
const typeName = GHOSTSPEAK_CREDENTIAL_TYPES.REPUTATION_SCORE;
const schema = {
$schema: "https://json-schema.org/draft/2020-12/schema",
title: "GhostSpeak Reputation",
description: "Verified reputation score for GhostSpeak users",
type: "object",
properties: {
credentialSubject: {
type: "object",
properties: {
userId: { type: "string" },
walletAddress: { type: "string" },
reputationScore: { type: "number" },
totalTransactions: { type: "integer" },
disputeRate: { type: "number" },
memberSince: { type: "string" },
id: { type: "string" }
},
required: ["userId", "walletAddress", "reputationScore", "memberSince"],
additionalProperties: false
}
}
};
return this.createCredentialType(typeName, schema);
}
/**
* Create the GhostSpeak Job Completion credential type
*/
async createJobCompletionType() {
const typeName = GHOSTSPEAK_CREDENTIAL_TYPES.JOB_COMPLETION;
const schema = {
$schema: "https://json-schema.org/draft/2020-12/schema",
title: "GhostSpeak Job Completion",
description: "Certificate of successful job completion on GhostSpeak",
type: "object",
properties: {
credentialSubject: {
type: "object",
properties: {
jobId: { type: "string" },
agentId: { type: "string" },
clientAddress: { type: "string" },
completedAt: { type: "string" },
amountPaid: { type: "string" },
rating: { type: "integer" },
review: { type: "string" },
id: { type: "string" }
},
required: ["jobId", "agentId", "clientAddress", "completedAt", "amountPaid", "rating"],
additionalProperties: false
}
}
};
return this.createCredentialType(typeName, schema);
}
/**
* Initialize all GhostSpeak credential types
*/
async initializeAllTypes() {
const [agentIdentity, reputation, jobCompletion] = await Promise.all([
this.createAgentIdentityType(),
this.createReputationType(),
this.createJobCompletionType()
]);
return { agentIdentity, reputation, jobCompletion };
}
/**
* Create all GhostSpeak credential templates
*/
async createAllTemplates(types) {
const [agentIdentityTemplate, reputationTemplate, jobCompletionTemplate] = await Promise.all([
this.createTemplate(types.agentIdentity.id, {
name: "GhostSpeak Agent Identity",
description: "Verified AI agent identity on the GhostSpeak Protocol",
imageUrl: "https://www.ghostspeak.io/assets/credential-agent.png"
}),
this.createTemplate(types.reputation.id, {
name: "GhostSpeak Reputation",
description: "Verified reputation score for GhostSpeak users",
imageUrl: "https://www.ghostspeak.io/assets/credential-reputation.png"
}),
this.createTemplate(types.jobCompletion.id, {
name: "GhostSpeak Job Completion Certificate",
description: "Certificate of successful job completion on GhostSpeak",
imageUrl: "https://www.ghostspeak.io/assets/credential-job.png"
})
]);
return { agentIdentityTemplate, reputationTemplate, jobCompletionTemplate };
}
/**
* Issue an agent identity credential
*/
async issueAgentCredential(templateId, recipientEmail, subject, expiresAt) {
return this.issueCredential(templateId, recipientEmail, subject, expiresAt);
}
/**
* Issue a reputation credential
*/
async issueReputationCredential(templateId, recipientEmail, subject, expiresAt) {
return this.issueCredential(templateId, recipientEmail, subject, expiresAt);
}
/**
* Issue a job completion credential
*/
async issueJobCompletionCredential(templateId, recipientEmail, subject, expiresAt) {
return this.issueCredential(templateId, recipientEmail, subject, expiresAt);
}
/**
* Create a credential type (JSON Schema)
*/
async createCredentialType(typeName, schema) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/types/${typeName}`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
"X-API-KEY": this.apiKey
},
body: JSON.stringify(schema)
}
);
if (!response.ok) {
const error = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Failed to create credential type: ${JSON.stringify(error)}`);
}
return response.json();
}
/**
* Create a credential template
*/
async createTemplate(typeId, metadata) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/templates/`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": this.apiKey
},
body: JSON.stringify({
credentials: {
type: typeId,
encryption: "none",
storage: "crossmint"
},
metadata,
chain: this.chain
})
}
);
if (!response.ok) {
const text = await response.text();
try {
const error = JSON.parse(text);
throw new Error(`Failed to create template: ${JSON.stringify(error)}`);
} catch (e) {
throw new Error(`Failed to create template (${response.status}): ${text}`);
}
}
const action = await response.json();
const result = await this.waitForAction(action.id);
if (result.data && result.data.collection) {
return result.data.collection;
}
return result.data || result;
}
/**
* Poll an action until completion
*/
async waitForAction(actionId) {
let retries = 0;
while (retries < 60) {
await new Promise((resolve) => setTimeout(resolve, 2e3));
const response = await fetch(
`${this.baseUrl}/api/2022-06-09/actions/${actionId}`,
{
headers: {
"X-API-KEY": this.apiKey
}
}
);
if (!response.ok) {
throw new Error(`Failed to poll action: ${response.statusText}`);
}
const action = await response.json();
if (action.status === "succeeded") {
return action;
}
if (action.status === "failed") {
throw new Error(`Action failed: ${JSON.stringify(action)}`);
}
retries++;
}
throw new Error("Action polling timed out");
}
// ===================================
// Issuance
// ===================================
/**
* Issue a credential using a template
*/
async issueCredential(templateId, recipientEmail, subject, expiresAt) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/templates/${templateId}/vcs`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": this.apiKey
},
body: JSON.stringify({
recipient: `email:${recipientEmail}:${this.chain}`,
credential: {
subject,
expiresAt: expiresAt || this.getDefaultExpiry()
}
})
}
);
if (!response.ok) {
const error = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Failed to issue credential: ${JSON.stringify(error)}`);
}
return response.json();
}
// ===================================
// Verification & Retrieval
// ===================================
async getCredential(credentialId) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/${credentialId}`,
{
headers: {
"X-API-KEY": this.apiKey
}
}
);
if (!response.ok) {
const error = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Failed to get credential: ${JSON.stringify(error)}`);
}
return response.json();
}
async verifyCredential(credential) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/verification/verify`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-KEY": this.apiKey
},
body: JSON.stringify({ credential })
}
);
if (!response.ok) {
const error = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Failed to verify credential: ${JSON.stringify(error)}`);
}
return response.json();
}
async revokeCredential(credentialId) {
const response = await fetch(
`${this.baseUrl}/api/v1-alpha1/credentials/${credentialId}`,
{
method: "DELETE",
headers: {
"X-API-KEY": this.apiKey
}
}
);
if (!response.ok) {
const error = await response.json().catch(() => ({ message: response.statusText }));
throw new Error(`Failed to revoke credential: ${JSON.stringify(error)}`);
}
return response.json();
}
getDefaultExpiry() {
const date = /* @__PURE__ */ new Date();
date.setFullYear(date.getFullYear() + 1);
return date.toISOString().split("T")[0];
}
};
export { CrossmintVCClient, GHOSTSPEAK_CREDENTIAL_TYPES };
//# sourceMappingURL=chunk-RIZZPLLB.js.map
//# sourceMappingURL=chunk-RIZZPLLB.js.map