@hashgraphonline/standards-agent-kit
Version:
A modular SDK for building on-chain autonomous agents using Hashgraph Online Standards, including HCS-10 for agent discovery and communication. https://hol.org
318 lines (317 loc) • 10.7 kB
JavaScript
import { BaseServiceBuilder } from "hedera-agent-kit";
import { getOrCreateSDK, inscribe, inscribeWithSigner, getTopicId, retrieveInscription } from "@hashgraphonline/standards-sdk";
const toDashedTransactionId = (transactionId) => {
if (transactionId.includes("-")) {
return transactionId;
}
const [account, timePart] = transactionId.split("@");
if (!account || !timePart) {
return transactionId;
}
const [secondsPart, nanosPart] = timePart.split(".");
if (!secondsPart) {
return transactionId;
}
const normalizedNanos = (nanosPart ?? "0").padEnd(9, "0").slice(0, 9);
return `${account}-${secondsPart}-${normalizedNanos}`;
};
const _InscriberBuilder = class _InscriberBuilder extends BaseServiceBuilder {
constructor(hederaKit) {
super(hederaKit);
}
getOperationalMode() {
return this.hederaKit.operationalMode;
}
static setSignerProvider(provider) {
_InscriberBuilder.signerProvider = provider;
}
static setWalletInfoResolver(resolver) {
_InscriberBuilder.walletInfoResolver = resolver;
}
static setStartInscriptionDelegate(delegate) {
_InscriberBuilder.startInscriptionDelegate = delegate;
}
static setWalletExecutor(executor) {
_InscriberBuilder.walletExecutor = executor;
}
/**
* Control fallback behavior. When true, wallet must be available for execution paths.
*/
static setPreferWalletOnly(flag) {
_InscriberBuilder.preferWalletOnly = !!flag;
}
async getSigner() {
const provider = _InscriberBuilder.signerProvider;
if (!provider) return null;
try {
const maybe = provider();
return maybe && typeof maybe.then === "function" ? await maybe : maybe;
} catch {
return null;
}
}
/**
* Get or create Inscription SDK
*/
async getInscriptionSDK(options) {
if (this.inscriptionSDK) {
return this.inscriptionSDK;
}
const network = this.hederaKit.client.network;
const networkType = network.toString().includes("mainnet") ? "mainnet" : "testnet";
const accountId = this.hederaKit.signer.getAccountId().toString();
const operatorKey = this.hederaKit.signer?.getOperatorPrivateKey();
const baseOptions = {
...options,
network: options.network ?? networkType
};
const apiKey = baseOptions.apiKey ?? (operatorKey ? void 0 : "public-access");
const effectiveOptions = apiKey ? { ...baseOptions, apiKey } : baseOptions;
const clientConfig = {
accountId,
privateKey: operatorKey?.toStringRaw() ?? apiKey ?? "public-access",
network: networkType
};
try {
this.inscriptionSDK = await getOrCreateSDK(
clientConfig,
effectiveOptions,
this.inscriptionSDK
);
return this.inscriptionSDK;
} catch (error) {
this.logger.error("failed to setup sdk", {
error: error instanceof Error ? error.message : String(error)
});
this.inscriptionSDK = void 0;
return null;
}
}
/**
* Inscribe content using server-side authentication
*/
async inscribe(input, options) {
const operatorId = this.hederaKit.signer.getAccountId().toString();
const operatorPrivateKey = this.hederaKit.signer?.getOperatorPrivateKey() ? this.hederaKit.signer.getOperatorPrivateKey().toStringRaw() : "";
const network = this.hederaKit.client.network;
const networkType = network.toString().includes("mainnet") ? "mainnet" : "testnet";
const clientConfig = {
accountId: operatorId,
privateKey: operatorPrivateKey,
network: networkType
};
return await inscribe(input, clientConfig, options);
}
/**
* Inscribe content using a DApp signer
*/
async inscribeWithSigner(input, signer, options) {
return await inscribeWithSigner(
input,
signer,
options
);
}
async inscribeAuto(input, options) {
const signer = await this.getSigner();
if (signer) {
return this.inscribeWithSigner(input, signer, options);
}
const infoMaybe = _InscriberBuilder.walletInfoResolver ? await _InscriberBuilder.walletInfoResolver() : null;
if (_InscriberBuilder.preferWalletOnly && !infoMaybe) {
const err = new Error(
"Wallet unavailable: connect a wallet or switch to autonomous mode"
);
err.code = "wallet_unavailable";
throw err;
}
if (infoMaybe && _InscriberBuilder.startInscriptionDelegate && _InscriberBuilder.walletExecutor) {
const holderId = infoMaybe.accountId;
const network = infoMaybe.network;
const ext = options;
const baseRequest = {
holderId,
metadata: ext.metadata || {},
tags: options.tags || [],
mode: options.mode || "file"
};
if (typeof ext.fileStandard !== "undefined") {
baseRequest.fileStandard = ext.fileStandard;
}
if (typeof ext.chunkSize !== "undefined") {
baseRequest.chunkSize = ext.chunkSize;
}
let request = { ...baseRequest };
switch (input.type) {
case "url":
request = { ...baseRequest, file: { type: "url", url: input.url } };
break;
case "file":
request = {
...baseRequest,
file: { type: "path", path: input.path }
};
break;
case "buffer":
request = {
...baseRequest,
file: {
type: "base64",
base64: Buffer.from(input.buffer).toString("base64"),
fileName: input.fileName,
mimeType: input.mimeType
}
};
break;
}
if (options.mode === "hashinal") {
request.metadataObject = ext.metadata;
request.creator = ext.metadata?.creator || holderId;
request.description = ext.metadata?.description;
if (typeof ext.jsonFileURL === "string" && ext.jsonFileURL.length > 0) {
request.jsonFileURL = ext.jsonFileURL;
}
}
const start = await _InscriberBuilder.startInscriptionDelegate(
request,
network
);
this.logger.info("inscribeAuto start response", {
hasTransactionBytes: typeof start.transactionBytes === "string",
txId: start.tx_id,
status: start.status
});
const completedStart = start;
const isCompletedResponse = Boolean(completedStart?.inscription) && completedStart?.confirmed;
if (isCompletedResponse) {
const completed = start;
this.logger.info(
"inscription already completed, short circuiting",
start
);
return {
quote: false,
confirmed: completed.confirmed === true,
result: completed.result,
inscription: completed.inscription
};
}
const startResponse = start;
if (!startResponse || !startResponse.transactionBytes) {
throw new Error("Failed to start inscription (no transaction bytes)");
}
const exec = await _InscriberBuilder.walletExecutor(
startResponse.transactionBytes,
network
);
const transactionId = exec?.transactionId || "";
const rawTransactionId = startResponse.tx_id || transactionId;
const canonicalTransactionId = toDashedTransactionId(rawTransactionId);
this.logger.info("inscribeAuto wallet execution", {
transactionId,
network
});
const shouldWait = options.quoteOnly ? false : options.waitForConfirmation ?? true;
if (shouldWait) {
const maxAttempts = options.waitMaxAttempts ?? 60;
const intervalMs = options.waitIntervalMs ?? 5e3;
const pollId = canonicalTransactionId;
this.logger.debug("Will be retrieving inscription", pollId);
let retrieved = null;
const sdk = await this.getInscriptionSDK(options);
if (sdk) {
try {
retrieved = await sdk.waitForInscription(
pollId,
maxAttempts,
intervalMs,
true,
(progress) => {
this.logger.debug("checking inscription", progress);
}
);
} catch (error) {
this.logger.warn("Primary inscription wait failed", {
pollId,
error: error instanceof Error ? error.message : String(error)
});
}
} else {
this.logger.warn(
"No inscription SDK available, using public client",
{
pollId
}
);
}
if (retrieved) {
const topicIdFromInscription = getTopicId(
retrieved
);
const topicId = topicIdFromInscription ?? startResponse.topic_id;
const resultConfirmed = {
quote: false,
confirmed: true,
result: {
jobId: toDashedTransactionId(startResponse.tx_id || ""),
transactionId: canonicalTransactionId,
topicId
},
inscription: retrieved
};
this.logger.debug(
"retrieved inscription confirmed",
resultConfirmed,
retrieved
);
return resultConfirmed;
}
}
const partial = {
quote: false,
confirmed: false,
result: {
jobId: toDashedTransactionId(startResponse.tx_id || ""),
transactionId: canonicalTransactionId,
status: startResponse.status,
completed: startResponse.completed
},
inscription: startResponse.topic_id ? { topic_id: startResponse.topic_id } : void 0
};
return partial;
}
if (_InscriberBuilder.preferWalletOnly) {
const err = new Error(
"Wallet unavailable: connect a wallet or switch to autonomous mode"
);
err.code = "wallet_unavailable";
throw err;
}
return this.inscribe(input, options);
}
/**
* Retrieve an existing inscription
*/
async retrieveInscription(transactionId, options) {
const operatorId = this.hederaKit.signer.getAccountId().toString();
const operatorPrivateKey = this.hederaKit.signer?.getOperatorPrivateKey() ? this.hederaKit.signer.getOperatorPrivateKey().toStringRaw() : "";
return await retrieveInscription(transactionId, {
...options,
accountId: operatorId,
privateKey: operatorPrivateKey
});
}
/**
* Close the inscription SDK
*/
async close() {
this.inscriptionSDK = void 0;
}
};
_InscriberBuilder.preferWalletOnly = false;
let InscriberBuilder = _InscriberBuilder;
export {
InscriberBuilder,
toDashedTransactionId
};
//# sourceMappingURL=standards-agent-kit.es8.js.map