diff --git a/packages/asset/src/Asset.chain.ts b/packages/asset/src/Asset.chain.ts index 2af8c9fd..e043aa9e 100644 --- a/packages/asset/src/Asset.chain.ts +++ b/packages/asset/src/Asset.chain.ts @@ -10,39 +10,49 @@ import { ASSET_PREFIX, DidUri, SubmittableExtrinsic, -} from '@cord.network/types' - -import type { Option } from '@cord.network/types' -import type { PalletAssetAssetEntry, PalletAssetAssetStatusOf } from '@cord.network/augment-api' - -import * as Did from '@cord.network/did' -import { uriToIdentifier } from '@cord.network/identifier' -import { Chain } from '@cord.network/network' -import { ConfigService } from '@cord.network/config' -import { SDKErrors } from '@cord.network/utils' - -/* TODO: Write method description, params, return types to all methods */ - +} from '@cord.network/types'; + +import type { Option } from '@cord.network/types'; +import type { PalletAssetAssetEntry, PalletAssetAssetStatusOf } from '@cord.network/augment-api'; + +import * as Did from '@cord.network/did'; +import { uriToIdentifier } from '@cord.network/identifier'; +import { Chain } from '@cord.network/network'; +import { ConfigService } from '@cord.network/config'; +import { SDKErrors } from '@cord.network/utils'; + +/** + * Checks if an asset is stored on the chain. + * @param assetUri - URI of the asset. + * @returns A promise that resolves to a boolean indicating if the asset is stored. + */ export async function isAssetStored(assetUri: AssetUri): Promise { try { - const api = ConfigService.get('api') - - const identifier = uriToIdentifier(assetUri) + const api = ConfigService.get('api'); + const identifier = uriToIdentifier(assetUri); const encoded = (await api.query.asset.assets( identifier - )) as Option + )) as Option; - return encoded.isSome + return encoded.isSome; } catch (error) { const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordQueryError( `Error querying asset entry: ${errorMessage}` - ) + ); } } +/** + * Prepares an extrinsic for creating an asset entry. + * @param assetEntry - The asset entry to create. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to a SubmittableExtrinsic. + */ export async function prepareCreateExtrinsic( assetEntry: IAssetEntry, authorAccount: CordKeyringPair, @@ -76,6 +86,14 @@ export async function prepareCreateExtrinsic( } } +/** + * Dispatches the creation of an asset entry to the chain. + * @param assetEntry - The asset entry to create. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to the AssetUri. + */ export async function dispatchCreateToChain( assetEntry: IAssetEntry, authorAccount: CordKeyringPair, @@ -83,394 +101,249 @@ export async function dispatchCreateToChain( signCallback: SignExtrinsicCallback ): Promise { try { - const extrinsic = await prepareCreateExtrinsic( assetEntry, authorAccount, authorizationUri, signCallback - ) + ); - await Chain.signAndSubmitTx(extrinsic, authorAccount) + await Chain.signAndSubmitTx(extrinsic, authorAccount); - return assetEntry.uri + return assetEntry.uri; } catch (error) { const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( `Error dispatching to chain: "${errorMessage}".` - ) + ); } } -export async function dispatchCreateVcToChain( +/** + * Prepares an extrinsic for creating a Verifiable Credential (VC) asset entry. + * @param assetQty - Quantity of the asset. + * @param digest - Digest string for the asset. + * @param creator - DID URI of the creator. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to a SubmittableExtrinsic. + */ +export async function prepareCreateVcExtrinsic( assetQty: number, digest: string, creator: DidUri, authorAccount: CordKeyringPair, authorizationUri: AuthorizationUri, - assetEntryUri: AssetUri, signCallback: SignExtrinsicCallback -): Promise { +): Promise { try { - const api = ConfigService.get('api') - const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri) + const api = ConfigService.get('api'); + const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri); - const tx = api.tx.asset.vcCreate( - assetQty, - digest, - authorizationId - ) + const tx = api.tx.asset.vcCreate(assetQty, digest, authorizationId); const extrinsic = await Did.authorizeTx( creator, tx, signCallback, authorAccount.address - ) - - await Chain.signAndSubmitTx(extrinsic, authorAccount) + ); - return assetEntryUri + return extrinsic; } catch (error) { const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) - throw new SDKErrors.CordDispatchError( - `Error dispatching to chain: "${errorMessage}".` - ) - } -} - -export async function prepareExtrinsic( - assetEntry: IAssetIssuance, - authorAccount: CordKeyringPair, - authorizationUri: AuthorizationUri, - signCallback: SignExtrinsicCallback -): Promise { - try { - const api = ConfigService.get('api') - - const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri) - - const tx = api.tx.asset.issue( - assetEntry.entry, - assetEntry.digest, - authorizationId - ) - - const extrinsic = await Did.authorizeTx( - assetEntry.issuer, - tx, - signCallback, - authorAccount.address - ) - - return extrinsic - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( - `Error preparing extrinsic: "${errorMessage}".` - ) + `Error preparing VC Asset Entry extrinsic: "${errorMessage}".` + ); } } -export async function dispatchIssueToChain( - assetEntry: IAssetIssuance, +/** + * Dispatches the creation of a Verifiable Credential (VC) asset entry to the chain. + * @param assetQty - Quantity of the asset. + * @param digest - Digest string for the asset. + * @param creator - DID URI of the creator. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param assetEntryUri - URI of the asset entry. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to the AssetUri. + */ +export async function dispatchCreateVcToChain( + assetQty: number, + digest: string, + creator: DidUri, authorAccount: CordKeyringPair, authorizationUri: AuthorizationUri, + assetEntryUri: AssetUri, signCallback: SignExtrinsicCallback ): Promise { try { + const extrinsic = await prepareCreateVcExtrinsic( + assetQty, + digest, + creator, + authorAccount, + authorizationUri, + signCallback + ); - const extrinsic = await prepareExtrinsic(assetEntry, authorAccount, authorizationUri, signCallback) - await Chain.signAndSubmitTx(extrinsic, authorAccount) + await Chain.signAndSubmitTx(extrinsic, authorAccount); - return assetEntry.uri + return assetEntryUri; } catch (error) { const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( `Error dispatching to chain: "${errorMessage}".` - ) + ); } } -export async function prepareVcExtrinsic( - assetEntry: IAssetIssuance, +/** + * Prepares an extrinsic for issuing an asset entry. + * @param assetEntry - The asset entry to issue. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to a SubmittableExtrinsic. + */ +export async function prepareExtrinsic( + assetEntry: IAssetEntry, authorAccount: CordKeyringPair, authorizationUri: AuthorizationUri, signCallback: SignExtrinsicCallback ): Promise { try { - const api = ConfigService.get('api') - - const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri) + const api = ConfigService.get('api'); + const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri); - const tx = api.tx.asset.vcIssue( + const tx = api.tx.asset.issue( assetEntry.entry, assetEntry.digest, authorizationId - ) + ); const extrinsic = await Did.authorizeTx( - assetEntry.issuer, + assetEntry.creator, tx, signCallback, authorAccount.address - ) + ); - return extrinsic + return extrinsic; } catch (error) { - const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + const errorMessage = + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( `Error preparing extrinsic: "${errorMessage}".` - ) + ); } } -export async function dispatchIssueVcToChain( - assetEntry: IAssetIssuance, +/** + * Dispatches the issuance of an asset entry to the chain. + * @param assetEntry - The asset entry to issue. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to the AssetUri. + */ +export async function dispatchIssueToChain( + assetEntry: IAssetEntry, authorAccount: CordKeyringPair, authorizationUri: AuthorizationUri, signCallback: SignExtrinsicCallback ): Promise { try { + const extrinsic = await prepareExtrinsic( + assetEntry, + authorAccount, + authorizationUri, + signCallback + ); - const extrinsic = await prepareVcExtrinsic(assetEntry, authorAccount, authorizationUri, signCallback) - await Chain.signAndSubmitTx(extrinsic, authorAccount) - - return assetEntry.uri - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) - throw new SDKErrors.CordDispatchError( - `Error dispatching to chain: "${errorMessage}".` - ) - } -} - -export async function dispatchTransferToChain( - assetEntry: IAssetTransfer, - authorAccount: CordKeyringPair, - signCallback: SignExtrinsicCallback -): Promise { - try { - const api = ConfigService.get('api') - - const tx = api.tx.asset.transfer(assetEntry.entry, assetEntry.digest) - - const extrinsic = await Did.authorizeTx( - assetEntry.owner, - tx, - signCallback, - authorAccount.address - ) - - await Chain.signAndSubmitTx(extrinsic, authorAccount) + await Chain.signAndSubmitTx(extrinsic, authorAccount); - return `${ASSET_PREFIX}${assetEntry.entry.assetId}:${assetEntry.entry.assetInstanceId}` + return assetEntry.uri; } catch (error) { const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) + error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( `Error dispatching to chain: "${errorMessage}".` - ) + ); } } -export async function dispatchTransferVcToChain( - assetEntry: IAssetTransfer, +/** + * Prepares an extrinsic for issuing a Verifiable Credential (VC) asset entry. + * @param assetEntry - The asset entry to issue. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to a SubmittableExtrinsic. + */ +export async function prepareVcExtrinsic( + assetEntry: IAssetEntry, authorAccount: CordKeyringPair, + authorizationUri: AuthorizationUri, signCallback: SignExtrinsicCallback -): Promise { +): Promise { try { - const api = ConfigService.get('api') - - const tx = api.tx.asset.vcTransfer(assetEntry.entry, assetEntry.digest) - - const extrinsic = await Did.authorizeTx( - assetEntry.owner, - tx, - signCallback, - authorAccount.address - ) - - await Chain.signAndSubmitTx(extrinsic, authorAccount) - - return `${ASSET_PREFIX}${assetEntry.entry.assetId}:${assetEntry.entry.assetInstanceId}` - } catch (error) { - const errorMessage = - error instanceof Error ? error.message : JSON.stringify(error) - throw new SDKErrors.CordDispatchError( - `Error dispatching to chain: "${errorMessage}".` - ) - } -} + const api = ConfigService.get('api'); + const authorizationId: AuthorizationId = uriToIdentifier(authorizationUri); -export async function dispatchAssetStatusChangeToChain( - assetUri: AssetUri, - assetIssuerDidUri: DidUri, - authorAccount: CordKeyringPair, - newStatus: PalletAssetAssetStatusOf, - signCallback: SignExtrinsicCallback, - assetInstanceId?: string -): Promise { - try { - const api = ConfigService.get("api"); - let tx; - const assetId = uriToIdentifier(assetUri); - const assetIssuerDid = Did.toChain(assetIssuerDidUri); - - assetInstanceId = assetInstanceId?.split(":").pop(); - - /* Check if assetStatusType is undefined */ - if (newStatus === undefined) { - throw new SDKErrors.InvalidAssetStatus("Asset status is undefined."); - } - - if (assetInstanceId) { - let encodedAssetInstanceDetail = await api.query.asset.issuance( - assetId, - assetInstanceId - ); - if (encodedAssetInstanceDetail.isNone) { - throw new SDKErrors.AssetInstanceNotFound( - `Error: Asset Instance Not Found` - ); - } - let assetInstanceDetail = JSON.parse( - encodedAssetInstanceDetail.toString() - ); - if (assetIssuerDid !== assetInstanceDetail.assetInstanceIssuer) { - throw new SDKErrors.AssetIssuerMismatch(`Error: Asset issuer mismatch`); - } - - if ( - assetInstanceDetail.assetInstanceStatus?.toLowerCase() === - String(newStatus)?.toLowerCase() - ) { - throw new SDKErrors.AssetStatusError( - `Error: Asset Instance is already in the ${newStatus} state` - ); - } - tx = api.tx.asset.statusChange(assetId, assetInstanceId, newStatus); - } else { - let encodedAssetDetail = await api.query.asset.assets(assetId); - if (encodedAssetDetail.isNone) { - throw new SDKErrors.AssetNotFound(`Error: Asset Not Found`); - } - let assetDetail = JSON.parse(encodedAssetDetail.toString()); - - if (assetIssuerDid !== assetDetail.assetIssuer) { - throw new SDKErrors.AssetIssuerMismatch(`Error: Asset issuer mismatch`); - } - - if ( - assetDetail.assetStatus?.toLowerCase() === - String(newStatus)?.toLowerCase() - ) { - throw new SDKErrors.AssetStatusError( - `Error: Asset is already in the ${newStatus} state` - ); - } - tx = api.tx.asset.statusChange(assetId, null, newStatus); - } + const tx = api.tx.asset.vcIssue( + assetEntry.entry, + assetEntry.digest, + authorizationId + ); const extrinsic = await Did.authorizeTx( - assetIssuerDidUri, + assetEntry.creator, tx, signCallback, authorAccount.address ); - await Chain.signAndSubmitTx(extrinsic, authorAccount); + return extrinsic; } catch (error) { const errorMessage = error instanceof Error ? error.message : JSON.stringify(error); throw new SDKErrors.CordDispatchError( - `Error dispatching to chain: "${errorMessage}".` + `Error preparing extrinsic: "${errorMessage}".` ); } } -export async function dispatchAssetStatusChangeVcToChain( - assetUri: AssetUri, - assetIssuerDidUri: DidUri, +/** + * Dispatches the issuance of a Verifiable Credential (VC) asset entry to the chain. + * @param assetEntry - The asset entry to issue. + * @param authorAccount - Keyring pair of the author. + * @param authorizationUri - URI for authorization. + * @param signCallback - Callback for signing the extrinsic. + * @returns A promise that resolves to the AssetUri. + */ +export async function dispatchIssueVcToChain( + assetEntry: IAssetEntry, authorAccount: CordKeyringPair, - newStatus: PalletAssetAssetStatusOf, - signCallback: SignExtrinsicCallback, - assetInstanceId?: string -): Promise { + authorizationUri: AuthorizationUri, + signCallback: SignExtrinsicCallback +): Promise { try { - const api = ConfigService.get("api"); - let tx; - const assetId = uriToIdentifier(assetUri); - const assetIssuerDid = Did.toChain(assetIssuerDidUri); - - assetInstanceId = assetInstanceId?.split(":").pop(); - - /* Check if assetStatusType is undefined */ - if (newStatus === undefined) { - throw new SDKErrors.InvalidAssetStatus("Asset status is undefined."); - } - - if (assetInstanceId) { - let encodedAssetInstanceDetail = await api.query.asset.vcIssuance( - assetId, - assetInstanceId - ); - if (encodedAssetInstanceDetail.isNone) { - throw new SDKErrors.AssetInstanceNotFound( - `Error: Asset Instance Not Found` - ); - } - let assetInstanceDetail = JSON.parse( - encodedAssetInstanceDetail.toString() - ); - if (assetIssuerDid !== assetInstanceDetail.assetInstanceIssuer) { - throw new SDKErrors.AssetIssuerMismatch(`Error: Asset issuer mismatch`); - } - if ( - assetInstanceDetail.assetInstanceStatus?.toLowerCase() === - String(newStatus)?.toLowerCase() - ) { - throw new SDKErrors.AssetStatusError( - `Error: Asset Instance is already in the ${newStatus} state` - ); - } - tx = api.tx.asset.statusChange(assetId, assetInstanceId, newStatus); - } else { - let encodedAssetDetail = await api.query.asset.assets(assetId); - - if (encodedAssetDetail.isNone) { - throw new SDKErrors.AssetNotFound(`Error: Asset Not Found`); - } - let assetDetail = JSON.parse(encodedAssetDetail.toString()); - - if (assetIssuerDid !== assetDetail.assetIssuer) { - throw new SDKErrors.AssetIssuerMismatch(`Error: Asset issuer mismatch`); - } - if ( - assetDetail.assetStatus?.toLowerCase() === - String(newStatus)?.toLowerCase() - ) { - throw new SDKErrors.AssetStatusError( - `Error: Asset is already in the ${newStatus} state` - ); - } - tx = api.tx.asset.statusChange(assetId, null, newStatus); - } - - const extrinsic = await Did.authorizeTx( - assetIssuerDidUri, - tx, - signCallback, - authorAccount.address + const extrinsic = await prepareVcExtrinsic( + assetEntry, + authorAccount, + authorizationUri, + signCallback ); await Chain.signAndSubmitTx(extrinsic, authorAccount); + + return assetEntry.uri; } catch (error) { const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);