@hashgraphonline/standards-agent-kit 0.2.135 → 0.2.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -4
- package/dist/cjs/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/cjs/interfaces/FormValidatable.d.ts +4 -13
- package/dist/cjs/standards-agent-kit.cjs +1 -1
- package/dist/cjs/standards-agent-kit.cjs.map +1 -1
- package/dist/cjs/tools/inscriber/InscribeHashinalTool.d.ts +2 -10
- package/dist/cjs/types/inscription-response.d.ts +8 -0
- package/dist/cjs/utils/inscription-utils.d.ts +21 -0
- package/dist/es/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/es/interfaces/FormValidatable.d.ts +4 -13
- package/dist/es/standards-agent-kit.es3.js +4 -0
- package/dist/es/standards-agent-kit.es3.js.map +1 -1
- package/dist/es/standards-agent-kit.es34.js +12 -6
- package/dist/es/standards-agent-kit.es34.js.map +1 -1
- package/dist/es/standards-agent-kit.es35.js +5 -4
- package/dist/es/standards-agent-kit.es35.js.map +1 -1
- package/dist/es/standards-agent-kit.es36.js +13 -9
- package/dist/es/standards-agent-kit.es36.js.map +1 -1
- package/dist/es/standards-agent-kit.es37.js +32 -48
- package/dist/es/standards-agent-kit.es37.js.map +1 -1
- package/dist/es/standards-agent-kit.es38.js +9 -10
- package/dist/es/standards-agent-kit.es38.js.map +1 -1
- package/dist/es/standards-agent-kit.es44.js +1 -1
- package/dist/es/standards-agent-kit.es44.js.map +1 -1
- package/dist/es/standards-agent-kit.es47.js +17 -50
- package/dist/es/standards-agent-kit.es47.js.map +1 -1
- package/dist/es/standards-agent-kit.es48.js +54 -3
- package/dist/es/standards-agent-kit.es48.js.map +1 -1
- package/dist/es/standards-agent-kit.es49.js +2 -39
- package/dist/es/standards-agent-kit.es49.js.map +1 -1
- package/dist/es/standards-agent-kit.es50.js +38 -17
- package/dist/es/standards-agent-kit.es50.js.map +1 -1
- package/dist/es/standards-agent-kit.es51.js +16 -51
- package/dist/es/standards-agent-kit.es51.js.map +1 -1
- package/dist/es/standards-agent-kit.es52.js +77 -0
- package/dist/es/standards-agent-kit.es52.js.map +1 -0
- package/dist/es/standards-agent-kit.es6.js +160 -4
- package/dist/es/standards-agent-kit.es6.js.map +1 -1
- package/dist/es/tools/inscriber/InscribeHashinalTool.d.ts +2 -10
- package/dist/es/types/inscription-response.d.ts +8 -0
- package/dist/es/utils/inscription-utils.d.ts +21 -0
- package/dist/umd/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/umd/interfaces/FormValidatable.d.ts +4 -13
- package/dist/umd/standards-agent-kit.umd.js +1 -1
- package/dist/umd/standards-agent-kit.umd.js.map +1 -1
- package/dist/umd/tools/inscriber/InscribeHashinalTool.d.ts +2 -10
- package/dist/umd/types/inscription-response.d.ts +8 -0
- package/dist/umd/utils/inscription-utils.d.ts +21 -0
- package/package.json +9 -4
- package/src/builders/hcs10/hcs10-builder.ts +4 -0
- package/src/builders/inscriber/inscriber-builder.ts +235 -2
- package/src/interfaces/FormValidatable.ts +9 -12
- package/src/tools/inscriber/InscribeFromBufferTool.ts +48 -19
- package/src/tools/inscriber/InscribeFromFileTool.ts +10 -13
- package/src/tools/inscriber/InscribeFromUrlTool.ts +15 -11
- package/src/tools/inscriber/InscribeHashinalTool.ts +42 -90
- package/src/tools/inscriber/RetrieveInscriptionTool.ts +15 -16
- package/src/types/inscription-response.ts +27 -0
- package/src/utils/inscription-utils.ts +53 -0
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
1
|
import { z } from 'zod';
|
|
3
2
|
import { BaseInscriberQueryTool } from './base-inscriber-tools';
|
|
4
3
|
import {
|
|
@@ -6,6 +5,7 @@ import {
|
|
|
6
5
|
InscriptionInput,
|
|
7
6
|
ContentResolverRegistry,
|
|
8
7
|
Logger,
|
|
8
|
+
InscriptionResult,
|
|
9
9
|
} from '@hashgraphonline/standards-sdk';
|
|
10
10
|
import { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';
|
|
11
11
|
import { validateHIP412Metadata } from '../../validation/hip412-schemas';
|
|
@@ -19,9 +19,14 @@ import {
|
|
|
19
19
|
createInscriptionSuccess,
|
|
20
20
|
createInscriptionQuote,
|
|
21
21
|
createInscriptionError,
|
|
22
|
+
createInscriptionPending,
|
|
22
23
|
InscriptionResponse,
|
|
23
24
|
} from '../../types/inscription-response';
|
|
24
25
|
import { FormValidatable } from '../../interfaces/FormValidatable';
|
|
26
|
+
import {
|
|
27
|
+
extractTopicIds,
|
|
28
|
+
buildInscriptionLinks,
|
|
29
|
+
} from '../../utils/inscription-utils';
|
|
25
30
|
|
|
26
31
|
/**
|
|
27
32
|
* Network-specific Hashinal block configuration for HashLink blocks
|
|
@@ -46,7 +51,6 @@ const HASHLINK_BLOCK_CONFIG = {
|
|
|
46
51
|
* @param network The network type to get configuration for
|
|
47
52
|
* @returns Network-specific block configuration with blockId, hashLink, and template
|
|
48
53
|
*/
|
|
49
|
-
// @ts-ignore - keep untyped to satisfy mixed parser while using runtime narrowing
|
|
50
54
|
function getHashLinkBlockId(network) {
|
|
51
55
|
const config =
|
|
52
56
|
network === 'mainnet'
|
|
@@ -58,8 +62,6 @@ function getHashLinkBlockId(network) {
|
|
|
58
62
|
return config;
|
|
59
63
|
}
|
|
60
64
|
|
|
61
|
-
// Note: Using inline return type annotations to avoid parser issues with interface declarations
|
|
62
|
-
|
|
63
65
|
/**
|
|
64
66
|
* Schema for inscribing Hashinal NFT
|
|
65
67
|
*/
|
|
@@ -205,7 +207,6 @@ export class InscribeHashinalTool
|
|
|
205
207
|
description =
|
|
206
208
|
'Tool for inscribing Hashinal NFTs. CRITICAL: When user provides content (url/contentRef/base64Data), call with ONLY the content parameters - DO NOT auto-generate name, description, creator, or attributes. A form will be automatically shown to collect metadata from the user. Only include metadata parameters if the user explicitly provided them in their message.';
|
|
207
209
|
|
|
208
|
-
// Declare entity resolution preferences to preserve user-specified literal fields
|
|
209
210
|
getEntityResolutionPreferences(): Record<string, string> {
|
|
210
211
|
return {
|
|
211
212
|
name: 'literal',
|
|
@@ -350,20 +351,17 @@ export class InscribeHashinalTool
|
|
|
350
351
|
.describe('Trait name (e.g., "Rarity", "Color", "Style")'),
|
|
351
352
|
value: z
|
|
352
353
|
.union([z.string(), z.number()])
|
|
353
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
354
354
|
.describe('Trait value (e.g., "Epic", "Blue", 85)'),
|
|
355
355
|
})
|
|
356
356
|
)
|
|
357
357
|
)
|
|
358
358
|
.withRender(renderConfigs.array('NFT Attributes', 'Attribute'))
|
|
359
359
|
.optional()
|
|
360
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
361
360
|
.describe('Collectible traits and characteristics.'),
|
|
362
361
|
|
|
363
362
|
type: z
|
|
364
363
|
.string()
|
|
365
364
|
.optional()
|
|
366
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
367
365
|
.describe(
|
|
368
366
|
'Category or genre of the NFT (e.g., "Digital Art", "Photography", "Collectible Card)'
|
|
369
367
|
),
|
|
@@ -379,35 +377,6 @@ export class InscribeHashinalTool
|
|
|
379
377
|
return focusedSchema as unknown as z.ZodObject<z.ZodRawShape>;
|
|
380
378
|
}
|
|
381
379
|
|
|
382
|
-
/**
|
|
383
|
-
* Implementation of FormValidatable interface
|
|
384
|
-
* Validates metadata quality and provides detailed feedback
|
|
385
|
-
*/
|
|
386
|
-
validateMetadataQuality(input: unknown): {
|
|
387
|
-
needsForm: boolean;
|
|
388
|
-
reason: string;
|
|
389
|
-
} {
|
|
390
|
-
const inputObj = input as Record<string, unknown>;
|
|
391
|
-
const hasRequiredMetadata = !!(
|
|
392
|
-
inputObj.name &&
|
|
393
|
-
inputObj.description &&
|
|
394
|
-
inputObj.creator
|
|
395
|
-
);
|
|
396
|
-
|
|
397
|
-
if (!hasRequiredMetadata) {
|
|
398
|
-
return {
|
|
399
|
-
needsForm: true,
|
|
400
|
-
reason:
|
|
401
|
-
'Missing essential metadata (name, description, creator) for NFT creation',
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
|
|
405
|
-
return {
|
|
406
|
-
needsForm: false,
|
|
407
|
-
reason: 'All required metadata fields present',
|
|
408
|
-
};
|
|
409
|
-
}
|
|
410
|
-
|
|
411
380
|
protected async executeQuery(
|
|
412
381
|
params: z.infer<typeof inscribeHashinalSchema>,
|
|
413
382
|
_runManager?: CallbackManagerForToolRun
|
|
@@ -552,28 +521,26 @@ export class InscribeHashinalTool
|
|
|
552
521
|
});
|
|
553
522
|
|
|
554
523
|
result = await Promise.race([
|
|
555
|
-
this.inscriberBuilder.
|
|
524
|
+
this.inscriberBuilder.inscribeAuto
|
|
525
|
+
? this.inscriberBuilder.inscribeAuto(inscriptionData, options)
|
|
526
|
+
: this.inscriberBuilder.inscribe(inscriptionData, options),
|
|
556
527
|
timeoutPromise,
|
|
557
528
|
]);
|
|
558
529
|
} else {
|
|
559
|
-
result =
|
|
530
|
+
result = this.inscriberBuilder.inscribeAuto
|
|
531
|
+
? await this.inscriberBuilder.inscribeAuto(inscriptionData, options)
|
|
532
|
+
: await this.inscriberBuilder.inscribe(inscriptionData, options);
|
|
560
533
|
}
|
|
561
534
|
|
|
562
535
|
if (result.confirmed && !result.quote) {
|
|
563
|
-
const
|
|
564
|
-
result.inscription as { topic_id?: string; jsonTopicId?: string }
|
|
565
|
-
)?.topic_id;
|
|
566
|
-
const jsonTopicId = (
|
|
567
|
-
result.inscription as { topic_id?: string; jsonTopicId?: string }
|
|
568
|
-
)?.jsonTopicId;
|
|
536
|
+
const ids = extractTopicIds(result.inscription, result.result);
|
|
569
537
|
const network = options.network || 'testnet';
|
|
570
|
-
|
|
571
|
-
const cdnUrl = jsonTopicId
|
|
572
|
-
? `https://kiloscribe.com/api/inscription-cdn/${jsonTopicId}?network=${network}`
|
|
573
|
-
: null;
|
|
574
|
-
|
|
575
538
|
const fileStandard = params.fileStandard || '1';
|
|
576
|
-
const hrl
|
|
539
|
+
const { hrl, cdnUrl, topicId } = buildInscriptionLinks(
|
|
540
|
+
ids,
|
|
541
|
+
network,
|
|
542
|
+
fileStandard
|
|
543
|
+
);
|
|
577
544
|
const standardType = fileStandard === '6' ? 'Dynamic' : 'Static';
|
|
578
545
|
|
|
579
546
|
if (!hrl) {
|
|
@@ -589,11 +556,10 @@ export class InscribeHashinalTool
|
|
|
589
556
|
|
|
590
557
|
const inscriptionResponse = createInscriptionSuccess({
|
|
591
558
|
hrl,
|
|
592
|
-
topicId:
|
|
559
|
+
topicId: topicId || 'unknown',
|
|
593
560
|
standard: standardType as 'Static' | 'Dynamic',
|
|
594
561
|
cdnUrl: cdnUrl || undefined,
|
|
595
|
-
transactionId: (result.result as
|
|
596
|
-
?.transactionId,
|
|
562
|
+
transactionId: (result.result as InscriptionResult)?.transactionId,
|
|
597
563
|
metadata: {
|
|
598
564
|
name: params.name,
|
|
599
565
|
creator: params.creator,
|
|
@@ -604,11 +570,10 @@ export class InscribeHashinalTool
|
|
|
604
570
|
});
|
|
605
571
|
|
|
606
572
|
this.onEntityCreated?.({
|
|
607
|
-
entityId:
|
|
573
|
+
entityId: topicId || 'unknown',
|
|
608
574
|
entityName: params.name || 'Unnamed Inscription',
|
|
609
|
-
entityType: '
|
|
610
|
-
transactionId: (result.result as
|
|
611
|
-
?.transactionId,
|
|
575
|
+
entityType: 'topicId',
|
|
576
|
+
transactionId: (result.result as InscriptionResult)?.transactionId,
|
|
612
577
|
});
|
|
613
578
|
|
|
614
579
|
if (params.withHashLinkBlocks) {
|
|
@@ -622,7 +587,6 @@ export class InscribeHashinalTool
|
|
|
622
587
|
|
|
623
588
|
inscriptionResponse.hashLinkBlock = blockData;
|
|
624
589
|
} catch (blockError) {
|
|
625
|
-
// Log error but don't fail the inscription
|
|
626
590
|
const logger = new Logger({ module: 'InscribeHashinalTool' });
|
|
627
591
|
logger.error('Failed to create HashLink block', {
|
|
628
592
|
error: blockError,
|
|
@@ -632,32 +596,24 @@ export class InscribeHashinalTool
|
|
|
632
596
|
|
|
633
597
|
return inscriptionResponse;
|
|
634
598
|
} else if (!result.quote && !result.confirmed) {
|
|
635
|
-
const
|
|
636
|
-
|
|
637
|
-
)?.topic_id;
|
|
638
|
-
const jsonTopicId = (
|
|
639
|
-
result.inscription as { topic_id?: string; jsonTopicId?: string }
|
|
640
|
-
)?.jsonTopicId;
|
|
641
|
-
|
|
642
|
-
if (jsonTopicId || imageTopicId) {
|
|
599
|
+
const ids = extractTopicIds(result.inscription, result.result);
|
|
600
|
+
if (ids.jsonTopicId || ids.topicId) {
|
|
643
601
|
const network = options.network || 'testnet';
|
|
644
|
-
const cdnUrl = jsonTopicId
|
|
645
|
-
? `https://kiloscribe.com/api/inscription-cdn/${jsonTopicId}?network=${network}`
|
|
646
|
-
: null;
|
|
647
|
-
|
|
648
602
|
const fileStandard = params.fileStandard || '1';
|
|
649
|
-
const hrl =
|
|
650
|
-
|
|
651
|
-
|
|
603
|
+
const { hrl, cdnUrl, topicId } = buildInscriptionLinks(
|
|
604
|
+
ids,
|
|
605
|
+
network,
|
|
606
|
+
fileStandard
|
|
607
|
+
);
|
|
652
608
|
const standardType = fileStandard === '6' ? 'Dynamic' : 'Static';
|
|
653
609
|
|
|
654
610
|
if (hrl) {
|
|
655
611
|
const inscriptionResponse = createInscriptionSuccess({
|
|
656
612
|
hrl,
|
|
657
|
-
topicId:
|
|
613
|
+
topicId: topicId || 'unknown',
|
|
658
614
|
standard: standardType as 'Static' | 'Dynamic',
|
|
659
615
|
cdnUrl: cdnUrl || undefined,
|
|
660
|
-
transactionId: (result.result as
|
|
616
|
+
transactionId: (result.result as InscriptionResult)
|
|
661
617
|
?.transactionId,
|
|
662
618
|
metadata: {
|
|
663
619
|
name: params.name,
|
|
@@ -669,10 +625,10 @@ export class InscribeHashinalTool
|
|
|
669
625
|
});
|
|
670
626
|
|
|
671
627
|
this.onEntityCreated?.({
|
|
672
|
-
entityId:
|
|
628
|
+
entityId: topicId || 'unknown',
|
|
673
629
|
entityName: params.name || 'Unnamed Inscription',
|
|
674
|
-
entityType: '
|
|
675
|
-
transactionId: (result.result as
|
|
630
|
+
entityType: 'topicId',
|
|
631
|
+
transactionId: (result.result as InscriptionResult)
|
|
676
632
|
?.transactionId,
|
|
677
633
|
});
|
|
678
634
|
|
|
@@ -687,7 +643,6 @@ export class InscribeHashinalTool
|
|
|
687
643
|
|
|
688
644
|
inscriptionResponse.hashLinkBlock = blockData;
|
|
689
645
|
} catch (blockError) {
|
|
690
|
-
// Log error but don't fail the inscription
|
|
691
646
|
const logger = new Logger({ module: 'InscribeHashinalTool' });
|
|
692
647
|
logger.error('Failed to create HashLink block', {
|
|
693
648
|
error: blockError,
|
|
@@ -700,17 +655,14 @@ export class InscribeHashinalTool
|
|
|
700
655
|
}
|
|
701
656
|
|
|
702
657
|
const transactionId =
|
|
703
|
-
(result.result as
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
code: 'INSCRIPTION_PENDING',
|
|
707
|
-
details: `Inscription submitted but not yet confirmed. Transaction ID: ${transactionId}`,
|
|
708
|
-
suggestions: [
|
|
709
|
-
'Wait a few moments for confirmation',
|
|
710
|
-
'Check the transaction status on a Hedera explorer',
|
|
711
|
-
"Try the inscription again if it doesn't confirm within 5 minutes",
|
|
712
|
-
],
|
|
658
|
+
(result.result as InscriptionResult)?.transactionId || 'unknown';
|
|
659
|
+
const pending = createInscriptionPending({
|
|
660
|
+
transactionId,
|
|
713
661
|
});
|
|
662
|
+
return {
|
|
663
|
+
...pending,
|
|
664
|
+
metadata: { transactionId },
|
|
665
|
+
} as unknown as InscriptionResponse;
|
|
714
666
|
} else {
|
|
715
667
|
return createInscriptionError({
|
|
716
668
|
code: 'UNKNOWN_STATE',
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import { BaseInscriberQueryTool } from './base-inscriber-tools';
|
|
3
3
|
import { CallbackManagerForToolRun } from '@langchain/core/callbacks/manager';
|
|
4
|
+
import type { RetrievedInscriptionResult } from '@hashgraphonline/standards-sdk';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Schema for retrieving inscription
|
|
@@ -51,7 +52,7 @@ export class RetrieveInscriptionTool extends BaseInscriberQueryTool<typeof retri
|
|
|
51
52
|
params: z.infer<typeof retrieveInscriptionSchema>,
|
|
52
53
|
_runManager?: CallbackManagerForToolRun
|
|
53
54
|
): Promise<InscriptionRetrievalResult> {
|
|
54
|
-
const result = await this.inscriberBuilder.retrieveInscription(
|
|
55
|
+
const result: RetrievedInscriptionResult = await this.inscriberBuilder.retrieveInscription(
|
|
55
56
|
params.transactionId,
|
|
56
57
|
{
|
|
57
58
|
apiKey: params.apiKey,
|
|
@@ -59,23 +60,21 @@ export class RetrieveInscriptionTool extends BaseInscriberQueryTool<typeof retri
|
|
|
59
60
|
}
|
|
60
61
|
);
|
|
61
62
|
|
|
62
|
-
const typedResult = result as unknown as Record<string, unknown>;
|
|
63
|
-
|
|
64
63
|
return {
|
|
65
|
-
inscriptionId:
|
|
66
|
-
transactionId: result.transactionId || 'unknown',
|
|
67
|
-
topicId:
|
|
68
|
-
status: result.status || 'unknown',
|
|
69
|
-
holderId:
|
|
64
|
+
inscriptionId: (result as unknown as { inscriptionId?: string }).inscriptionId,
|
|
65
|
+
transactionId: (result as unknown as { transactionId?: string }).transactionId || 'unknown',
|
|
66
|
+
topicId: (result as unknown as { topic_id?: string; topicId?: string }).topic_id || (result as unknown as { topicId?: string }).topicId,
|
|
67
|
+
status: (result as unknown as { status?: string }).status || 'unknown',
|
|
68
|
+
holderId: (result as unknown as { holderId?: string }).holderId,
|
|
70
69
|
metadata: result.metadata,
|
|
71
|
-
tags:
|
|
72
|
-
mode: result.mode,
|
|
73
|
-
chunks:
|
|
74
|
-
createdAt:
|
|
75
|
-
completedAt: (
|
|
76
|
-
fileUrl: result.fileUrl,
|
|
77
|
-
mimeType:
|
|
78
|
-
fileSize:
|
|
70
|
+
tags: (result as unknown as { tags?: unknown }).tags,
|
|
71
|
+
mode: (result as unknown as { mode?: string }).mode,
|
|
72
|
+
chunks: (result as unknown as { chunks?: unknown }).chunks,
|
|
73
|
+
createdAt: (result as unknown as { createdAt?: string }).createdAt,
|
|
74
|
+
completedAt: (result as unknown as { completed?: string; completedAt?: string }).completed || (result as unknown as { completedAt?: string }).completedAt,
|
|
75
|
+
fileUrl: (result as unknown as { fileUrl?: string }).fileUrl,
|
|
76
|
+
mimeType: (result as unknown as { mimeType?: string }).mimeType,
|
|
77
|
+
fileSize: (result as unknown as { fileSize?: number }).fileSize,
|
|
79
78
|
};
|
|
80
79
|
}
|
|
81
80
|
}
|
|
@@ -232,3 +232,30 @@ export function createInscriptionError(params: {
|
|
|
232
232
|
},
|
|
233
233
|
};
|
|
234
234
|
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Helper for pending inscription state (submitted but not yet confirmed)
|
|
238
|
+
*/
|
|
239
|
+
export function createInscriptionPending(params: {
|
|
240
|
+
transactionId: string;
|
|
241
|
+
details?: string;
|
|
242
|
+
suggestions?: string[];
|
|
243
|
+
}): InscriptionErrorResponse {
|
|
244
|
+
const { transactionId, details, suggestions } = params;
|
|
245
|
+
const d = details || `Inscription submitted but not yet confirmed. Transaction ID: ${transactionId}`;
|
|
246
|
+
return {
|
|
247
|
+
success: false,
|
|
248
|
+
type: 'error',
|
|
249
|
+
title: 'Inscription Submitted (Pending)',
|
|
250
|
+
message: d,
|
|
251
|
+
error: {
|
|
252
|
+
code: 'INSCRIPTION_PENDING',
|
|
253
|
+
details: d,
|
|
254
|
+
suggestions: suggestions || [
|
|
255
|
+
'Wait a few moments for confirmation',
|
|
256
|
+
'Check the transaction status on a Hedera explorer',
|
|
257
|
+
"Try the inscription again if it doesn't confirm within 5 minutes",
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
};
|
|
261
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export type NetworkType = 'mainnet' | 'testnet';
|
|
2
|
+
|
|
3
|
+
export interface TopicIds {
|
|
4
|
+
jsonTopicId?: string;
|
|
5
|
+
topicId?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
function getStringProp(obj: unknown, key: string): string | undefined {
|
|
9
|
+
if (!obj || typeof obj !== 'object') return undefined;
|
|
10
|
+
const val = (obj as Record<string, unknown>)[key];
|
|
11
|
+
return typeof val === 'string' && val.trim() ? val : undefined;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Extract topic ids from an inscription and/or result object without using any.
|
|
16
|
+
* - Prefers jsonTopicId when present (for CDN linking)
|
|
17
|
+
* - Collects topic_id/topicId from either inscription or result
|
|
18
|
+
*/
|
|
19
|
+
export function extractTopicIds(
|
|
20
|
+
inscription: unknown,
|
|
21
|
+
result?: unknown
|
|
22
|
+
): TopicIds {
|
|
23
|
+
const jsonTopicId = getStringProp(inscription, 'jsonTopicId');
|
|
24
|
+
|
|
25
|
+
const imageTopicId =
|
|
26
|
+
getStringProp(inscription, 'topic_id') ||
|
|
27
|
+
getStringProp(inscription, 'topicId') ||
|
|
28
|
+
getStringProp(result, 'topicId') ||
|
|
29
|
+
getStringProp(result, 'topic_id');
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
jsonTopicId: jsonTopicId,
|
|
33
|
+
topicId: imageTopicId,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Build HRL/CDN URLs from extracted topic ids.
|
|
39
|
+
* - HRL prefers jsonTopicId, falls back to topicId
|
|
40
|
+
* - CDN URL only provided when jsonTopicId is present
|
|
41
|
+
*/
|
|
42
|
+
export function buildInscriptionLinks(
|
|
43
|
+
ids: TopicIds,
|
|
44
|
+
network: NetworkType,
|
|
45
|
+
fileStandard: string = '1'
|
|
46
|
+
): { hrl?: string; cdnUrl?: string; topicId?: string } {
|
|
47
|
+
const chosen = ids.jsonTopicId || ids.topicId;
|
|
48
|
+
const hrl = chosen ? `hcs://${fileStandard}/${chosen}` : undefined;
|
|
49
|
+
const cdnUrl = ids.jsonTopicId
|
|
50
|
+
? `https://kiloscribe.com/api/inscription-cdn/${ids.jsonTopicId}?network=${network}`
|
|
51
|
+
: undefined;
|
|
52
|
+
return { hrl, cdnUrl, topicId: chosen };
|
|
53
|
+
}
|