UNPKG

@cheqd/sdk

Version:

A TypeScript SDK built with CosmJS to interact with the cheqd network ledger

297 lines 13.2 kB
import { AbstractCheqdSDKModule } from './_.js'; import { CheqdSigningStargateClient } from '../signer.js'; import { ISignInputs } from '../types.js'; import { MsgCreateResource, MsgCreateResourcePayload, MsgCreateResourceResponse, QueryClientImpl, protobufPackage, } from '@cheqd/ts-proto/cheqd/resource/v2/index.js'; import { createPagination, createProtobufRpcClient } from '@cosmjs/stargate'; import { fileTypeFromBuffer } from 'file-type'; import { toString } from 'uint8arrays/to-string'; import { assert } from '@cosmjs/utils'; import { isJSON } from '../utils.js'; /** Default extension key for resource-related query operations */ export const defaultResourceExtensionKey = 'resource'; /** * Protobuf message type literals for resource operations. * Used for consistent message type identification across the module. */ export const protobufLiterals = { /** Create resource message type */ MsgCreateResource: 'MsgCreateResource', /** Create resource response message type */ MsgCreateResourceResponse: 'MsgCreateResourceResponse', }; /** Type URL for MsgCreateResource messages */ export const typeUrlMsgCreateResource = `/${protobufPackage}.${protobufLiterals.MsgCreateResource}`; /** Type URL for MsgCreateResourceResponse messages */ export const typeUrlMsgCreateResourceResponse = `/${protobufPackage}.${protobufLiterals.MsgCreateResourceResponse}`; /** * Type guard function to check if an object is a MsgCreateResourceEncodeObject. * * @param obj - EncodeObject to check * @returns True if the object is a MsgCreateResourceEncodeObject */ export function isMsgCreateResourceEncodeObject(obj) { return obj.typeUrl === typeUrlMsgCreateResource; } /** * Sets up the resource extension for the querier client. * Creates and configures the resource-specific query methods. * * @param base - Base QueryClient to extend * @returns Configured resource extension with query methods */ export const setupResourceExtension = (base) => { const rpc = createProtobufRpcClient(base); const queryService = new QueryClientImpl(rpc); return { [defaultResourceExtensionKey]: { resource: async (collectionId, resourceId) => { const { resource } = await queryService.Resource({ collectionId, id: resourceId }); assert(resource); return resource; }, resourceMetadata: async (collectionId, resourceId) => { const { resource } = await queryService.ResourceMetadata({ collectionId, id: resourceId }); assert(resource); return resource; }, collectionResources: async (collectionId, paginationKey) => { const response = await queryService.CollectionResources({ collectionId, pagination: createPagination(paginationKey), }); return response; }, }, }; }; /** * Resource Module class providing comprehensive linked resource functionality. * Handles creation, querying, and metadata management of resources linked to DID documents. */ export class ResourceModule extends AbstractCheqdSDKModule { // @ts-expect-error underlying type `GeneratedType` is intentionally wider static registryTypes = [ [typeUrlMsgCreateResource, MsgCreateResource], [typeUrlMsgCreateResourceResponse, MsgCreateResourceResponse], ]; /** Base denomination for Cheqd network transactions */ static baseMinimalDenom = 'ncheq'; /** * Standard fee amounts for different resource types. * Fees vary based on resource content type and processing requirements. */ static fees = { /** Default fee for creating image resources */ DefaultCreateResourceImageFee: { amount: '10000000000', denom: ResourceModule.baseMinimalDenom }, /** Default fee for creating JSON resources */ DefaultCreateResourceJsonFee: { amount: '10000000000', denom: ResourceModule.baseMinimalDenom }, /** Default fee for creating other types of resources */ DefaultCreateResourceDefaultFee: { amount: '10000000000', denom: ResourceModule.baseMinimalDenom }, }; /** Querier extension setup function for resource operations */ static querierExtensionSetup = setupResourceExtension; /** Querier instance with resource extension capabilities */ querier; /** * Constructs a new resource module instance. * * @param signer - Signing client for blockchain transactions * @param querier - Querier client with resource extension for data retrieval */ constructor(signer, querier) { super(signer, querier); this.querier = querier; this.methods = { createLinkedResourceTx: this.createLinkedResourceTx.bind(this), queryLinkedResource: this.queryLinkedResource.bind(this), queryLinkedResourceMetadata: this.queryLinkedResourceMetadata.bind(this), queryLinkedResources: this.queryLinkedResources.bind(this), }; } /** * Gets the registry types for resource message encoding/decoding. * * @returns Iterable of [typeUrl, GeneratedType] pairs for the registry */ getRegistryTypes() { return ResourceModule.registryTypes; } /** * Gets the querier extension setup for resource operations. * * @returns Query extension setup function for resource functionality */ getQuerierExtensionSetup() { return ResourceModule.querierExtensionSetup; } /** * Signs a resource payload with provided signature inputs. * Creates a complete signed resource message ready for blockchain submission. * * @param payload - Resource payload to sign * @param signInputs - Signing inputs or pre-computed signatures * @returns Promise resolving to the signed resource message */ static async signPayload(payload, signInputs) { const signBytes = MsgCreateResourcePayload.encode(payload).finish(); let signatures; if (ISignInputs.isSignInput(signInputs)) { signatures = await CheqdSigningStargateClient.signIdentityTx(signBytes, signInputs); } else { signatures = signInputs; } return { payload, signatures, }; } /** * Creates a linked resource transaction on the blockchain. * Handles automatic fee calculation based on resource content type and size. * * @param signInputs - Signing inputs or pre-computed signatures for the transaction * @param resourcePayload - Resource payload containing data and metadata * @param address - Address of the account submitting the transaction * @param fee - Transaction fee configuration or 'auto' for automatic calculation * @param memo - Optional transaction memo * @param context - Optional SDK context for accessing clients * @returns Promise resolving to the transaction response * @throws Error if linked resource data is empty when automatic fee calculation is requested */ async createLinkedResourceTx(signInputs, resourcePayload, address, fee, memo, context) { if (!this._signer) { this._signer = context.sdk.signer; } const payload = MsgCreateResourcePayload.fromPartial(resourcePayload); const msg = await ResourceModule.signPayload(payload, signInputs); const encObj = { typeUrl: typeUrlMsgCreateResource, value: msg, }; if (address === '') { address = (await context.sdk.options.wallet.getAccounts())[0].address; } if (!fee) { if (payload.data.length === 0) { throw new Error('Linked resource data is empty'); } fee = await (async function () { const mimeType = await ResourceModule.readMimeType(payload.data); if (mimeType.startsWith('image/')) { return await ResourceModule.generateCreateResourceImageFees(address); } if (mimeType.startsWith('application/json')) { return await ResourceModule.generateCreateResourceJsonFees(address); } return await ResourceModule.generateCreateResourceDefaultFees(address); })(); } return this._signer.signAndBroadcast(address, [encObj], fee, memo); } /** * Queries a specific linked resource by collection and resource ID. * Retrieves the complete resource data along with its metadata. * * @param collectionId - ID of the collection containing the resource * @param resourceId - ID of the resource to query * @param context - Optional SDK context for accessing clients * @returns Promise resolving to the resource with metadata */ async queryLinkedResource(collectionId, resourceId, context) { if (!this.querier) { this.querier = context.sdk.querier; } return await this.querier[defaultResourceExtensionKey].resource(collectionId, resourceId); } /** * Queries metadata for a specific linked resource. * Retrieves only the metadata without the resource content data. * * @param collectionId - ID of the collection containing the resource * @param resourceId - ID of the resource to query metadata for * @param context - Optional SDK context for accessing clients * @returns Promise resolving to the resource metadata */ async queryLinkedResourceMetadata(collectionId, resourceId, context) { if (!this.querier) { this.querier = context.sdk.querier; } return await this.querier[defaultResourceExtensionKey].resourceMetadata(collectionId, resourceId); } /** * Queries all resources in a collection with pagination support. * Retrieves a list of all resources belonging to a specific collection. * * @param collectionId - ID of the collection to query resources for * @param context - Optional SDK context for accessing clients * @returns Promise resolving to the collection resources response with pagination */ async queryLinkedResources(collectionId, context) { if (!this.querier) { this.querier = context.sdk.querier; } return await this.querier[defaultResourceExtensionKey].collectionResources(collectionId); } /** * Reads and determines the MIME type of resource content. * Analyzes the content to identify the appropriate MIME type for fee calculation and validation. * * @param content - Resource content as byte array * @returns Promise resolving to the detected MIME type string */ static async readMimeType(content) { if (isJSON(toString(content, 'utf-8'))) return 'application/json'; return (await fileTypeFromBuffer(content))?.mime ?? 'application/octet-stream'; } /** * Generates fee configuration for image resource creation transactions. * Uses higher gas limits appropriate for image processing and storage. * * @param feePayer - Address of the account that will pay the transaction fees * @param granter - Optional address of the account granting fee payment permissions * @returns Promise resolving to the fee configuration for image resources */ static async generateCreateResourceImageFees(feePayer, granter) { return { amount: [ResourceModule.fees.DefaultCreateResourceImageFee], gas: '2000000', payer: feePayer, granter: granter, }; } /** * Generates fee configuration for JSON resource creation transactions. * Uses gas limits optimized for JSON data processing and validation. * * @param feePayer - Address of the account that will pay the transaction fees * @param granter - Optional address of the account granting fee payment permissions * @returns Promise resolving to the fee configuration for JSON resources */ static async generateCreateResourceJsonFees(feePayer, granter) { return { amount: [ResourceModule.fees.DefaultCreateResourceJsonFee], gas: '2000000', payer: feePayer, granter: granter, }; } /** * Generates fee configuration for default resource creation transactions. * Uses standard gas limits for generic resource types and binary data. * * @param feePayer - Address of the account that will pay the transaction fees * @param granter - Optional address of the account granting fee payment permissions * @returns Promise resolving to the fee configuration for default resources */ static async generateCreateResourceDefaultFees(feePayer, granter) { return { amount: [ResourceModule.fees.DefaultCreateResourceDefaultFee], gas: '2000000', payer: feePayer, granter: granter, }; } } //# sourceMappingURL=resource.js.map