import { generateQuote, inscribe, retrieveInscription, type InscriptionInput, type InscriptionOptions, type InscriptionResponse, type InscriptionResult, type NodeHederaClientConfig, } from '@hashgraphonline/standards-sdk'; const requiredEnv = (name: string): string => { const value = process.env[name]; if (!value) throw new Error(`Missing ${name}`); return value; }; const network = process.env.KILOSCRIBE_NETWORK === 'testnet' ? 'testnet' : 'mainnet'; const client: NodeHederaClientConfig = { accountId: requiredEnv('KILOSCRIBE_ACCOUNT_ID'), privateKey: requiredEnv('KILOSCRIBE_PRIVATE_KEY'), network, }; const isInscriptionResult = ( result: InscriptionResponse['result'], ): result is InscriptionResult => 'jobId' in result; type PublishOptions = Omit; export type PublishedInscription = { quoteHbar: string; jobId: string; transactionId?: string; topicId: string; hcsReference: string; publicUrl: string; }; async function publish( input: InscriptionInput, options: PublishOptions, ): Promise { const quote = await generateQuote(input, client, { ...options, quoteOnly: true, }); if (!quote.quote || !('totalCostHbar' in quote.result)) { throw new Error('KiloScribe did not return a quote'); } const execution = await inscribe(input, client, { ...options, quoteOnly: false, waitForConfirmation: true, waitMaxAttempts: 30, waitIntervalMs: 4_000, }); const result = isInscriptionResult(execution.result) ? execution.result : undefined; const jobId = execution.inscription?.jobId ?? result?.jobId; if (!jobId) throw new Error('Inscription completed without a job ID'); const completed = execution.inscription ?? (await retrieveInscription(jobId, { accountId: client.accountId, privateKey: client.privateKey.toString(), network: client.network, mode: options.mode, })); const topicId = completed.topic_id; if (!topicId) throw new Error('Inscription completed without a topic ID'); return { quoteHbar: quote.result.totalCostHbar, jobId, transactionId: result?.transactionId, topicId, hcsReference: `hcs://1/${topicId}`, publicUrl: `https://kiloscribe.com/api/inscription-cdn/${topicId}`, }; } export function inscribeUrl(url: string): Promise { return publish( { type: 'url', url }, { mode: 'file', fileStandard: '1', tags: ['ai-generated'], }, ); } export function inscribeFile(path: string): Promise { return publish( { type: 'file', path }, { mode: 'file', fileStandard: '1', tags: ['ai-generated'], }, ); } export type HashinalMetadata = { name: string; creator: string; description: string; type: string; image?: string; attributes?: Array<{ trait_type: string; value: string | number }>; [key: string]: unknown; }; export function inscribeHashinal( url: string, metadata: HashinalMetadata, ): Promise { return publish( { type: 'url', url }, { mode: 'hashinal', fileStandard: '1', metadata, tags: ['ai-generated', 'hcs-5'], }, ); } // Run with: pnpm dlx tsx inscriber.ts https://example.com/artifact.html if (process.argv[1]?.endsWith('inscriber.ts') && process.argv[2]) { inscribeUrl(process.argv[2]) .then((result) => console.log(JSON.stringify(result, null, 2))) .catch((error: unknown) => { console.error(error instanceof Error ? error.message : error); process.exitCode = 1; }); }