UNPKG

@attestprotocol/stellar-sdk

Version:

Stellar implementation of the Attest Protocol SDK

1,438 lines (1,433 loc) 48.2 kB
import { Address, scValToNative, rpc, Networks } from '@stellar/stellar-sdk'; import { createErrorResponse, createAttestProtocolError, AttestProtocolErrorType, createSuccessResponse, AttestProtocolBase } from '@attestprotocol/core'; export { AttestProtocolErrorType, createAttestProtocolError, createErrorResponse, createSuccessResponse } from '@attestprotocol/core'; import { networks, Client } from '@attestprotocol/stellar/dist/bindings/src/protocol'; export { Client as ProtocolClient, networks as ProtocolNetworks } from '@attestprotocol/stellar/dist/bindings/src/protocol'; import { networks as networks$1, Client as Client$1 } from '@attestprotocol/stellar/dist/bindings/src/authority'; export { Client as AuthorityClient, networks as AuthorityNetworks } from '@attestprotocol/stellar/dist/bindings/src/authority'; var __defProp = Object.defineProperty; var __getOwnPropNames = Object.getOwnPropertyNames; var __esm = (fn, res) => function __init() { return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; }; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; // src/common/schema-utils.ts async function generateSchemaUid(schemaDefinition, authority, resolver) { let dataToHash = schemaDefinition + authority; if (resolver) { dataToHash += resolver; } const encoder = new TextEncoder(); const data = encoder.encode(dataToHash); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map((b) => b.toString(16).padStart(2, "0")).join(""); } async function generateIdFromSchema(schema, authority) { const auth = authority || ""; return generateSchemaUid(schema.content, auth, schema.resolver); } function formatSchemaUid(uid) { if (uid.length !== 64) { return uid; } return `${uid.slice(0, 8)}-${uid.slice(8, 16)}-${uid.slice(16, 24)}-${uid.slice(24, 32)}-${uid.slice(32)}`; } function parseFormattedUid(formattedUid) { return formattedUid.replace(/-/g, ""); } var init_schema_utils = __esm({ "src/common/schema-utils.ts"() { } }); var StellarDataType, SchemaValidationError, StellarSchemaEncoder, StellarSchemaRegistry; var init_schema_encoder = __esm({ "src/common/schema-encoder.ts"() { StellarDataType = /* @__PURE__ */ ((StellarDataType2) => { StellarDataType2["STRING"] = "string"; StellarDataType2["BOOL"] = "bool"; StellarDataType2["U32"] = "u32"; StellarDataType2["U64"] = "u64"; StellarDataType2["I32"] = "i32"; StellarDataType2["I64"] = "i64"; StellarDataType2["I128"] = "i128"; StellarDataType2["ADDRESS"] = "address"; StellarDataType2["BYTES"] = "bytes"; StellarDataType2["SYMBOL"] = "symbol"; StellarDataType2["ARRAY"] = "array"; StellarDataType2["OPTION"] = "option"; StellarDataType2["MAP"] = "map"; StellarDataType2["TIMESTAMP"] = "timestamp"; StellarDataType2["AMOUNT"] = "amount"; return StellarDataType2; })(StellarDataType || {}); SchemaValidationError = class extends Error { constructor(message, field) { super(message); this.field = field; this.name = "SchemaValidationError"; } }; StellarSchemaEncoder = class _StellarSchemaEncoder { constructor(schema) { this.validateSchema(schema); this.schema = schema; } /** * Get the schema definition */ getSchema() { return { ...this.schema }; } /** * Generate a unique hash for this schema */ getSchemaHash() { const schemaString = JSON.stringify({ name: this.schema.name, version: this.schema.version, fields: this.schema.fields.map((f) => ({ name: f.name, type: f.type, optional: f.optional })) }); const encoder = new TextEncoder(); const data = encoder.encode(schemaString); return Array.from(new Uint8Array(data.slice(0, 32))).map((b) => b.toString(16).padStart(2, "0")).join(""); } /** * Encode attestation data according to the schema */ async encodeData(data) { this.validateData(data); const encodedData = JSON.stringify(this.processDataForEncoding(data)); const schemaHash = this.getSchemaHash(); return { schemaHash, encodedData, decodedData: { ...data }, schema: this.getSchema() }; } /** * Decode attestation data from encoded format */ decodeData(encodedData) { try { const parsed = JSON.parse(encodedData); return this.processDataForDecoding(parsed); } catch (error) { throw new SchemaValidationError(`Failed to decode data: ${error}`); } } /** * Validate data against the schema */ validateData(data) { for (const field of this.schema.fields) { if (!field.optional && !(field.name in data)) { throw new SchemaValidationError(`Required field '${field.name}' is missing`, field.name); } } for (const [key, value] of Object.entries(data)) { const field = this.schema.fields.find((f) => f.name === key); if (!field) { throw new SchemaValidationError(`Unknown field '${key}'`, key); } this.validateFieldValue(field, value); } } /** * Generate default values for a schema */ generateDefaults() { const defaults = {}; for (const field of this.schema.fields) { if (field.optional) continue; defaults[field.name] = this.getDefaultValue(field.type); } return defaults; } /** * Convert schema to JSON Schema format for external compatibility */ toJSONSchema() { const properties = {}; const required = []; for (const field of this.schema.fields) { properties[field.name] = { type: this.stellarTypeToJSONSchemaType(field.type), description: field.description }; if (field.validation) { Object.assign(properties[field.name], field.validation); } if (!field.optional) { required.push(field.name); } } return { $schema: "https://json-schema.org/draft/2020-12/schema", type: "object", title: this.schema.name, description: this.schema.description, version: this.schema.version, properties, required, additionalProperties: false }; } /** * Create a schema encoder from JSON Schema */ static fromJSONSchema(jsonSchema) { const fields = []; for (const [name, prop] of Object.entries(jsonSchema.properties || {})) { const property = prop; fields.push({ name, type: _StellarSchemaEncoder.jsonSchemaTypeToStellarType(property.type), optional: !jsonSchema.required?.includes(name), description: property.description, validation: { min: property.minimum, max: property.maximum, pattern: property.pattern, enum: property.enum } }); } const schema = { name: jsonSchema.title || "Untitled Schema", version: jsonSchema.version || "1.0.0", description: jsonSchema.description || "", fields }; return new _StellarSchemaEncoder(schema); } /** * Validate schema definition */ validateSchema(schema) { if (!schema.name || typeof schema.name !== "string") { throw new SchemaValidationError("Schema must have a valid name"); } if (!schema.version || typeof schema.version !== "string") { throw new SchemaValidationError("Schema must have a valid version"); } if (!schema.fields || !Array.isArray(schema.fields) || schema.fields.length === 0) { throw new SchemaValidationError("Schema must have at least one field"); } const fieldNames = /* @__PURE__ */ new Set(); for (const field of schema.fields) { if (!field.name || typeof field.name !== "string") { throw new SchemaValidationError("Each field must have a valid name"); } if (fieldNames.has(field.name)) { throw new SchemaValidationError(`Duplicate field name: ${field.name}`); } fieldNames.add(field.name); if (!this.isValidStellarType(field.type)) { throw new SchemaValidationError(`Invalid type '${field.type}' for field '${field.name}'`); } } } /** * Validate individual field value */ validateFieldValue(field, value) { if (value === null || value === void 0) { if (!field.optional) { throw new SchemaValidationError(`Field '${field.name}' cannot be null`, field.name); } return; } switch (field.type) { case "string" /* STRING */: case "symbol" /* SYMBOL */: if (typeof value !== "string") { throw new SchemaValidationError(`Field '${field.name}' must be a string`, field.name); } break; case "bool" /* BOOL */: if (typeof value !== "boolean") { throw new SchemaValidationError(`Field '${field.name}' must be a boolean`, field.name); } break; case "u32" /* U32 */: case "u64" /* U64 */: case "i32" /* I32 */: case "i64" /* I64 */: case "i128" /* I128 */: case "amount" /* AMOUNT */: if (typeof value !== "number" && typeof value !== "bigint") { throw new SchemaValidationError(`Field '${field.name}' must be a number`, field.name); } break; case "address" /* ADDRESS */: if (typeof value !== "string" || !this.isValidStellarAddress(value)) { throw new SchemaValidationError(`Field '${field.name}' must be a valid Stellar address`, field.name); } break; case "timestamp" /* TIMESTAMP */: if (typeof value !== "number" && typeof value !== "string") { throw new SchemaValidationError(`Field '${field.name}' must be a timestamp`, field.name); } break; } if (field.validation) { if (field.validation.enum && !field.validation.enum.includes(value)) { throw new SchemaValidationError( `Field '${field.name}' must be one of: ${field.validation.enum.join(", ")}`, field.name ); } if (typeof value === "string" && field.validation.pattern) { if (!new RegExp(field.validation.pattern).test(value)) { throw new SchemaValidationError(`Field '${field.name}' does not match pattern`, field.name); } } if (typeof value === "number") { if (field.validation.min !== void 0 && value < field.validation.min) { throw new SchemaValidationError(`Field '${field.name}' is below minimum value`, field.name); } if (field.validation.max !== void 0 && value > field.validation.max) { throw new SchemaValidationError(`Field '${field.name}' exceeds maximum value`, field.name); } } } } /** * Process data for encoding (type conversions, etc.) */ processDataForEncoding(data) { const processed = {}; for (const [key, value] of Object.entries(data)) { const field = this.schema.fields.find((f) => f.name === key); if (!field) continue; switch (field.type) { case "address" /* ADDRESS */: processed[key] = typeof value === "string" ? value : value.toString(); break; case "timestamp" /* TIMESTAMP */: processed[key] = typeof value === "string" ? new Date(value).getTime() : value; break; case "i128" /* I128 */: case "amount" /* AMOUNT */: processed[key] = typeof value === "bigint" ? value.toString() : value; break; default: processed[key] = value; } } return processed; } /** * Process data for decoding (reverse of encoding) */ processDataForDecoding(data) { const processed = {}; for (const [key, value] of Object.entries(data)) { const field = this.schema.fields.find((f) => f.name === key); if (!field) { processed[key] = value; continue; } switch (field.type) { case "i128" /* I128 */: case "amount" /* AMOUNT */: processed[key] = typeof value === "string" && /^\d+$/.test(value) ? BigInt(value) : value; break; default: processed[key] = value; } } return processed; } /** * Get default value for a type */ getDefaultValue(type) { switch (type) { case "string" /* STRING */: case "symbol" /* SYMBOL */: return ""; case "bool" /* BOOL */: return false; case "u32" /* U32 */: case "u64" /* U64 */: case "i32" /* I32 */: case "i64" /* I64 */: case "amount" /* AMOUNT */: return 0; case "i128" /* I128 */: return BigInt(0); case "address" /* ADDRESS */: return "GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWHF"; case "timestamp" /* TIMESTAMP */: return Date.now(); case "bytes" /* BYTES */: return new Uint8Array(0); case "array" /* ARRAY */: return []; case "map" /* MAP */: return {}; default: return null; } } /** * Check if a type is valid Stellar type */ isValidStellarType(type) { return Object.values(StellarDataType).includes(type) || type.startsWith("array<") || type.startsWith("option<") || type.startsWith("map<"); } /** * Convert Stellar type to JSON Schema type */ stellarTypeToJSONSchemaType(stellarType) { switch (stellarType) { case "string" /* STRING */: case "symbol" /* SYMBOL */: case "address" /* ADDRESS */: return "string"; case "bool" /* BOOL */: return "boolean"; case "u32" /* U32 */: case "u64" /* U64 */: case "i32" /* I32 */: case "i64" /* I64 */: case "i128" /* I128 */: case "amount" /* AMOUNT */: case "timestamp" /* TIMESTAMP */: return "number"; case "array" /* ARRAY */: return "array"; case "map" /* MAP */: return "object"; default: return "string"; } } /** * Convert JSON Schema type to Stellar type */ static jsonSchemaTypeToStellarType(jsonType) { switch (jsonType) { case "string": return "string" /* STRING */; case "boolean": return "bool" /* BOOL */; case "number": case "integer": return "i64" /* I64 */; case "array": return "array" /* ARRAY */; case "object": return "map" /* MAP */; default: return "string" /* STRING */; } } /** * Validate Stellar address format */ isValidStellarAddress(address) { try { Address.fromString(address); return true; } catch { return false; } } }; StellarSchemaRegistry = class { /** * Register a schema encoder */ static register(name, encoder) { this.schemas.set(name, encoder); } /** * Get a registered schema encoder */ static get(name) { return this.schemas.get(name); } /** * List all registered schema names */ static list() { return Array.from(this.schemas.keys()); } /** * Initialize with common schemas */ static initializeDefaults() { this.register("identity-verification", new StellarSchemaEncoder({ name: "Identity Verification", version: "1.0.0", description: "Standard identity verification attestation", fields: [ { name: "fullName", type: "string" /* STRING */, description: "Legal full name" }, { name: "dateOfBirth", type: "timestamp" /* TIMESTAMP */, description: "Date of birth" }, { name: "nationality", type: "string" /* STRING */, description: "Nationality" }, { name: "documentType", type: "string" /* STRING */, validation: { enum: ["passport", "drivers_license", "national_id"] } }, { name: "verificationLevel", type: "string" /* STRING */, validation: { enum: ["basic", "enhanced", "premium"] } }, { name: "verifiedBy", type: "address" /* ADDRESS */, description: "Verifying authority address" } ] })); this.register("academic-credential", new StellarSchemaEncoder({ name: "Academic Credential", version: "1.0.0", description: "University degree or academic achievement", fields: [ { name: "studentName", type: "string" /* STRING */, description: "Name of the student" }, { name: "institution", type: "string" /* STRING */, description: "Educational institution" }, { name: "degree", type: "string" /* STRING */, description: "Type of degree" }, { name: "fieldOfStudy", type: "string" /* STRING */, description: "Major or field" }, { name: "graduationDate", type: "timestamp" /* TIMESTAMP */, description: "Graduation date" }, { name: "gpa", type: "u32" /* U32 */, optional: true, validation: { min: 0, max: 400 } }, // GPA * 100 { name: "honors", type: "string" /* STRING */, optional: true, validation: { enum: ["summa_cum_laude", "magna_cum_laude", "cum_laude", "none"] } } ] })); this.register("professional-certification", new StellarSchemaEncoder({ name: "Professional Certification", version: "1.0.0", description: "Professional certification or license", fields: [ { name: "holderName", type: "string" /* STRING */, description: "Certification holder name" }, { name: "certificationName", type: "string" /* STRING */, description: "Name of certification" }, { name: "issuingOrganization", type: "string" /* STRING */, description: "Issuing organization" }, { name: "certificationNumber", type: "string" /* STRING */, description: "Certification number" }, { name: "issueDate", type: "timestamp" /* TIMESTAMP */, description: "Issue date" }, { name: "expirationDate", type: "timestamp" /* TIMESTAMP */, optional: true, description: "Expiration date" }, { name: "level", type: "string" /* STRING */, validation: { enum: ["entry", "associate", "professional", "expert", "master"] } } ] })); } }; StellarSchemaRegistry.schemas = /* @__PURE__ */ new Map(); StellarSchemaRegistry.initializeDefaults(); } }); // src/common/index.ts var common_exports = {}; __export(common_exports, { SchemaValidationError: () => SchemaValidationError, StellarDataType: () => StellarDataType, StellarSchemaEncoder: () => StellarSchemaEncoder, StellarSchemaRegistry: () => StellarSchemaRegistry, formatSchemaUid: () => formatSchemaUid, generateIdFromSchema: () => generateIdFromSchema, generateSchemaUid: () => generateSchemaUid, parseFormattedUid: () => parseFormattedUid }); var init_common = __esm({ "src/common/index.ts"() { init_schema_utils(); init_schema_encoder(); } }); var StellarSchemaService = class { constructor(config, protocolClient) { this.protocolClient = protocolClient; this.publicKey = config.publicKey; } /** * Create a new schema on the Stellar network */ async createSchema(config) { try { const validationError = this.validateSchemaDefinition(config); if (validationError) return createErrorResponse(validationError); const caller = this.publicKey; const schemaDefinition = config.content; const resolver = config.resolver || null; const revocable = config.revocable ?? true; const tx = await this.protocolClient.register({ caller, schema_definition: schemaDefinition, resolver, revocable }); const result = await tx.signAndSend(); if (!result.returnValue) { throw createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, "Failed to get schema UID from transaction" ); } const uid = scValToNative(result.returnValue).toString("hex"); return createSuccessResponse({ uid, definition: config.content, authority: caller, revocable: config.revocable ?? true, resolver: config.resolver || null, levy: config.levy || null }); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to create schema" ) ); } } /** * Fetch a schema by its UID */ async fetchSchemaById(id) { try { if (!/^[0-9a-fA-F]{64}$/.test(id)) { throw createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid schema UID format. Expected a 64-character hex string." ); } const schemaUid = Buffer.from(id, "hex"); return createSuccessResponse(null); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to fetch schema" ) ); } } /** * Generate a deterministic ID from schema definition */ async generateIdFromSchema(schema) { try { const { generateIdFromSchema: generateId } = await Promise.resolve().then(() => (init_common(), common_exports)); const uid = await generateId(schema, this.publicKey); return createSuccessResponse(uid); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, error.message || "Failed to generate schema ID" ) ); } } /** * List schemas by issuer */ async listSchemasByIssuer(params) { try { const emptyResponse = { items: [], total: 0, limit: params.limit ?? 10, offset: params.offset ?? 0, hasMore: false }; return createSuccessResponse(emptyResponse); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to list schemas" ) ); } } /** * Validate schema definition */ validateSchemaDefinition(config) { if (!config.name || config.name.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Schema name is required" ); } if (!config.content || config.content.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Schema content is required" ); } if (config.resolver) { try { Address.fromString(config.resolver); } catch { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid resolver address format" ); } } return null; } }; var StellarAttestationService = class { constructor(config, protocolClient) { this.protocolClient = protocolClient; this.publicKey = config.publicKey; } /** * Issue a new attestation on the Stellar network */ async issueAttestation(config) { try { const validationError = this.validateAttestationDefinition(config); if (validationError) return createErrorResponse(validationError); if (!/^[0-9a-fA-F]{64}$/.test(config.schemaUid)) { throw createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid schema UID format. Must be a 64-character hex string." ); } const caller = this.publicKey; const schemaUid = Buffer.from(config.schemaUid, "hex"); const subject = config.subject; const value = config.data; const reference = config.reference || null; const tx = await this.protocolClient.attest({ caller, schema_uid: schemaUid, subject, value, reference }); const result = await tx.signAndSend(); const timestamp = Date.now(); return createSuccessResponse({ uid: result.transactionHash || Date.now().toString(), schemaUid: config.schemaUid, subject: config.subject, attester: this.publicKey, data: config.data, timestamp, expirationTime: config.expirationTime || null, revocationTime: null, revoked: false, reference: config.reference || null }); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to issue attestation" ) ); } } /** * Fetch an attestation by its ID */ async fetchAttestationById(id) { try { return createSuccessResponse(null); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to fetch attestation" ) ); } } /** * Get an attestation by schema UID, subject, and reference */ async getAttestation(schemaUid, subject, reference) { try { if (!/^[0-9a-fA-F]{64}$/.test(schemaUid)) { throw createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid schema UID format. Must be a 64-character hex string." ); } const schemaUidBuffer = Buffer.from(schemaUid, "hex"); const tx = await this.protocolClient.get_attestation({ schema_uid: schemaUidBuffer, subject, reference: reference || null }); const result = await tx.simulate(); if (!result.result?.returnValue) { return createSuccessResponse(null); } const attestationRecord = scValToNative(result.result.returnValue); return createSuccessResponse({ uid: `${schemaUid}-${subject}-${reference || "default"}`, schemaUid, subject, attester: this.publicKey, // This should come from the contract data: attestationRecord.value, timestamp: Date.now(), // This should come from the contract expirationTime: null, revocationTime: null, revoked: attestationRecord.revoked || false, reference: attestationRecord.reference || null }); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to get attestation" ) ); } } /** * List attestations by wallet address */ async listAttestationsByWallet(params) { try { const emptyResponse = { items: [], total: 0, limit: params.limit ?? 10, offset: params.offset ?? 0, hasMore: false }; return createSuccessResponse(emptyResponse); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to list attestations by wallet" ) ); } } /** * List attestations by schema UID */ async listAttestationsBySchema(params) { try { const emptyResponse = { items: [], total: 0, limit: params.limit ?? 10, offset: params.offset ?? 0, hasMore: false }; return createSuccessResponse(emptyResponse); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to list attestations by schema" ) ); } } /** * Revoke an attestation */ async revokeAttestation(config) { try { const validationError = this.validateRevocationDefinition(config); if (validationError) return createErrorResponse(validationError); return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NOT_FOUND_ERROR, "Revocation by attestation UID not yet implemented. Use revokeAttestationByComponents instead." ) ); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to revoke attestation" ) ); } } /** * Revoke an attestation by its components (Stellar-specific) */ async revokeAttestationByComponents(schemaUid, subject, reference) { try { if (!/^[0-9a-fA-F]{64}$/.test(schemaUid)) { throw createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid schema UID format. Must be a 64-character hex string." ); } const caller = this.publicKey; const schemaUidBuffer = Buffer.from(schemaUid, "hex"); const tx = await this.protocolClient.revoke_attestation({ caller, schema_uid: schemaUidBuffer, subject, reference: reference || null }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to revoke attestation" ) ); } } /** * Attest by delegation (not implemented in current Stellar contracts) */ async attestByDelegation(config) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NOT_FOUND_ERROR, "Delegation not implemented in Stellar contracts" ) ); } /** * Revoke by delegation (not implemented in current Stellar contracts) */ async revokeByDelegation(config) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NOT_FOUND_ERROR, "Delegation not implemented in Stellar contracts" ) ); } /** * Validate attestation definition */ validateAttestationDefinition(config) { if (!config.schemaUid || config.schemaUid.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Schema UID is required" ); } if (!config.subject || config.subject.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Subject is required" ); } try { Address.fromString(config.subject); } catch { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Invalid subject address format" ); } if (!config.data || config.data.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Attestation data is required" ); } return null; } /** * Validate revocation definition */ validateRevocationDefinition(config) { if (!config.attestationUid || config.attestationUid.trim() === "") { return createAttestProtocolError( AttestProtocolErrorType.VALIDATION_ERROR, "Attestation UID is required" ); } return null; } }; var StellarAuthorityService = class { constructor(config, authorityClient) { this.authorityClient = authorityClient; this.publicKey = config.publicKey; } /** * Initialize the authority contract */ async initialize(admin, tokenContractId) { try { const tx = await this.authorityClient.initialize({ admin, token_contract_id: tokenContractId }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to initialize authority contract" ) ); } } /** * Register an authority (admin function) */ async adminRegisterAuthority(authToReg, metadata) { try { const tx = await this.authorityClient.admin_register_authority({ admin: this.publicKey, auth_to_reg: authToReg, metadata }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to register authority" ) ); } } /** * Register an authority (public function with fees) */ async registerAuthority(authorityToReg, metadata) { try { const tx = await this.authorityClient.register_authority({ caller: this.publicKey, authority_to_reg: authorityToReg, metadata }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to register authority" ) ); } } /** * Check if an address is an authority */ async isAuthority(authority) { try { const tx = await this.authorityClient.is_authority({ authority }); const result = await tx.simulate(); if (!result.result?.returnValue) { return createSuccessResponse(false); } const isAuth = scValToNative(result.result.returnValue); return createSuccessResponse(isAuth); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to check authority status" ) ); } } /** * Register schema rules (admin function) */ async adminRegisterSchema(schemaUid, rules) { try { const tx = await this.authorityClient.admin_register_schema({ admin: this.publicKey, schema_uid: schemaUid, rules }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to register schema rules" ) ); } } /** * Set schema levy (admin function) */ async adminSetSchemaLevy(schemaUid, levyAmount, levyRecipient) { try { const tx = await this.authorityClient.admin_set_schema_levy({ admin: this.publicKey, schema_uid: schemaUid, levy_amount: levyAmount, levy_recipient: levyRecipient }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to set schema levy" ) ); } } /** * Set registration fee (admin function) */ async adminSetRegistrationFee(feeAmount, tokenId) { try { const tx = await this.authorityClient.admin_set_registration_fee({ admin: this.publicKey, fee_amount: feeAmount, token_id: tokenId }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to set registration fee" ) ); } } /** * Process attestation through authority contract */ async attest(attestation) { try { const tx = await this.authorityClient.attest({ attestation }); const result = await tx.signAndSend(); if (!result.returnValue) { return createSuccessResponse(false); } const success = scValToNative(result.returnValue); return createSuccessResponse(success); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to process attestation" ) ); } } /** * Process revocation through authority contract */ async revoke(attestation) { try { const tx = await this.authorityClient.revoke({ attestation }); const result = await tx.signAndSend(); if (!result.returnValue) { return createSuccessResponse(false); } const success = scValToNative(result.returnValue); return createSuccessResponse(success); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to process revocation" ) ); } } /** * Withdraw collected levies */ async withdrawLevies() { try { const tx = await this.authorityClient.withdraw_levies({ caller: this.publicKey }); await tx.signAndSend(); return createSuccessResponse(void 0); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to withdraw levies" ) ); } } /** * Get schema rules */ async getSchemaRules(schemaUid) { try { const tx = await this.authorityClient.get_schema_rules({ schema_uid: schemaUid }); const result = await tx.simulate(); if (!result.result?.returnValue) { return createSuccessResponse(null); } const rules = scValToNative(result.result.returnValue); return createSuccessResponse(rules); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to get schema rules" ) ); } } /** * Get collected levies for an authority */ async getCollectedLevies(authority) { try { const tx = await this.authorityClient.get_collected_levies({ authority }); const result = await tx.simulate(); if (!result.result?.returnValue) { return createSuccessResponse(BigInt(0)); } const levies = scValToNative(result.result.returnValue); return createSuccessResponse(BigInt(levies)); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to get collected levies" ) ); } } /** * Get token ID */ async getTokenId() { try { const tx = await this.authorityClient.get_token_id(); const result = await tx.simulate(); if (!result.result?.returnValue) { throw new Error("No token ID returned"); } const tokenId = scValToNative(result.result.returnValue); return createSuccessResponse(tokenId); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to get token ID" ) ); } } /** * Get admin address */ async getAdminAddress() { try { const tx = await this.authorityClient.get_admin_address(); const result = await tx.simulate(); if (!result.result?.returnValue) { throw new Error("No admin address returned"); } const admin = scValToNative(result.result.returnValue); return createSuccessResponse(admin); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to get admin address" ) ); } } /** * Fetch authority information */ async fetchAuthority(id) { try { const isAuthResult = await this.isAuthority(id); if (isAuthResult.error || !isAuthResult.data) { return createSuccessResponse(null); } return createSuccessResponse({ id, isVerified: true, metadata: "Authority metadata" // This should come from contract storage }); } catch (error) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || "Failed to fetch authority" ) ); } } }; var StellarAttestProtocol = class extends AttestProtocolBase { /** * Creates a new instance of the Stellar Attest SDK * @param config SDK configuration options */ constructor(config) { super(config); this.config = config; const defaultUrl = "https://soroban-testnet.stellar.org"; this.server = new rpc.Server(config.url ?? defaultUrl, { allowHttp: config.allowHttp ?? (config.url ?? defaultUrl).startsWith("http://") }); this.networkPassphrase = config.networkPassphrase ?? Networks.TESTNET; const clientOptions = { networkPassphrase: this.networkPassphrase, rpcUrl: config.url ?? defaultUrl, allowHttp: config.allowHttp ?? (config.url ?? defaultUrl).startsWith("http://") }; const protocolContractId = config.contractAddresses?.protocol ?? networks.testnet.contractId; const authorityContractId = config.contractAddresses?.authority ?? networks$1.testnet.contractId; this.protocolClient = new Client({ ...clientOptions, contractId: protocolContractId }); this.authorityClient = new Client$1({ ...clientOptions, contractId: authorityContractId }); this.schemaService = new StellarSchemaService(config, this.protocolClient); this.attestationService = new StellarAttestationService(config, this.protocolClient); this.authorityService = new StellarAuthorityService(config, this.authorityClient); } getDefaultNetworkUrl() { return "https://soroban-testnet.stellar.org"; } /** * Initialize the protocol contract by setting the admin */ async initialize() { return this.safeExecute( async () => { const tx = await this.protocolClient.initialize({ admin: this.config.publicKey }); await tx.signAndSend(); }, () => { this.initialized = true; } ); } // Authority Management - Delegate to AuthorityService async registerAuthority() { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return createSuccessResponse(this.config.publicKey); } async fetchAuthority(id) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.authorityService.fetchAuthority(id); } async isIssuerAnAuthority(issuer) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.authorityService.isAuthority(issuer); } // Schema Management - Delegate to SchemaService async createSchema(config) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.schemaService.createSchema(config); } async fetchSchemaById(id) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.schemaService.fetchSchemaById(id); } async generateIdFromSchema(schema) { return this.schemaService.generateIdFromSchema(schema); } async listSchemasByIssuer(params) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.schemaService.listSchemasByIssuer(params); } // Attestation Management - Delegate to AttestationService async issueAttestation(config) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.issueAttestation(config); } async fetchAttestationById(id) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.fetchAttestationById(id); } async listAttestationsByWallet(params) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.listAttestationsByWallet(params); } async listAttestationsBySchema(params) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.listAttestationsBySchema(params); } async revokeAttestation(config) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.revokeAttestation(config); } // Delegation (not implemented in current Stellar contracts) async attestByDelegation(config) { return this.attestationService.attestByDelegation(config); } async revokeByDelegation(config) { return this.attestationService.revokeByDelegation(config); } // Stellar-specific helper methods /** * Get the underlying protocol contract client */ getProtocolClient() { return this.protocolClient; } /** * Get the underlying authority contract client */ getAuthorityClient() { return this.authorityClient; } /** * Get the schema service for direct access */ getSchemaService() { return this.schemaService; } /** * Get the attestation service for direct access */ getAttestationService() { return this.attestationService; } /** * Get the authority service for direct access */ getAuthorityService() { return this.authorityService; } /** * Get an attestation by schema UID, subject, and reference */ async getAttestation(schemaUid, subject, reference) { const initError = this.ensureInitialized(); if (initError) return createErrorResponse(initError); return this.attestationService.getAttestation(schemaUid, subject, reference); } }; // src/index.ts init_schema_encoder(); init_common(); var index_default = StellarAttestProtocol; export { SchemaValidationError, StellarAttestProtocol, StellarAttestationService, StellarAuthorityService, StellarDataType, StellarSchemaEncoder, StellarSchemaRegistry, StellarSchemaService, common_exports as common, index_default as default }; //# sourceMappingURL=index.mjs.map //# sourceMappingURL=index.mjs.map