UNPKG

@hashgraphonline/conversational-agent

Version:

Hashgraph Online conversational AI agent implementing HCS-10 communication, HCS-2 registries, and content inscription on Hedera. https://hol.org

112 lines (102 loc) 3.21 kB
import { AccountId, Client, PrivateKey, PublicKey, Transaction, TransactionReceipt, } from '@hashgraph/sdk'; import { AbstractSigner } from 'hedera-agent-kit'; import { HederaMirrorNode, Logger, type NetworkType, } from '@hashgraphonline/standards-sdk'; /** * BrowserSigner (bytes-only) * * Minimal signer compatible with HederaAgentKit in bytes/Provide Bytes mode. * - Does NOT hold a private key * - Cannot execute transactions; only provides identity and network context * - getOperatorPrivateKey() throws to signal absence of a local key */ export class BrowserSigner extends AbstractSigner { private readonly account: AccountId; private readonly network: 'mainnet' | 'testnet'; private readonly client: Client; private readonly exec: (( base64: string, network: 'mainnet' | 'testnet' ) => Promise<{ transactionId: string }>) | null; private readonly ephemeralKey: PrivateKey; getAccountId(): AccountId { return this.account; } getNetwork(): 'mainnet' | 'testnet' { return this.network; } constructor( accountId: string, network: 'mainnet' | 'testnet', executor?: ( base64: string, network: 'mainnet' | 'testnet' ) => Promise<{ transactionId: string }> ) { super(); this.account = AccountId.fromString(accountId); this.network = network; this.client = network === 'mainnet' ? Client.forMainnet() : Client.forTestnet(); this.exec = executor ?? null; this.ephemeralKey = PrivateKey.generateED25519(); } /** * Returns an auto-generated ED25519 key for client wiring only. * Do not use for signing; wallet performs signing in renderer. */ getOperatorPrivateKey(): PrivateKey { return this.ephemeralKey; } getClient(): Client { return this.client; } async signAndExecuteTransaction( tx: Transaction ): Promise<TransactionReceipt> { if (!this.exec) { throw new Error('BrowserSigner executor not available'); } if (!tx.isFrozen()) { await tx.freezeWith(this.client); } const base64 = Buffer.from(tx.toBytes()).toString('base64'); const { transactionId } = await this.exec(base64, this.network); const mirror = new HederaMirrorNode(this.network); const deadline = Date.now() + 60000; while (Date.now() < deadline) { try { const details = await mirror.getTransaction(transactionId); if (details && details.result) { return TransactionReceipt.fromBytes( Buffer.from(details.result, 'base64') ); } } catch {} await new Promise((r) => setTimeout(r, 1200)); } return TransactionReceipt.fromBytes(Buffer.from('')); } override async getPublicKey(): Promise<PublicKey> { const network: NetworkType = this.network === 'mainnet' ? 'mainnet' : 'testnet'; const mirror = new HederaMirrorNode( network, new Logger({ module: 'BrowserSigner' }) ); const anyKey: any = await mirror.getPublicKey(this.account.toString()); const keyStr = typeof anyKey?.toString === 'function' ? anyKey.toString() : String(anyKey); return PublicKey.fromString(keyStr); } } export default BrowserSigner;