UNPKG

@attestprotocol/stellar-sdk

Version:

Stellar implementation of the Attest Protocol SDK

408 lines (359 loc) 10.9 kB
/** * Authority operations for the Stellar Attest Protocol */ import { AttestProtocolResponse, Authority, AttestProtocolErrorType, createSuccessResponse, createErrorResponse, createAttestProtocolError, } from '@attestprotocol/core' import { Client as AuthorityClient, SchemaRules, AttestationRecord } from '@attestprotocol/stellar/dist/bindings/src/authority' import { Address, scValToNative } from '@stellar/stellar-sdk' import { StellarConfig } from './types' export class StellarAuthorityService { private authorityClient: AuthorityClient private publicKey: string constructor(config: StellarConfig, authorityClient: AuthorityClient) { this.authorityClient = authorityClient this.publicKey = config.publicKey } /** * Initialize the authority contract */ async initialize(admin: string, tokenContractId: string): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.initialize({ admin, token_contract_id: tokenContractId }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to initialize authority contract' ) ) } } /** * Register an authority (admin function) */ async adminRegisterAuthority( authToReg: string, metadata: string ): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.admin_register_authority({ admin: this.publicKey, auth_to_reg: authToReg, metadata }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to register authority' ) ) } } /** * Register an authority (public function with fees) */ async registerAuthority( authorityToReg: string, metadata: string ): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.register_authority({ caller: this.publicKey, authority_to_reg: authorityToReg, metadata }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to register authority' ) ) } } /** * Check if an address is an authority */ async isAuthority(authority: string): Promise<AttestProtocolResponse<boolean>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to check authority status' ) ) } } /** * Register schema rules (admin function) */ async adminRegisterSchema( schemaUid: Buffer, rules: SchemaRules ): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.admin_register_schema({ admin: this.publicKey, schema_uid: schemaUid, rules }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to register schema rules' ) ) } } /** * Set schema levy (admin function) */ async adminSetSchemaLevy( schemaUid: Buffer, levyAmount: bigint, levyRecipient: string ): Promise<AttestProtocolResponse<void>> { 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(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to set schema levy' ) ) } } /** * Set registration fee (admin function) */ async adminSetRegistrationFee( feeAmount: bigint, tokenId: string ): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.admin_set_registration_fee({ admin: this.publicKey, fee_amount: feeAmount, token_id: tokenId }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to set registration fee' ) ) } } /** * Process attestation through authority contract */ async attest(attestation: AttestationRecord): Promise<AttestProtocolResponse<boolean>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to process attestation' ) ) } } /** * Process revocation through authority contract */ async revoke(attestation: AttestationRecord): Promise<AttestProtocolResponse<boolean>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to process revocation' ) ) } } /** * Withdraw collected levies */ async withdrawLevies(): Promise<AttestProtocolResponse<void>> { try { const tx = await this.authorityClient.withdraw_levies({ caller: this.publicKey }) await tx.signAndSend() return createSuccessResponse(undefined) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to withdraw levies' ) ) } } /** * Get schema rules */ async getSchemaRules(schemaUid: Buffer): Promise<AttestProtocolResponse<SchemaRules | null>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to get schema rules' ) ) } } /** * Get collected levies for an authority */ async getCollectedLevies(authority: string): Promise<AttestProtocolResponse<bigint>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to get collected levies' ) ) } } /** * Get token ID */ async getTokenId(): Promise<AttestProtocolResponse<string>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to get token ID' ) ) } } /** * Get admin address */ async getAdminAddress(): Promise<AttestProtocolResponse<string>> { 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: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to get admin address' ) ) } } /** * Fetch authority information */ async fetchAuthority(id: string): Promise<AttestProtocolResponse<Authority | null>> { try { const isAuthResult = await this.isAuthority(id) if (isAuthResult.error || !isAuthResult.data) { return createSuccessResponse(null) } // For now, return basic authority info // In a real implementation, we'd need to get metadata from contract storage or events return createSuccessResponse({ id, isVerified: true, metadata: 'Authority metadata', // This should come from contract storage }) } catch (error: any) { return createErrorResponse( createAttestProtocolError( AttestProtocolErrorType.NETWORK_ERROR, error.message || 'Failed to fetch authority' ) ) } } }