@hashgraphonline/standards-agent-kit 0.2.136 → 0.2.138
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/hcs10/hcs10-builder.d.ts +1 -0
- package/dist/cjs/builders/hcs2/hcs2-builder.d.ts +8 -7
- package/dist/cjs/builders/hcs6/hcs6-builder.d.ts +5 -4
- package/dist/cjs/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/cjs/index.d.ts +4 -0
- package/dist/cjs/signing/bytes-registry.d.ts +17 -0
- package/dist/cjs/signing/signer-provider.d.ts +45 -0
- package/dist/cjs/standards-agent-kit.cjs +1 -1
- package/dist/cjs/standards-agent-kit.cjs.map +1 -1
- package/dist/cjs/tools/hcs10/InitiateConnectionTool.d.ts +4 -4
- package/dist/cjs/tools/hcs2/CreateRegistryTool.d.ts +2 -2
- package/dist/cjs/tools/hcs2/DeleteEntryTool.d.ts +2 -2
- package/dist/cjs/tools/hcs2/UpdateEntryTool.d.ts +2 -2
- package/dist/cjs/tools/hcs6/RegisterDynamicHashinalTool.d.ts +10 -10
- package/dist/cjs/tools/hcs6/UpdateDynamicHashinalTool.d.ts +8 -8
- package/dist/cjs/tools/inscriber/InscribeFromBufferTool.d.ts +5 -4
- package/dist/cjs/tools/inscriber/InscribeFromFileTool.d.ts +2 -2
- package/dist/cjs/tools/inscriber/InscribeFromUrlTool.d.ts +4 -4
- package/dist/cjs/tools/inscriber/InscribeHashinalTool.d.ts +3 -3
- package/dist/cjs/types/inscription-response.d.ts +8 -0
- package/dist/cjs/types/tx-results.d.ts +15 -0
- package/dist/cjs/utils/CodedError.d.ts +4 -0
- package/dist/cjs/utils/inscription-utils.d.ts +21 -0
- package/dist/cjs/validation/hip412-schemas.d.ts +2 -2
- package/dist/es/builders/hcs10/hcs10-builder.d.ts +1 -0
- package/dist/es/builders/hcs2/hcs2-builder.d.ts +8 -7
- package/dist/es/builders/hcs6/hcs6-builder.d.ts +5 -4
- package/dist/es/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/es/index.d.ts +4 -0
- package/dist/es/signing/bytes-registry.d.ts +17 -0
- package/dist/es/signing/signer-provider.d.ts +45 -0
- package/dist/es/standards-agent-kit.es.js +46 -42
- package/dist/es/standards-agent-kit.es.js.map +1 -1
- package/dist/es/standards-agent-kit.es10.js +24 -83
- package/dist/es/standards-agent-kit.es10.js.map +1 -1
- package/dist/es/standards-agent-kit.es11.js +224 -20
- package/dist/es/standards-agent-kit.es11.js.map +1 -1
- package/dist/es/standards-agent-kit.es12.js +78 -27
- package/dist/es/standards-agent-kit.es12.js.map +1 -1
- package/dist/es/standards-agent-kit.es13.js +26 -36
- package/dist/es/standards-agent-kit.es13.js.map +1 -1
- package/dist/es/standards-agent-kit.es14.js +17 -39
- package/dist/es/standards-agent-kit.es14.js.map +1 -1
- package/dist/es/standards-agent-kit.es15.js +36 -58
- package/dist/es/standards-agent-kit.es15.js.map +1 -1
- package/dist/es/standards-agent-kit.es16.js +45 -18
- package/dist/es/standards-agent-kit.es16.js.map +1 -1
- package/dist/es/standards-agent-kit.es17.js +53 -16
- package/dist/es/standards-agent-kit.es17.js.map +1 -1
- package/dist/es/standards-agent-kit.es18.js +18 -28
- package/dist/es/standards-agent-kit.es18.js.map +1 -1
- package/dist/es/standards-agent-kit.es19.js +26 -12
- package/dist/es/standards-agent-kit.es19.js.map +1 -1
- package/dist/es/standards-agent-kit.es20.js +38 -136
- package/dist/es/standards-agent-kit.es20.js.map +1 -1
- package/dist/es/standards-agent-kit.es21.js +13 -24
- package/dist/es/standards-agent-kit.es21.js.map +1 -1
- package/dist/es/standards-agent-kit.es22.js +136 -39
- package/dist/es/standards-agent-kit.es22.js.map +1 -1
- package/dist/es/standards-agent-kit.es23.js +25 -41
- package/dist/es/standards-agent-kit.es23.js.map +1 -1
- package/dist/es/standards-agent-kit.es24.js +49 -31
- package/dist/es/standards-agent-kit.es24.js.map +1 -1
- package/dist/es/standards-agent-kit.es25.js +34 -18
- package/dist/es/standards-agent-kit.es25.js.map +1 -1
- package/dist/es/standards-agent-kit.es26.js +35 -19
- package/dist/es/standards-agent-kit.es26.js.map +1 -1
- package/dist/es/standards-agent-kit.es27.js +45 -32
- package/dist/es/standards-agent-kit.es27.js.map +1 -1
- package/dist/es/standards-agent-kit.es28.js +54 -25
- package/dist/es/standards-agent-kit.es28.js.map +1 -1
- package/dist/es/standards-agent-kit.es29.js +35 -23
- package/dist/es/standards-agent-kit.es29.js.map +1 -1
- package/dist/es/standards-agent-kit.es3.js +41 -1545
- package/dist/es/standards-agent-kit.es3.js.map +1 -1
- package/dist/es/standards-agent-kit.es30.js +23 -39
- package/dist/es/standards-agent-kit.es30.js.map +1 -1
- package/dist/es/standards-agent-kit.es31.js +30 -28
- package/dist/es/standards-agent-kit.es31.js.map +1 -1
- package/dist/es/standards-agent-kit.es32.js +45 -32
- package/dist/es/standards-agent-kit.es32.js.map +1 -1
- package/dist/es/standards-agent-kit.es33.js +50 -89
- package/dist/es/standards-agent-kit.es33.js.map +1 -1
- package/dist/es/standards-agent-kit.es34.js +35 -228
- package/dist/es/standards-agent-kit.es34.js.map +1 -1
- package/dist/es/standards-agent-kit.es35.js +87 -212
- package/dist/es/standards-agent-kit.es35.js.map +1 -1
- package/dist/es/standards-agent-kit.es36.js +188 -128
- package/dist/es/standards-agent-kit.es36.js.map +1 -1
- package/dist/es/standards-agent-kit.es37.js +167 -561
- package/dist/es/standards-agent-kit.es37.js.map +1 -1
- package/dist/es/standards-agent-kit.es38.js +236 -31
- package/dist/es/standards-agent-kit.es38.js.map +1 -1
- package/dist/es/standards-agent-kit.es39.js +483 -206
- package/dist/es/standards-agent-kit.es39.js.map +1 -1
- package/dist/es/standards-agent-kit.es4.js +359 -81
- package/dist/es/standards-agent-kit.es4.js.map +1 -1
- package/dist/es/standards-agent-kit.es40.js +39 -135
- package/dist/es/standards-agent-kit.es40.js.map +1 -1
- package/dist/es/standards-agent-kit.es41.js +244 -28
- package/dist/es/standards-agent-kit.es41.js.map +1 -1
- package/dist/es/standards-agent-kit.es42.js +132 -418
- package/dist/es/standards-agent-kit.es42.js.map +1 -1
- package/dist/es/standards-agent-kit.es43.js +28 -184
- package/dist/es/standards-agent-kit.es43.js.map +1 -1
- package/dist/es/standards-agent-kit.es44.js +423 -3
- package/dist/es/standards-agent-kit.es44.js.map +1 -1
- package/dist/es/standards-agent-kit.es45.js +185 -24
- package/dist/es/standards-agent-kit.es45.js.map +1 -1
- package/dist/es/standards-agent-kit.es46.js +3 -3
- package/dist/es/standards-agent-kit.es46.js.map +1 -1
- package/dist/es/standards-agent-kit.es47.js +21 -50
- package/dist/es/standards-agent-kit.es47.js.map +1 -1
- package/dist/es/standards-agent-kit.es48.js +8 -3
- package/dist/es/standards-agent-kit.es48.js.map +1 -1
- package/dist/es/standards-agent-kit.es49.js +3 -39
- package/dist/es/standards-agent-kit.es49.js.map +1 -1
- package/dist/es/standards-agent-kit.es5.js +1747 -73
- package/dist/es/standards-agent-kit.es5.js.map +1 -1
- package/dist/es/standards-agent-kit.es50.js +18 -16
- package/dist/es/standards-agent-kit.es50.js.map +1 -1
- package/dist/es/standards-agent-kit.es51.js +49 -49
- package/dist/es/standards-agent-kit.es51.js.map +1 -1
- package/dist/es/standards-agent-kit.es52.js +6 -0
- package/dist/es/standards-agent-kit.es52.js.map +1 -0
- package/dist/es/standards-agent-kit.es53.js +43 -0
- package/dist/es/standards-agent-kit.es53.js.map +1 -0
- package/dist/es/standards-agent-kit.es54.js +22 -0
- package/dist/es/standards-agent-kit.es54.js.map +1 -0
- package/dist/es/standards-agent-kit.es55.js +77 -0
- package/dist/es/standards-agent-kit.es55.js.map +1 -0
- package/dist/es/standards-agent-kit.es56.js +7 -0
- package/dist/es/standards-agent-kit.es56.js.map +1 -0
- package/dist/es/standards-agent-kit.es6.js +347 -32
- package/dist/es/standards-agent-kit.es6.js.map +1 -1
- package/dist/es/standards-agent-kit.es7.js +142 -293
- package/dist/es/standards-agent-kit.es7.js.map +1 -1
- package/dist/es/standards-agent-kit.es8.js +201 -21
- package/dist/es/standards-agent-kit.es8.js.map +1 -1
- package/dist/es/standards-agent-kit.es9.js +301 -213
- package/dist/es/standards-agent-kit.es9.js.map +1 -1
- package/dist/es/tools/hcs10/InitiateConnectionTool.d.ts +4 -4
- package/dist/es/tools/hcs2/CreateRegistryTool.d.ts +2 -2
- package/dist/es/tools/hcs2/DeleteEntryTool.d.ts +2 -2
- package/dist/es/tools/hcs2/UpdateEntryTool.d.ts +2 -2
- package/dist/es/tools/hcs6/RegisterDynamicHashinalTool.d.ts +10 -10
- package/dist/es/tools/hcs6/UpdateDynamicHashinalTool.d.ts +8 -8
- package/dist/es/tools/inscriber/InscribeFromBufferTool.d.ts +5 -4
- package/dist/es/tools/inscriber/InscribeFromFileTool.d.ts +2 -2
- package/dist/es/tools/inscriber/InscribeFromUrlTool.d.ts +4 -4
- package/dist/es/tools/inscriber/InscribeHashinalTool.d.ts +3 -3
- package/dist/es/types/inscription-response.d.ts +8 -0
- package/dist/es/types/tx-results.d.ts +15 -0
- package/dist/es/utils/CodedError.d.ts +4 -0
- package/dist/es/utils/inscription-utils.d.ts +21 -0
- package/dist/es/validation/hip412-schemas.d.ts +2 -2
- package/dist/umd/builders/hcs10/hcs10-builder.d.ts +1 -0
- package/dist/umd/builders/hcs2/hcs2-builder.d.ts +8 -7
- package/dist/umd/builders/hcs6/hcs6-builder.d.ts +5 -4
- package/dist/umd/builders/inscriber/inscriber-builder.d.ts +32 -1
- package/dist/umd/index.d.ts +4 -0
- package/dist/umd/signing/bytes-registry.d.ts +17 -0
- package/dist/umd/signing/signer-provider.d.ts +45 -0
- 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/hcs10/InitiateConnectionTool.d.ts +4 -4
- package/dist/umd/tools/hcs2/CreateRegistryTool.d.ts +2 -2
- package/dist/umd/tools/hcs2/DeleteEntryTool.d.ts +2 -2
- package/dist/umd/tools/hcs2/UpdateEntryTool.d.ts +2 -2
- package/dist/umd/tools/hcs6/RegisterDynamicHashinalTool.d.ts +10 -10
- package/dist/umd/tools/hcs6/UpdateDynamicHashinalTool.d.ts +8 -8
- package/dist/umd/tools/inscriber/InscribeFromBufferTool.d.ts +5 -4
- package/dist/umd/tools/inscriber/InscribeFromFileTool.d.ts +2 -2
- package/dist/umd/tools/inscriber/InscribeFromUrlTool.d.ts +4 -4
- package/dist/umd/tools/inscriber/InscribeHashinalTool.d.ts +3 -3
- package/dist/umd/types/inscription-response.d.ts +8 -0
- package/dist/umd/types/tx-results.d.ts +15 -0
- package/dist/umd/utils/CodedError.d.ts +4 -0
- package/dist/umd/utils/inscription-utils.d.ts +21 -0
- package/dist/umd/validation/hip412-schemas.d.ts +2 -2
- package/package.json +10 -5
- package/src/builders/hcs10/hcs10-builder.ts +239 -6
- package/src/builders/hcs2/hcs2-builder.ts +302 -9
- package/src/builders/hcs6/hcs6-builder.ts +79 -4
- package/src/builders/inscriber/inscriber-builder.ts +235 -2
- package/src/hcs10/HCS10Client.ts +1 -1
- package/src/index.ts +5 -1
- package/src/lib/zod-render/schema-extension.ts +0 -1
- package/src/signing/bytes-registry.ts +501 -0
- package/src/signing/signer-provider.ts +120 -0
- package/src/tools/hcs2/CreateRegistryTool.ts +30 -5
- package/src/tools/hcs2/DeleteEntryTool.ts +16 -2
- package/src/tools/hcs2/MigrateRegistryTool.ts +16 -2
- package/src/tools/hcs2/QueryRegistryTool.ts +11 -2
- package/src/tools/hcs2/RegisterEntryTool.ts +17 -3
- package/src/tools/hcs2/UpdateEntryTool.ts +16 -2
- package/src/tools/hcs6/CreateDynamicRegistryTool.ts +17 -3
- package/src/tools/hcs6/RegisterDynamicHashinalTool.ts +17 -3
- package/src/tools/hcs6/UpdateDynamicHashinalTool.ts +17 -3
- package/src/tools/inscriber/InscribeFromBufferTool.ts +126 -21
- package/src/tools/inscriber/InscribeFromFileTool.ts +10 -13
- package/src/tools/inscriber/InscribeFromUrlTool.ts +15 -11
- package/src/tools/inscriber/InscribeHashinalTool.ts +40 -168
- package/src/tools/inscriber/RetrieveInscriptionTool.ts +15 -16
- package/src/types/inscription-response.ts +27 -0
- package/src/types/tx-results.ts +18 -0
- package/src/utils/CodedError.ts +8 -0
- package/src/utils/Encryption.ts +0 -2
- package/src/utils/ensure-agent-has-hbar.ts +4 -5
- package/src/utils/inscription-utils.ts +53 -0
|
@@ -1,314 +1,137 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
import { BaseInscriberQueryTool } from "./standards-agent-kit.
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
};
|
|
21
|
-
function getHashLinkBlockId(network) {
|
|
22
|
-
const config = network === "mainnet" ? HASHLINK_BLOCK_CONFIG.mainnet : HASHLINK_BLOCK_CONFIG.testnet;
|
|
23
|
-
if (!config || config.blockId === "0.0.TBD") {
|
|
24
|
-
return HASHLINK_BLOCK_CONFIG.testnet;
|
|
25
|
-
}
|
|
26
|
-
return config;
|
|
27
|
-
}
|
|
28
|
-
const inscribeHashinalSchema = extendZodSchema(
|
|
29
|
-
z.object({
|
|
30
|
-
url: z.string().optional().describe(
|
|
31
|
-
"The URL of the content to inscribe as Hashinal NFT (use this OR contentRef)"
|
|
32
|
-
),
|
|
33
|
-
contentRef: contentRefSchema.optional().describe(
|
|
34
|
-
'Content reference ID in format "content-ref:[id]" for already stored content (use this OR url)'
|
|
35
|
-
),
|
|
36
|
-
base64Data: z.string().optional().describe(
|
|
37
|
-
"Base64 encoded content data (use this if neither url nor contentRef provided)"
|
|
38
|
-
),
|
|
39
|
-
fileName: z.string().optional().describe(
|
|
40
|
-
"File name for the content (required when using base64Data or contentRef)"
|
|
41
|
-
),
|
|
42
|
-
mimeType: z.string().optional().describe('MIME type of the content (e.g., "image/png", "image/jpeg")'),
|
|
43
|
-
name: z.string().optional().describe(
|
|
44
|
-
'Display name for the NFT (e.g., "Sunset Landscape #42", "Digital Abstract Art")'
|
|
45
|
-
),
|
|
46
|
-
creator: z.string().optional().describe(
|
|
47
|
-
'Creator account ID, artist name, or brand (e.g., "0.0.123456", "ArtistName", "StudioBrand")'
|
|
48
|
-
),
|
|
49
|
-
description: z.string().optional().describe(
|
|
50
|
-
"Meaningful description of the artwork, story, or concept behind this NFT"
|
|
51
|
-
),
|
|
52
|
-
type: z.string().optional().describe(
|
|
53
|
-
'Category or genre of the NFT (e.g., "Digital Art", "Photography", "Collectible Card")'
|
|
54
|
-
),
|
|
55
|
-
attributes: extendZodSchema(
|
|
56
|
-
z.array(
|
|
57
|
-
z.object({
|
|
58
|
-
trait_type: z.string(),
|
|
59
|
-
value: z.union([z.string(), z.number()])
|
|
60
|
-
})
|
|
61
|
-
)
|
|
62
|
-
).withRender(renderConfigs.array("NFT Attributes", "Attribute")).optional().describe(
|
|
63
|
-
'Collectible traits and characteristics (e.g., "Rarity": "Epic", "Color": "Blue", "Style": "Abstract")'
|
|
64
|
-
),
|
|
65
|
-
properties: z.record(z.unknown()).optional().describe("Additional properties"),
|
|
66
|
-
jsonFileURL: z.string().url().optional().describe("URL to JSON metadata file"),
|
|
67
|
-
fileStandard: z.enum(["1", "6"]).optional().default("1").describe(
|
|
68
|
-
"HCS file standard: 1 for static Hashinals (HCS-5), 6 for dynamic Hashinals (HCS-6)"
|
|
69
|
-
),
|
|
70
|
-
tags: z.array(z.string()).optional().describe("Tags to categorize the NFT"),
|
|
71
|
-
chunkSize: z.number().int().positive().optional().describe("Chunk size for large files"),
|
|
72
|
-
waitForConfirmation: z.boolean().optional().describe("Whether to wait for inscription confirmation"),
|
|
73
|
-
timeoutMs: z.number().int().positive().optional().describe(
|
|
74
|
-
"Timeout in milliseconds for inscription (default: no timeout - waits until completion)"
|
|
75
|
-
),
|
|
76
|
-
quoteOnly: z.boolean().optional().default(false).describe(
|
|
77
|
-
"If true, returns a cost quote instead of executing the inscription"
|
|
78
|
-
),
|
|
79
|
-
withHashLinkBlocks: z.boolean().optional().default(true).describe(
|
|
80
|
-
"If true, creates interactive HashLink blocks for the inscribed content and returns block data alongside the inscription response"
|
|
81
|
-
),
|
|
82
|
-
renderForm: z.boolean().optional().default(true).describe(
|
|
83
|
-
"Whether to show a form to collect metadata. Set to false only if user provided complete metadata including name, description, creator, and attributes."
|
|
84
|
-
)
|
|
85
|
-
})
|
|
86
|
-
).withRender({
|
|
87
|
-
fieldType: "object",
|
|
88
|
-
ui: {
|
|
89
|
-
label: "Inscribe Hashinal NFT",
|
|
90
|
-
description: "Create a Hashinal inscription for NFT minting"
|
|
91
|
-
}
|
|
2
|
+
import { BaseInscriberQueryTool } from "./standards-agent-kit.es35.js";
|
|
3
|
+
import * as fs from "fs/promises";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
import { extractTopicIds, buildInscriptionLinks } from "./standards-agent-kit.es50.js";
|
|
6
|
+
const inscribeFromFileSchema = z.object({
|
|
7
|
+
filePath: z.string().min(1, "File path cannot be empty").describe(
|
|
8
|
+
"The file path of the content to inscribe. Must point to a valid, non-empty file."
|
|
9
|
+
),
|
|
10
|
+
mode: z.enum(["file", "hashinal"]).optional().describe("Inscription mode: file or hashinal NFT"),
|
|
11
|
+
metadata: z.record(z.unknown()).optional().describe("Metadata to attach to the inscription"),
|
|
12
|
+
tags: z.array(z.string()).optional().describe("Tags to categorize the inscription"),
|
|
13
|
+
chunkSize: z.number().int().positive().optional().describe("Chunk size for large files"),
|
|
14
|
+
waitForConfirmation: z.boolean().optional().describe("Whether to wait for inscription confirmation"),
|
|
15
|
+
timeoutMs: z.number().int().positive().optional().describe("Timeout in milliseconds for inscription (default: no timeout)"),
|
|
16
|
+
apiKey: z.string().optional().describe("API key for inscription service"),
|
|
17
|
+
quoteOnly: z.boolean().optional().default(false).describe(
|
|
18
|
+
"If true, returns a cost quote instead of executing the inscription"
|
|
19
|
+
)
|
|
92
20
|
});
|
|
93
|
-
class
|
|
21
|
+
class InscribeFromFileTool extends BaseInscriberQueryTool {
|
|
94
22
|
constructor() {
|
|
95
23
|
super(...arguments);
|
|
96
|
-
this.name = "
|
|
97
|
-
this.description = "
|
|
98
|
-
}
|
|
99
|
-
// Declare entity resolution preferences to preserve user-specified literal fields
|
|
100
|
-
getEntityResolutionPreferences() {
|
|
101
|
-
return {
|
|
102
|
-
name: "literal",
|
|
103
|
-
description: "literal",
|
|
104
|
-
creator: "literal",
|
|
105
|
-
attributes: "literal",
|
|
106
|
-
properties: "literal"
|
|
107
|
-
};
|
|
24
|
+
this.name = "inscribeFromFile";
|
|
25
|
+
this.description = "Inscribe content from a local file to the Hedera network using a file path. IMPORTANT: Only use this tool when you have a valid file path to actual content. The file must exist and contain meaningful data (minimum 10 bytes). For files accessed through MCP filesystem tools, consider reading the file content first and using inscribeFromBuffer instead. Set quoteOnly=true to get cost estimates without executing the inscription.";
|
|
108
26
|
}
|
|
109
27
|
get specificInputSchema() {
|
|
110
|
-
|
|
111
|
-
return baseSchema;
|
|
28
|
+
return inscribeFromFileSchema;
|
|
112
29
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
const
|
|
117
|
-
if (!
|
|
118
|
-
|
|
119
|
-
fieldType: "object",
|
|
120
|
-
ui: {
|
|
121
|
-
label: "Inscribe Hashinal NFT",
|
|
122
|
-
description: "Create a Hashinal inscription for NFT minting"
|
|
123
|
-
}
|
|
124
|
-
};
|
|
30
|
+
async executeQuery(params, _runManager) {
|
|
31
|
+
let fileContent;
|
|
32
|
+
try {
|
|
33
|
+
const stats = await fs.stat(params.filePath);
|
|
34
|
+
if (!stats.isFile()) {
|
|
35
|
+
throw new Error(`Path "${params.filePath}" is not a file`);
|
|
125
36
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Implementation of FormValidatable interface
|
|
132
|
-
* Determines if a form should be generated for the given input
|
|
133
|
-
*/
|
|
134
|
-
shouldGenerateForm(input) {
|
|
135
|
-
const logger = new Logger({ module: "InscribeHashinalTool" });
|
|
136
|
-
const inputObj = input;
|
|
137
|
-
logger.info("InscribeHashinalTool: Checking if form should be generated", {
|
|
138
|
-
inputKeys: Object.keys(inputObj || {}),
|
|
139
|
-
hasContent: !!(inputObj.url || inputObj.contentRef || inputObj.base64Data),
|
|
140
|
-
renderFormProvided: "renderForm" in inputObj,
|
|
141
|
-
renderFormValue: inputObj.renderForm
|
|
142
|
-
});
|
|
143
|
-
const hasContentSource = !!(inputObj.url || inputObj.contentRef || inputObj.base64Data);
|
|
144
|
-
if (!hasContentSource) {
|
|
145
|
-
logger.info("InscribeHashinalTool: No content source provided");
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
if ("renderForm" in inputObj && inputObj.renderForm === false) {
|
|
149
|
-
logger.info(
|
|
150
|
-
"InscribeHashinalTool: renderForm=false, skipping form generation"
|
|
151
|
-
);
|
|
152
|
-
return false;
|
|
153
|
-
}
|
|
154
|
-
const isNonEmptyString = (v) => {
|
|
155
|
-
if (typeof v !== "string") {
|
|
156
|
-
return false;
|
|
37
|
+
if (stats.size === 0) {
|
|
38
|
+
throw new Error(
|
|
39
|
+
`File "${params.filePath}" is empty (0 bytes). Cannot inscribe empty files.`
|
|
40
|
+
);
|
|
157
41
|
}
|
|
158
|
-
if (
|
|
159
|
-
|
|
42
|
+
if (stats.size < 10) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`File "${params.filePath}" is too small (${stats.size} bytes). Files must contain at least 10 bytes of meaningful content.`
|
|
45
|
+
);
|
|
160
46
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
);
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
)
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
z.array(
|
|
193
|
-
z.object({
|
|
194
|
-
trait_type: z.string().describe('Trait name (e.g., "Rarity", "Color", "Style")'),
|
|
195
|
-
value: z.union([z.string(), z.number()]).describe('Trait value (e.g., "Epic", "Blue", 85)')
|
|
196
|
-
})
|
|
197
|
-
)
|
|
198
|
-
).withRender(renderConfigs.array("NFT Attributes", "Attribute")).optional().describe("Collectible traits and characteristics."),
|
|
199
|
-
type: z.string().optional().describe(
|
|
200
|
-
'Category or genre of the NFT (e.g., "Digital Art", "Photography", "Collectible Card)'
|
|
201
|
-
)
|
|
202
|
-
})
|
|
203
|
-
).withRender({
|
|
204
|
-
fieldType: "object",
|
|
205
|
-
ui: {
|
|
206
|
-
label: "Complete NFT Metadata",
|
|
207
|
-
description: "Provide meaningful metadata to create a valuable NFT"
|
|
47
|
+
if (stats.size > 100 * 1024 * 1024) {
|
|
48
|
+
this.logger?.warn(
|
|
49
|
+
`Large file detected (${(stats.size / (1024 * 1024)).toFixed(2)} MB)`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
this.logger?.info("Reading file content...");
|
|
53
|
+
fileContent = await fs.readFile(params.filePath);
|
|
54
|
+
this.logger?.info(`Read ${fileContent.length} bytes from file`);
|
|
55
|
+
if (!fileContent || fileContent.length === 0) {
|
|
56
|
+
throw new Error(
|
|
57
|
+
`File "${params.filePath}" has no content after reading. Cannot inscribe empty files.`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
if (fileContent.length < 10) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
`File "${params.filePath}" content is too small (${fileContent.length} bytes). Files must contain at least 10 bytes of meaningful content.`
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
const fileName2 = path.basename(params.filePath);
|
|
66
|
+
const mimeType2 = this.getMimeType(fileName2);
|
|
67
|
+
if (mimeType2.startsWith("text/") || mimeType2 === "application/json") {
|
|
68
|
+
const textContent = fileContent.toString(
|
|
69
|
+
"utf8",
|
|
70
|
+
0,
|
|
71
|
+
Math.min(fileContent.length, 1e3)
|
|
72
|
+
);
|
|
73
|
+
if (textContent.trim() === "") {
|
|
74
|
+
throw new Error(
|
|
75
|
+
`File "${params.filePath}" contains only whitespace or empty content. Cannot inscribe meaningless data.`
|
|
76
|
+
);
|
|
77
|
+
}
|
|
208
78
|
}
|
|
209
|
-
});
|
|
210
|
-
return focusedSchema;
|
|
211
|
-
}
|
|
212
|
-
async executeQuery(params, _runManager) {
|
|
213
|
-
if (!params.url && !params.contentRef && !params.base64Data) {
|
|
214
|
-
return createInscriptionError({
|
|
215
|
-
code: "MISSING_CONTENT",
|
|
216
|
-
details: "No content source provided",
|
|
217
|
-
suggestions: [
|
|
218
|
-
"Provide a URL to content you want to inscribe",
|
|
219
|
-
"Upload a file and use the content reference",
|
|
220
|
-
"Provide base64-encoded content data"
|
|
221
|
-
]
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
const operatorAccount = this.inscriberBuilder["hederaKit"]?.client?.operatorAccountId?.toString() || "0.0.unknown";
|
|
225
|
-
const rawMetadata = {
|
|
226
|
-
...generateDefaultMetadata({
|
|
227
|
-
name: params.name,
|
|
228
|
-
creator: params.creator,
|
|
229
|
-
description: params.description,
|
|
230
|
-
type: params.type,
|
|
231
|
-
fileName: params.fileName,
|
|
232
|
-
mimeType: params.mimeType,
|
|
233
|
-
operatorAccount
|
|
234
|
-
}),
|
|
235
|
-
attributes: Array.isArray(params.attributes) ? params.attributes : [],
|
|
236
|
-
properties: params.properties || {}
|
|
237
|
-
};
|
|
238
|
-
let validatedMetadata;
|
|
239
|
-
try {
|
|
240
|
-
validatedMetadata = validateHIP412Metadata(rawMetadata);
|
|
241
79
|
} catch (error) {
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
"Verify metadata follows HIP-412 standard"
|
|
250
|
-
]
|
|
251
|
-
});
|
|
80
|
+
if (error instanceof Error) {
|
|
81
|
+
if (error.message.includes("ENOENT")) {
|
|
82
|
+
throw new Error(`File not found: "${params.filePath}"`);
|
|
83
|
+
}
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
throw new Error(`Failed to read file: ${error}`);
|
|
252
87
|
}
|
|
88
|
+
const base64Data = fileContent.toString("base64");
|
|
89
|
+
this.logger?.info(`Converted to base64: ${base64Data.length} characters`);
|
|
90
|
+
const fileName = path.basename(params.filePath);
|
|
91
|
+
const mimeType = this.getMimeType(fileName);
|
|
92
|
+
this.logger?.info(`File: ${fileName}, MIME type: ${mimeType}`);
|
|
253
93
|
const options = {
|
|
254
|
-
mode:
|
|
255
|
-
metadata:
|
|
256
|
-
jsonFileURL: params.jsonFileURL,
|
|
257
|
-
fileStandard: params.fileStandard,
|
|
94
|
+
mode: params.mode,
|
|
95
|
+
metadata: params.metadata,
|
|
258
96
|
tags: params.tags,
|
|
259
97
|
chunkSize: params.chunkSize,
|
|
260
98
|
waitForConfirmation: params.quoteOnly ? false : params.waitForConfirmation ?? true,
|
|
261
|
-
waitMaxAttempts:
|
|
262
|
-
waitIntervalMs:
|
|
99
|
+
waitMaxAttempts: 10,
|
|
100
|
+
waitIntervalMs: 3e3,
|
|
101
|
+
apiKey: params.apiKey,
|
|
263
102
|
network: this.inscriberBuilder["hederaKit"].client.network.toString().includes("mainnet") ? "mainnet" : "testnet",
|
|
264
103
|
quoteOnly: params.quoteOnly
|
|
265
104
|
};
|
|
266
|
-
let inscriptionData;
|
|
267
|
-
if (params.url) {
|
|
268
|
-
inscriptionData = { type: "url", url: params.url };
|
|
269
|
-
} else if (params.contentRef || params.base64Data) {
|
|
270
|
-
const inputData = params.contentRef || params.base64Data || "";
|
|
271
|
-
const { buffer, mimeType, fileName } = await this.resolveContent(
|
|
272
|
-
inputData,
|
|
273
|
-
params.mimeType,
|
|
274
|
-
params.fileName
|
|
275
|
-
);
|
|
276
|
-
inscriptionData = {
|
|
277
|
-
type: "buffer",
|
|
278
|
-
buffer,
|
|
279
|
-
fileName: fileName || params.fileName || "hashinal-content",
|
|
280
|
-
mimeType: mimeType || params.mimeType
|
|
281
|
-
};
|
|
282
|
-
} else {
|
|
283
|
-
throw new Error("No valid input data provided for inscription");
|
|
284
|
-
}
|
|
285
105
|
if (params.quoteOnly) {
|
|
286
106
|
try {
|
|
287
107
|
const quote = await this.generateInscriptionQuote(
|
|
288
|
-
|
|
108
|
+
{
|
|
109
|
+
type: "buffer",
|
|
110
|
+
buffer: Buffer.from(base64Data, "base64"),
|
|
111
|
+
fileName,
|
|
112
|
+
mimeType
|
|
113
|
+
},
|
|
289
114
|
options
|
|
290
115
|
);
|
|
291
|
-
return
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
116
|
+
return {
|
|
117
|
+
success: true,
|
|
118
|
+
quote: {
|
|
119
|
+
totalCostHbar: quote.totalCostHbar,
|
|
120
|
+
validUntil: quote.validUntil,
|
|
121
|
+
breakdown: quote.breakdown
|
|
122
|
+
},
|
|
123
|
+
contentInfo: {
|
|
124
|
+
fileName,
|
|
125
|
+
mimeType,
|
|
126
|
+
sizeBytes: fileContent.length,
|
|
127
|
+
filePath: params.filePath
|
|
128
|
+
},
|
|
129
|
+
message: `Estimated Quote for file: ${fileName} (${(fileContent.length / 1024).toFixed(2)} KB)
|
|
130
|
+
Total cost: ${quote.totalCostHbar} HBAR`
|
|
131
|
+
};
|
|
301
132
|
} catch (error) {
|
|
302
133
|
const errorMessage = error instanceof Error ? error.message : "Failed to generate inscription quote";
|
|
303
|
-
|
|
304
|
-
code: "QUOTE_GENERATION_FAILED",
|
|
305
|
-
details: `Quote generation failed: ${errorMessage}`,
|
|
306
|
-
suggestions: [
|
|
307
|
-
"Check network connectivity",
|
|
308
|
-
"Verify content is accessible",
|
|
309
|
-
"Try again in a moment"
|
|
310
|
-
]
|
|
311
|
-
});
|
|
134
|
+
throw new Error(`Quote generation failed: ${errorMessage}`);
|
|
312
135
|
}
|
|
313
136
|
}
|
|
314
137
|
try {
|
|
@@ -323,296 +146,79 @@ class InscribeHashinalTool extends BaseInscriberQueryTool {
|
|
|
323
146
|
);
|
|
324
147
|
});
|
|
325
148
|
result = await Promise.race([
|
|
326
|
-
this.inscriberBuilder.inscribe(
|
|
149
|
+
this.inscriberBuilder.inscribe(
|
|
150
|
+
{
|
|
151
|
+
type: "buffer",
|
|
152
|
+
buffer: Buffer.from(base64Data, "base64"),
|
|
153
|
+
fileName,
|
|
154
|
+
mimeType
|
|
155
|
+
},
|
|
156
|
+
options
|
|
157
|
+
),
|
|
327
158
|
timeoutPromise
|
|
328
159
|
]);
|
|
329
160
|
} else {
|
|
330
|
-
result = await this.inscriberBuilder.inscribe(
|
|
161
|
+
result = await this.inscriberBuilder.inscribe(
|
|
162
|
+
{
|
|
163
|
+
type: "buffer",
|
|
164
|
+
buffer: Buffer.from(base64Data, "base64"),
|
|
165
|
+
fileName,
|
|
166
|
+
mimeType
|
|
167
|
+
},
|
|
168
|
+
options
|
|
169
|
+
);
|
|
331
170
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
const
|
|
171
|
+
const inscriptionResult = result;
|
|
172
|
+
if (inscriptionResult.confirmed && !inscriptionResult.quote) {
|
|
173
|
+
const ids = extractTopicIds(inscriptionResult.inscription, inscriptionResult.result);
|
|
335
174
|
const network = options.network || "testnet";
|
|
336
|
-
const cdnUrl =
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
const inscriptionResponse = createInscriptionSuccess({
|
|
351
|
-
hrl,
|
|
352
|
-
topicId: jsonTopicId || imageTopicId || "unknown",
|
|
353
|
-
standard: standardType,
|
|
354
|
-
cdnUrl: cdnUrl || void 0,
|
|
355
|
-
transactionId: result.result?.transactionId,
|
|
356
|
-
metadata: {
|
|
357
|
-
name: params.name,
|
|
358
|
-
creator: params.creator,
|
|
359
|
-
description: params.description,
|
|
360
|
-
type: params.type,
|
|
361
|
-
attributes: params.attributes
|
|
362
|
-
}
|
|
363
|
-
});
|
|
364
|
-
this.onEntityCreated?.({
|
|
365
|
-
entityId: jsonTopicId || imageTopicId || "unknown",
|
|
366
|
-
entityName: params.name || "Unnamed Inscription",
|
|
367
|
-
entityType: "topicId",
|
|
368
|
-
transactionId: result.result?.transactionId
|
|
369
|
-
});
|
|
370
|
-
if (params.withHashLinkBlocks) {
|
|
371
|
-
try {
|
|
372
|
-
const blockData = await this.createHashLinkBlock(
|
|
373
|
-
inscriptionResponse,
|
|
374
|
-
inscriptionData.type === "buffer" ? inscriptionData.mimeType : void 0
|
|
375
|
-
);
|
|
376
|
-
inscriptionResponse.hashLinkBlock = blockData;
|
|
377
|
-
} catch (blockError) {
|
|
378
|
-
const logger = new Logger({ module: "InscribeHashinalTool" });
|
|
379
|
-
logger.error("Failed to create HashLink block", {
|
|
380
|
-
error: blockError
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
return inscriptionResponse;
|
|
385
|
-
} else if (!result.quote && !result.confirmed) {
|
|
386
|
-
const imageTopicId = result.inscription?.topic_id;
|
|
387
|
-
const jsonTopicId = result.inscription?.jsonTopicId;
|
|
388
|
-
if (jsonTopicId || imageTopicId) {
|
|
389
|
-
const network = options.network || "testnet";
|
|
390
|
-
const cdnUrl = jsonTopicId ? `https://kiloscribe.com/api/inscription-cdn/${jsonTopicId}?network=${network}` : null;
|
|
391
|
-
const fileStandard = params.fileStandard || "1";
|
|
392
|
-
const hrl = jsonTopicId ? `hcs://${fileStandard}/${jsonTopicId}` : null;
|
|
393
|
-
const standardType = fileStandard === "6" ? "Dynamic" : "Static";
|
|
394
|
-
if (hrl) {
|
|
395
|
-
const inscriptionResponse = createInscriptionSuccess({
|
|
396
|
-
hrl,
|
|
397
|
-
topicId: jsonTopicId || imageTopicId || "unknown",
|
|
398
|
-
standard: standardType,
|
|
399
|
-
cdnUrl: cdnUrl || void 0,
|
|
400
|
-
transactionId: result.result?.transactionId,
|
|
401
|
-
metadata: {
|
|
402
|
-
name: params.name,
|
|
403
|
-
creator: params.creator,
|
|
404
|
-
description: params.description,
|
|
405
|
-
type: params.type,
|
|
406
|
-
attributes: params.attributes
|
|
407
|
-
}
|
|
408
|
-
});
|
|
409
|
-
this.onEntityCreated?.({
|
|
410
|
-
entityId: jsonTopicId || imageTopicId || "unknown",
|
|
411
|
-
entityName: params.name || "Unnamed Inscription",
|
|
412
|
-
entityType: "topicId",
|
|
413
|
-
transactionId: result.result?.transactionId
|
|
414
|
-
});
|
|
415
|
-
if (params.withHashLinkBlocks) {
|
|
416
|
-
try {
|
|
417
|
-
const blockData = await this.createHashLinkBlock(
|
|
418
|
-
inscriptionResponse,
|
|
419
|
-
inscriptionData.type === "buffer" ? inscriptionData.mimeType : void 0
|
|
420
|
-
);
|
|
421
|
-
inscriptionResponse.hashLinkBlock = blockData;
|
|
422
|
-
} catch (blockError) {
|
|
423
|
-
const logger = new Logger({ module: "InscribeHashinalTool" });
|
|
424
|
-
logger.error("Failed to create HashLink block", {
|
|
425
|
-
error: blockError
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
return inscriptionResponse;
|
|
430
|
-
}
|
|
431
|
-
}
|
|
432
|
-
const transactionId = result.result?.transactionId || "unknown";
|
|
433
|
-
return createInscriptionError({
|
|
434
|
-
code: "INSCRIPTION_PENDING",
|
|
435
|
-
details: `Inscription submitted but not yet confirmed. Transaction ID: ${transactionId}`,
|
|
436
|
-
suggestions: [
|
|
437
|
-
"Wait a few moments for confirmation",
|
|
438
|
-
"Check the transaction status on a Hedera explorer",
|
|
439
|
-
"Try the inscription again if it doesn't confirm within 5 minutes"
|
|
440
|
-
]
|
|
441
|
-
});
|
|
175
|
+
const { topicId, cdnUrl } = buildInscriptionLinks(ids, network, "1");
|
|
176
|
+
return `Successfully inscribed and confirmed content on the Hedera network!
|
|
177
|
+
|
|
178
|
+
Transaction ID: ${inscriptionResult.result?.transactionId ?? "unknown"}
|
|
179
|
+
Topic ID: ${topicId || "N/A"}${cdnUrl ? `
|
|
180
|
+
View inscription: ${cdnUrl}` : ""}
|
|
181
|
+
|
|
182
|
+
The inscription is now available.`;
|
|
183
|
+
} else if (!inscriptionResult.quote && !inscriptionResult.confirmed) {
|
|
184
|
+
return `Successfully submitted inscription to the Hedera network!
|
|
185
|
+
|
|
186
|
+
Transaction ID: ${inscriptionResult.result?.transactionId ?? "unknown"}
|
|
187
|
+
|
|
188
|
+
The inscription is processing and will be confirmed shortly.`;
|
|
442
189
|
} else {
|
|
443
|
-
return
|
|
444
|
-
code: "UNKNOWN_STATE",
|
|
445
|
-
details: "Inscription completed but result state is unclear",
|
|
446
|
-
suggestions: [
|
|
447
|
-
"Check if the inscription was successful manually",
|
|
448
|
-
"Try the inscription again"
|
|
449
|
-
]
|
|
450
|
-
});
|
|
190
|
+
return "Inscription operation completed.";
|
|
451
191
|
}
|
|
452
192
|
} catch (error) {
|
|
453
|
-
const errorMessage = error instanceof Error ? error.message : "Failed to inscribe
|
|
454
|
-
|
|
455
|
-
code: "INSCRIPTION_FAILED",
|
|
456
|
-
details: `Inscription failed: ${errorMessage}`,
|
|
457
|
-
suggestions: [
|
|
458
|
-
"Check network connectivity",
|
|
459
|
-
"Verify you have sufficient HBAR balance",
|
|
460
|
-
"Ensure content is accessible and valid",
|
|
461
|
-
"Try again in a moment"
|
|
462
|
-
]
|
|
463
|
-
});
|
|
193
|
+
const errorMessage = error instanceof Error ? error.message : "Failed to inscribe from file";
|
|
194
|
+
throw new Error(`Inscription failed: ${errorMessage}`);
|
|
464
195
|
}
|
|
465
196
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
* const tool = new InscribeHashinalTool(mainnetClient);
|
|
487
|
-
* const block = await tool.createHashLinkBlock(inscriptionResponse);
|
|
488
|
-
* console.log(block.blockId); // Network-specific mainnet block ID
|
|
489
|
-
*
|
|
490
|
-
* // HashLink Block Response Structure:
|
|
491
|
-
* {
|
|
492
|
-
* blockId: string; // Hedera account ID format (e.g., '0.0.6617393')
|
|
493
|
-
* hashLink: string; // HCS-12 URL format: 'hcs://12/{blockId}'
|
|
494
|
-
* template: string; // Block template reference matching blockId
|
|
495
|
-
* attributes: { // Metadata for client-side processing
|
|
496
|
-
* name: string; // Content display name
|
|
497
|
-
* creator: string; // Creator account ID
|
|
498
|
-
* topicId: string; // HCS topic containing the inscription
|
|
499
|
-
* hrl: string; // Hedera Resource Locator
|
|
500
|
-
* network: string; // Network type: 'testnet' | 'mainnet'
|
|
501
|
-
* }
|
|
502
|
-
* }
|
|
503
|
-
*
|
|
504
|
-
* // Render function usage in HashLink blocks:
|
|
505
|
-
* // The block's JavaScript render function receives this structure
|
|
506
|
-
* // and can access network-specific resources through attributes.network
|
|
507
|
-
* ```
|
|
508
|
-
*/
|
|
509
|
-
async createHashLinkBlock(response, _mimeType) {
|
|
510
|
-
const clientNetwork = this.inscriberBuilder["hederaKit"].client.network.toString().includes("mainnet") ? "mainnet" : "testnet";
|
|
511
|
-
const cdnNetwork = response.inscription.cdnUrl?.includes("mainnet") ? "mainnet" : "testnet";
|
|
512
|
-
if (clientNetwork !== cdnNetwork) {
|
|
513
|
-
const logger = new Logger({ module: "InscribeHashinalTool" });
|
|
514
|
-
logger.warn(
|
|
515
|
-
`Network mismatch detected: client=${clientNetwork}, cdn=${cdnNetwork}. Using client network.`
|
|
516
|
-
);
|
|
517
|
-
}
|
|
518
|
-
const network = clientNetwork;
|
|
519
|
-
const config = getHashLinkBlockId(network);
|
|
520
|
-
return {
|
|
521
|
-
blockId: config.blockId,
|
|
522
|
-
hashLink: config.hashLink,
|
|
523
|
-
template: config.template,
|
|
524
|
-
attributes: {
|
|
525
|
-
name: response.metadata.name || "Untitled Content",
|
|
526
|
-
creator: response.metadata.creator || "",
|
|
527
|
-
topicId: response.inscription.topicId,
|
|
528
|
-
hrl: response.inscription.hrl,
|
|
529
|
-
network
|
|
530
|
-
}
|
|
197
|
+
getMimeType(fileName) {
|
|
198
|
+
const ext = path.extname(fileName).toLowerCase();
|
|
199
|
+
const mimeTypes = {
|
|
200
|
+
".png": "image/png",
|
|
201
|
+
".jpg": "image/jpeg",
|
|
202
|
+
".jpeg": "image/jpeg",
|
|
203
|
+
".gif": "image/gif",
|
|
204
|
+
".webp": "image/webp",
|
|
205
|
+
".svg": "image/svg+xml",
|
|
206
|
+
".pdf": "application/pdf",
|
|
207
|
+
".json": "application/json",
|
|
208
|
+
".txt": "text/plain",
|
|
209
|
+
".html": "text/html",
|
|
210
|
+
".css": "text/css",
|
|
211
|
+
".js": "application/javascript",
|
|
212
|
+
".ts": "application/typescript",
|
|
213
|
+
".mp4": "video/mp4",
|
|
214
|
+
".mp3": "audio/mpeg",
|
|
215
|
+
".wav": "audio/wav",
|
|
216
|
+
".zip": "application/zip"
|
|
531
217
|
};
|
|
532
|
-
|
|
533
|
-
async resolveContent(input, providedMimeType, providedFileName) {
|
|
534
|
-
const trimmedInput = input.trim();
|
|
535
|
-
const resolver = this.getContentResolver() || ContentResolverRegistry.getResolver();
|
|
536
|
-
if (!resolver) {
|
|
537
|
-
return this.handleDirectContent(
|
|
538
|
-
trimmedInput,
|
|
539
|
-
providedMimeType,
|
|
540
|
-
providedFileName
|
|
541
|
-
);
|
|
542
|
-
}
|
|
543
|
-
const referenceId = resolver.extractReferenceId(trimmedInput);
|
|
544
|
-
if (referenceId) {
|
|
545
|
-
try {
|
|
546
|
-
const resolution = await resolver.resolveReference(referenceId);
|
|
547
|
-
return {
|
|
548
|
-
buffer: resolution.content,
|
|
549
|
-
mimeType: resolution.metadata?.mimeType || providedMimeType,
|
|
550
|
-
fileName: resolution.metadata?.fileName || providedFileName,
|
|
551
|
-
wasReference: true
|
|
552
|
-
};
|
|
553
|
-
} catch (error) {
|
|
554
|
-
const errorMsg = error instanceof Error ? error.message : "Unknown error resolving reference";
|
|
555
|
-
throw new Error(`Reference resolution failed: ${errorMsg}`);
|
|
556
|
-
}
|
|
557
|
-
}
|
|
558
|
-
return this.handleDirectContent(
|
|
559
|
-
trimmedInput,
|
|
560
|
-
providedMimeType,
|
|
561
|
-
providedFileName
|
|
562
|
-
);
|
|
563
|
-
}
|
|
564
|
-
handleDirectContent(input, providedMimeType, providedFileName) {
|
|
565
|
-
const isValidBase64 = /^[A-Za-z0-9+/]*={0,2}$/.test(input);
|
|
566
|
-
if (isValidBase64) {
|
|
567
|
-
try {
|
|
568
|
-
const buffer2 = Buffer.from(input, "base64");
|
|
569
|
-
return {
|
|
570
|
-
buffer: buffer2,
|
|
571
|
-
mimeType: providedMimeType,
|
|
572
|
-
fileName: providedFileName,
|
|
573
|
-
wasReference: false
|
|
574
|
-
};
|
|
575
|
-
} catch (error) {
|
|
576
|
-
throw new Error(
|
|
577
|
-
"Failed to decode base64 data. Please ensure the data is properly encoded."
|
|
578
|
-
);
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
const buffer = Buffer.from(input, "utf8");
|
|
582
|
-
return {
|
|
583
|
-
buffer,
|
|
584
|
-
mimeType: providedMimeType || "text/plain",
|
|
585
|
-
fileName: providedFileName,
|
|
586
|
-
wasReference: false
|
|
587
|
-
};
|
|
588
|
-
}
|
|
589
|
-
/**
|
|
590
|
-
* Implementation of FormValidatable interface
|
|
591
|
-
* Returns essential fields that should always be shown in forms
|
|
592
|
-
*/
|
|
593
|
-
getEssentialFields() {
|
|
594
|
-
return ["name", "description", "creator", "attributes"];
|
|
595
|
-
}
|
|
596
|
-
/**
|
|
597
|
-
* Implementation of FormValidatable interface
|
|
598
|
-
* Determines if a field value should be considered empty for this tool
|
|
599
|
-
*/
|
|
600
|
-
isFieldEmpty(fieldName, value) {
|
|
601
|
-
if (value === void 0 || value === null || value === "") {
|
|
602
|
-
return true;
|
|
603
|
-
}
|
|
604
|
-
if (Array.isArray(value) && value.length === 0) {
|
|
605
|
-
return true;
|
|
606
|
-
}
|
|
607
|
-
if (fieldName === "attributes" && Array.isArray(value)) {
|
|
608
|
-
return value.every(
|
|
609
|
-
(attr) => !attr || typeof attr === "object" && (!attr.trait_type || !attr.value)
|
|
610
|
-
);
|
|
611
|
-
}
|
|
612
|
-
return false;
|
|
218
|
+
return mimeTypes[ext] || "application/octet-stream";
|
|
613
219
|
}
|
|
614
220
|
}
|
|
615
221
|
export {
|
|
616
|
-
|
|
222
|
+
InscribeFromFileTool
|
|
617
223
|
};
|
|
618
224
|
//# sourceMappingURL=standards-agent-kit.es37.js.map
|