Repository: likecoin/nft-book-press
Pull request #320: [TAS-3524] ⚡️ Lazy load iscn-js and cosmos-js related imports
Author: login: AuroraHuang22
Created: 2025-04-01T16:14:13Z | Merged: 2025-04-04T10:46:19Z

[[TAS-3523] merge iscn signing client and cosmos signing client in book press](https://www.notion.so/likecoin/merge-iscn-signing-client-and-cosmos-signing-client-in-book-press-1c26658c4c68807680c3ed585d5c395c?pvs=4)
[[TAS-3524] lazy load cosmos-js and iscn-js in bookpress](https://www.notion.so/likecoin/lazy-load-cosmos-js-and-iscn-js-in-bookpress-1c26658c4c68809ea09cce4db0acc3c3?pvs=4)


Diff:
diff --git a/utils/cosmos.ts b/utils/cosmos.ts
index 748ef66bc..f8ef9669b 100644
--- a/utils/cosmos.ts
+++ b/utils/cosmos.ts
@@ -1,13 +1,12 @@
 import { BigNumber } from 'bignumber.js'
-import { OfflineSigner } from '@cosmjs/proto-signing'
-import { ISCNSigningClient, ISCNRecordData } from '@likecoin/iscn-js'
-import { parseAndCalculateStakeholderRewards } from '@likecoin/iscn-js/dist/iscn/parsing'
 import { MsgSend } from 'cosmjs-types/cosmos/nft/v1beta1/tx'
-import { DeliverTxResponse } from '@cosmjs/stargate'
 import { PageRequest } from 'cosmjs-types/cosmos/base/query/v1beta1/pagination'
-import { parseAuthzGrant, parseTxInfoFromIndexedTx } from '@likecoin/iscn-js/dist/messages/parsing'
 import { GenericAuthorization } from 'cosmjs-types/cosmos/authz/v1beta1/authz'
-import { formatMsgSend } from '@likecoin/iscn-js/dist/messages/likenft'
+
+import type { OfflineSigner } from '@cosmjs/proto-signing'
+import type { DeliverTxResponse } from '@cosmjs/stargate'
+import type { ISCNRecordData, ISCNSigningClient } from '@likecoin/iscn-js'
+
 import { addParamToUrl } from '.'
 import { TRANSFER_GAS } from '~/constant'
 
@@ -18,11 +17,40 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let cosmLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    const lib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+    const [parsing, msgParsing, likenft] = await Promise.all([
+      await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js/dist/iscn/parsing'),
+      await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js/dist/messages/parsing'),
+      await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js/dist/messages/likenft'),
+    ])
+    iscnLib = {
+      ...lib,
+      parseAndCalculateStakeholderRewards: parsing.parseAndCalculateStakeholderRewards,
+      parseAuthzGrant: msgParsing.parseAuthzGrant,
+      parseTxInfoFromIndexedTx: msgParsing.parseTxInfoFromIndexedTx,
+      formatMsgSend: likenft.formatMsgSend
+    }
+  }
+  return iscnLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
 
 export async function getSigningClient (): Promise<ISCNSigningClient> {
   if (!iscnSigningClient) {
     const { RPC_URL } = useRuntimeConfig().public
+    const { ISCNSigningClient } = await getISCNLib()
     const c = new ISCNSigningClient()
     await c.connect(RPC_URL)
     iscnSigningClient = c
@@ -61,6 +89,7 @@ export async function queryTxByHash (txHash: string) {
   if (!tx) { return null }
   const { code } = tx
   if (code) { throw new Error(`Tx failed with code: ${code}`) }
+  const { parseTxInfoFromIndexedTx } = await getISCNLib()
   const parsed = parseTxInfoFromIndexedTx(tx)
   return parsed
 }
@@ -89,8 +118,17 @@ export async function getNFTAuthzGranterGrants (granter: string) {
   const c = (await getSigningClient()).getISCNQueryClient()
   const client = await c.getQueryClient()
   const g = await client.authz.granterGrants(granter)
-  if (!g?.grants) { return [] }
-  const grants = g.grants.map(parseAuthzGrant).filter(g => (g?.authorization?.value as GenericAuthorization)?.msg === '/cosmos.nft.v1beta1.MsgSend')
+  if (!g?.grants) {
+    return []
+  }
+  const { parseAuthzGrant } = await getISCNLib()
+  const grants = g.grants
+    .map(parseAuthzGrant)
+    .filter(
+      g =>
+        (g?.authorization?.value as GenericAuthorization)?.msg ===
+        '/cosmos.nft.v1beta1.MsgSend'
+    )
   return grants
 }
 
@@ -99,6 +137,7 @@ export async function getNFTAuthzGrants (granter: string, grantee: string) {
   const client = await c.getQueryClient()
   const g = await client.authz.grants(granter, grantee, '/cosmos.nft.v1beta1.MsgSend')
   if (!g?.grants) { return null }
+  const { parseAuthzGrant } = await getISCNLib()
   const grants = g.grants.map(parseAuthzGrant)
   return grants[0]
 }
@@ -204,6 +243,7 @@ export async function signCreateRoyltyConfig (
     const totalAmount = royaltyUserAmount
     const signingClient = await getSigningClient()
     await signingClient.connectWithSigner(RPC_URL, signer)
+    const { parseAndCalculateStakeholderRewards } = await getISCNLib()
     const rewardMap = await parseAndCalculateStakeholderRewards(
       iscnData,
       iscnOwner,
@@ -236,7 +276,6 @@ export async function signCreateRoyltyConfig (
       })
     }
   } catch (err) {
-    // Don't throw on royalty create, not critical for now
     // eslint-disable-next-line no-console
     console.error(err)
   }
@@ -272,6 +311,7 @@ export async function signSendNFTs (
   const { RPC_URL } = useRuntimeConfig().public
   const signingClient = await getSigningClient()
   await signingClient.connectWithSigner(RPC_URL, signer)
+  const { formatMsgSend } = await getISCNLib()
   const messages = classIds.map((classId, index) => formatMsgSend(
     address,
     targetAddress,
@@ -435,16 +475,6 @@ export async function getAccountBalance (address: string) {
   return new BigNumber(amountToLIKE(balance, CHAIN_MINIMAL_DENOM))
 }
 
-let cosmLib: any = null
-
-async function getCosmLib () {
-  if (!cosmLib) {
-    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
-  }
-  return cosmLib
-}
-
-// Modify sendLIKE to get config from runtime
 export async function sendLIKE (
   fromAddress: string,
   toAddress: string,
@@ -462,13 +492,13 @@ export async function sendLIKE (
     }]
   }
 
-  const cosm = await getCosmLib()
-  const client = await cosm.SigningStargateClient.connectWithSigner(network.rpc, signer)
+  const { SigningStargateClient, assertIsDeliverTxSuccess } = await getCosmLib()
+  const client = await SigningStargateClient.connectWithSigner(network.rpc, signer)
   const coins = [{
     amount: new BigNumber(amount).shiftedBy(9).toFixed(0, 0),
     denom: CHAIN_MINIMAL_DENOM
   }]
   const res = await client.sendTokens(fromAddress, toAddress, coins, DEFAULT_TRANSFER_FEE, memo)
-  cosm.assertIsDeliverTxSuccess(res)
+  assertIsDeliverTxSuccess(res)
   return res
 }
diff --git a/utils/iscn.ts b/utils/iscn.ts
index e2a64bc15..95eb82a21 100644
--- a/utils/iscn.ts
+++ b/utils/iscn.ts
@@ -2,10 +2,10 @@ import { BigNumber } from 'bignumber.js'
 import type { OfflineSigner } from '@cosmjs/proto-signing'
 import type { DeliverTxResponse } from '@cosmjs/stargate'
 import type { ISCNSignPayload, ISCNSigningClient } from '@likecoin/iscn-js'
+import type { ISCNRegisterPayload } from './iscn.type'
 import { ISCN_GAS_FEE, ISCN_GAS_MULTIPLIER } from '~/constant'
 
-let client: ISCNSigningClient | null = null
-let iscnLib: any = null
+import { getSigningClient } from '~/utils/cosmos'
 
 export async function getISCNLib () {
   if (!iscnLib) {
@@ -63,6 +63,7 @@ export function formatISCNTxPayload (
 
 export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
   const signingClient = await getSigningClient()
+  // typo in the original code
   const res = await signingClient.esimateISCNTxGasAndFee(tx)
   return res
 }


Reviews:
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR refactors the ISCN and Cosmos signing clients by merging related functionalities and implementing lazy loading of external dependencies to preserve ISCN data integrity. Key changes include:
- Removal of redundant functions in utils/iscn.ts and shifting responsibility to the Cosmos client for lazy loading dependencies.
- Updating function signatures to use broad types (any) and explicit type casts where necessary.
- Propagating additional metadata properties to the UI state in composables and components.

### Reviewed Changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

| File                                | Description                                                                         |
| ----------------------------------- | ----------------------------------------------------------------------------------- |
| utils/iscn.ts                       | Merged ISCN signing client functions and applied lazy loading with type casts.      |
| utils/cosmos.ts                     | Refactored lazy-loading of external libraries and updated function parameters.      |
| composables/useISCN.ts               | Updated computed payload to include extra fields while preserving intended overrides.|
| components/EditISCNMetadataModal.vue| Extended metadata mapping to include additional identifiers and stakeholder info.  |




state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T16:14:52Z
user: login: AuroraHuang22
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T16:17:56Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR enables lazy loading for iscn-js and cosmos-js modules in Bookpress to improve performance by deferring module loading until needed.  
- Removed static imports and eager client initializations in utils/iscn.ts and utils/cosmos.ts.  
- Replaced direct type annotations with “any” in several function parameters to work with lazy-loaded modules.

### Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 10 comments.

| File           | Description                                                                            |
| -------------- | -------------------------------------------------------------------------------------- |
| utils/iscn.ts  | Removed eager imports and modified functions to use lazy loading with dynamic imports. |
| utils/cosmos.ts| Refactored to lazy load various cosmos-js and iscn-js submodules and updated signer types.|


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**utils/iscn.ts:90**
* Switching the transaction parameter to 'any' in signISCNTx compromises type safety. Consider reinstating the explicit type for accuracy.
```
tx: any,
```
**utils/cosmos.ts:380**
* Replacing explicit signer types with 'any' in signRevokeNFTSendAuthz can lead to subtle errors. Consider using the proper 'OfflineSigner' type instead.
```
signer: any,
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T03:14:06Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This pull request introduces lazy loading for iscn-js and cosmos-js related imports to improve application startup performance. Key changes include:
- Removal of static imports for iscn-js and several cosmos-js modules, replacing them with dynamic imports.
- Adjustment of function and parameter types to accommodate lazy loaded modules.
- Updates to function implementations in both iscn.ts and cosmos.ts to support the new loading strategy.

### Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

| File             | Description                                                  |
| ---------------- | ------------------------------------------------------------ |
| utils/iscn.ts    | Removed direct imports and instantiated client using lazy loading with dynamic imports; adjusted type casts for ISCNSignPayload and DeliverTxResponse. |
| utils/cosmos.ts  | Replaced static imports with lazy-loaded modules for cosmos-js and iscn-js submodules; updated types for OfflineSigner and various signing client functions. |


<details>
<summary>Comments suppressed due to low confidence (3)</summary>

**utils/cosmos.ts:57**
* [nitpick] Consider specifying a more precise return type for getSigningClient instead of 'any' to improve type safety and clarity.
```
export async function getSigningClient (): Promise<any> {
```
**utils/cosmos.ts:238**
* [nitpick] The function name 'signCreateRoyltyConfig' appears to be misspelled; consider renaming it to 'signCreateRoyaltyConfig' for clarity.
```
export async function signCreateRoyltyConfig (
```
**utils/cosmos.ts:331**
* [nitpick] Consider defining a type alias for DeliverTxResponse to reduce repetition of long import paths and improve code readability.
```
) as import('@cosmjs/stargate').DeliverTxResponse
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T04:13:01Z
user: login: copilot-pull-request-reviewer[bot]
body: ## Pull Request Overview

This PR implements lazy loading for the iscn-js and cosmos-js related imports to optimize performance in BookPress. Key changes include:
- Removing static imports and replacing them with dynamic imports for iscn-js, cosmos-js, and related parsing/messaging libraries.
- Updating function signatures and type annotations to align with the new lazy-loaded modules.
- Adjusting calls to methods across utils/iscn.ts and utils/cosmos.ts to reflect the updated dynamic import patterns.

### Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

| File           | Description                                                |
| -------------- | ---------------------------------------------------------- |
| utils/iscn.ts  | Replaces static imports and updates type usage; note the method call with a possible typo.  |
| utils/cosmos.ts| Implements lazy loading for multiple libraries and updates type references accordingly; potential typo in a function name. |


<details>
<summary>Comments suppressed due to low confidence (2)</summary>

**utils/iscn.ts:42**
* The method call 'esimateISCNTxGasAndFee' appears to contain a typo; please confirm if this is intentional or if it should be 'estimateISCNTxGasAndFee'.
```
const res = await signingClient.esimateISCNTxGasAndFee(tx)
```
**utils/cosmos.ts:238**
* There appears to be a typo in the function name 'signCreateRoyltyConfig'. Consider renaming it to 'signCreateRoyaltyConfig' for clarity.
```
export async function signCreateRoyltyConfig (
```
</details>


state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T05:14:15Z
user: login: williamchong
state: CHANGES_REQUESTED
author_association: MEMBER
submitted_at: 2025-04-02T06:54:44Z
user: login: AuroraHuang22
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T11:32:05Z
user: login: AuroraHuang22
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T11:32:10Z
user: login: AuroraHuang22
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T11:32:23Z
user: login: AuroraHuang22
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-03T11:32:26Z

Review comments:
diff_hunk: @@ -55,33 +31,36 @@ export function formatISCNTxPayload (payload: ISCNRegisterPayload): ISCNSignPayl
     usageInfo: license,
     contentFingerprints: [...new Set(contentFingerprints)],
     recordNotes
-  }
+  }as import('@likecoin/iscn-js').ISCNSignPayload
 }
 
-export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
+export async function estimateISCNTxGasAndFee (tx: any) {
   const signingClient = await getSigningClient()
-  const res = await signingClient.esimateISCNTxGasAndFee(tx)
+  const res = await signingClient.esimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
path: utils/iscn.ts
user: login: Copilot
body: Verify that the method name 'esimateISCNTxGasAndFee' is correct; if it is a typo, renaming it to 'estimateISCNTxGasAndFee' will help prevent potential issues.
```suggestion
  const res = await signingClient.estimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
```
created_at: 2025-04-01T16:14:52Z
author_association: CONTRIBUTOR
diff_hunk: @@ -55,33 +31,36 @@ export function formatISCNTxPayload (payload: ISCNRegisterPayload): ISCNSignPayl
     usageInfo: license,
     contentFingerprints: [...new Set(contentFingerprints)],
     recordNotes
-  }
+  }as import('@likecoin/iscn-js').ISCNSignPayload
 }
 
-export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
+export async function estimateISCNTxGasAndFee (tx: any) {
   const signingClient = await getSigningClient()
-  const res = await signingClient.esimateISCNTxGasAndFee(tx)
+  const res = await signingClient.esimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
path: utils/iscn.ts
user: login: AuroraHuang22
body: [🐛 Fix typo in estimateISCNTxGasAndFee function](https://github.com/likecoin/nft-book-press/pull/320/commits/b74da73ee02e654829b9a55f198f7c111e47a617)
created_at: 2025-04-01T16:17:56Z
author_association: CONTRIBUTOR
diff_hunk: @@ -54,34 +31,38 @@ export function formatISCNTxPayload (payload: ISCNRegisterPayload): ISCNSignPayl
     keywords: tagsString.split(','),
     usageInfo: license,
     contentFingerprints: [...new Set(contentFingerprints)],
-    recordNotes
-  }
+    recordNotes,
+    stakeholders: []
+  }as import('@likecoin/iscn-js').ISCNSignPayload
 }
 
-export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
+export async function estimateISCNTxGasAndFee (tx: any) {
   const signingClient = await getSigningClient()
-  const res = await signingClient.esimateISCNTxGasAndFee(tx)
+  const res = await signingClient.estimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
path: utils/iscn.ts
user: login: Copilot
body: Replacing the explicit 'ISCNSignPayload' type with 'any' here reduces type safety and may lead to runtime errors. Consider reverting to the specific type.
created_at: 2025-04-02T03:14:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -54,34 +31,38 @@ export function formatISCNTxPayload (payload: ISCNRegisterPayload): ISCNSignPayl
     keywords: tagsString.split(','),
     usageInfo: license,
     contentFingerprints: [...new Set(contentFingerprints)],
-    recordNotes
-  }
+    recordNotes,
+    stakeholders: []
+  }as import('@likecoin/iscn-js').ISCNSignPayload
 }
 
-export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
+export async function estimateISCNTxGasAndFee (tx: any) {
   const signingClient = await getSigningClient()
-  const res = await signingClient.esimateISCNTxGasAndFee(tx)
+  const res = await signingClient.estimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
   return res
 }
 
 export async function signISCN (
-  tx: ISCNSignPayload,
-  signer: OfflineSigner,
+  tx: any,
path: utils/iscn.ts
user: login: Copilot
body: Changing the 'tx' parameter type from 'ISCNSignPayload' to 'any' in signISCN reduces type safety. Please consider restoring the explicit type.
```suggestion
  tx: import('@likecoin/iscn-js').ISCNSignPayload,
```
created_at: 2025-04-02T03:14:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -54,34 +31,38 @@ export function formatISCNTxPayload (payload: ISCNRegisterPayload): ISCNSignPayl
     keywords: tagsString.split(','),
     usageInfo: license,
     contentFingerprints: [...new Set(contentFingerprints)],
-    recordNotes
-  }
+    recordNotes,
+    stakeholders: []
+  }as import('@likecoin/iscn-js').ISCNSignPayload
 }
 
-export async function estimateISCNTxGasAndFee (tx: ISCNSignPayload) {
+export async function estimateISCNTxGasAndFee (tx: any) {
   const signingClient = await getSigningClient()
-  const res = await signingClient.esimateISCNTxGasAndFee(tx)
+  const res = await signingClient.estimateISCNTxGasAndFee(tx as import('@likecoin/iscn-js').ISCNSignPayload)
   return res
 }
 
 export async function signISCN (
-  tx: ISCNSignPayload,
-  signer: OfflineSigner,
+  tx: any,
+  signer: any,
path: utils/iscn.ts
user: login: Copilot
body: Replacing the 'OfflineSigner' type with 'any' for the signer parameter in signISCN may lead to unintended usage. It is recommended to use the proper type.
```suggestion
  signer: import('@cosmjs/proto-signing').OfflineSigner,
```
created_at: 2025-04-02T03:14:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -102,18 +83,21 @@ export async function signISCN (
       }
     })
   const res = await signingPromise
-  return res as DeliverTxResponse
+  return res as import('@cosmjs/stargate').DeliverTxResponse
 }
 
 export async function signISCNTx (
-  tx: ISCNSignPayload,
-  signer: OfflineSigner,
+  tx: any,
+  signer: any,
path: utils/iscn.ts
user: login: Copilot
body: Using 'any' for the signer parameter in signISCNTx removes valuable type checks. Restoring the 'OfflineSigner' type would improve reliability.
```suggestion
  signer: import('@cosmjs/proto-signing').OfflineSigner,
```
created_at: 2025-04-02T03:14:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,19 +12,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
+
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
+
+export async function getSigningClient (): Promise<any> {
   if (!iscnSigningClient) {
     const { RPC_URL } = useRuntimeConfig().public
+    const { ISCNSigningClient } = await getISCNLib()
     const c = new ISCNSigningClient()
     await c.connect(RPC_URL)
     iscnSigningClient = c
   }
   return iscnSigningClient
 }
 
-export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<ISCNSigningClient> {
+export async function getSigningClientWithSigner (signer: any): Promise<any> {
path: utils/cosmos.ts
user: login: Copilot
body: Changing the signer parameter type to 'any' in getSigningClientWithSigner reduces type safety. It is advisable to keep the signer’s explicit type for clarity.
```suggestion
import { OfflineSigner } from '@cosmjs/proto-signing';

export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<any> {
```
created_at: 2025-04-02T03:14:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -149,14 +187,14 @@ export async function signCreateISCNRecord (
   const parsedData = { ...otherData, ...contentMetadata }
   const res = await signingClient.createISCNRecord(address, parsedData, { memo })
   const queryClient = await signingClient.getISCNQueryClient()
-  const [iscnId] = await queryClient.queryISCNIdsByTx((res as DeliverTxResponse).transactionHash)
+  const [iscnId] = await queryClient.queryISCNIdsByTx((res as any).transactionHash)
   return iscnId
 }
 
 export async function signCreateNFTClass (
   data: any,
   iscnId: string,
-  signer: OfflineSigner,
+  signer: any,
path: utils/cosmos.ts
user: login: Copilot
body: Replacing 'OfflineSigner' with 'any' in signCreateNFTClass may lead to misuse of the signer. Consider preserving the specific type.
```suggestion
  signer: OfflineSigner,
```
created_at: 2025-04-02T03:14:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -282,13 +320,13 @@ export async function signSendNFTs (
     address,
     messages,
     { memo }
-  ) as DeliverTxResponse
+  ) as any
   return res
 }
 
 export async function signGrantNFTSendAuthz (
   grantee: string,
-  signer: OfflineSigner,
+  signer: any,
path: utils/cosmos.ts
user: login: Copilot
body: Changing the signer parameter to 'any' in signGrantNFTSendAuthz weakens type validation. Reinstating the explicit signer type would be beneficial.
created_at: 2025-04-02T03:14:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -305,7 +343,7 @@ export async function signExecNFTSendAuthz (
   ownerAddress: string,
   classIds: string[],
   nftIds: string[],
-  signer: OfflineSigner,
+  signer: any,
path: utils/cosmos.ts
user: login: Copilot
body: The use of 'any' for the signer in signExecNFTSendAuthz undermines type safety. It is recommended to specify the correct type.
created_at: 2025-04-02T03:14:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -359,7 +397,7 @@ export async function sendNFTsToAPIWallet (
   classIds: string[],
   nftIds: string[],
   nftCount: number,
-  signer: OfflineSigner,
+  signer: any,
path: utils/cosmos.ts
user: login: Copilot
body: The signer parameter in sendNFTsToAPIWallet now uses 'any', reducing the benefits of TypeScript's type system. Using the specific type would enhance code reliability.
```suggestion
  signer: OfflineSigner,
```
created_at: 2025-04-02T03:14:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -435,21 +473,11 @@ export async function getAccountBalance (address: string) {
   return new BigNumber(amountToLIKE(balance, CHAIN_MINIMAL_DENOM))
 }
 
-let cosmLib: any = null
-
-async function getCosmLib () {
-  if (!cosmLib) {
-    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
-  }
-  return cosmLib
-}
-
-// Modify sendLIKE to get config from runtime
 export async function sendLIKE (
   fromAddress: string,
   toAddress: string,
   amount: string,
-  signer: OfflineSigner,
+  signer: any,
path: utils/cosmos.ts
user: login: Copilot
body: Switching from 'OfflineSigner' to 'any' in sendLIKE removes critical type safety. Restoring the explicit signer type is recommended for better error checking.
```suggestion
  signer: OfflineSigner,
```
created_at: 2025-04-02T03:14:06Z
author_association: CONTRIBUTOR
diff_hunk: @@ -236,8 +288,6 @@ export async function signCreateRoyltyConfig (
       })
     }
   } catch (err) {
-    // Don't throw on royalty create, not critical for now
-    // eslint-disable-next-line no-console
path: utils/cosmos.ts
user: login: williamchong
body: Should keep this rule
created_at: 2025-04-02T06:05:05Z
author_association: MEMBER
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
path: utils/cosmos.ts
user: login: williamchong
body: I think we can merge all these into `getISCNLib`, then parse the individual functions out from the main lib
created_at: 2025-04-02T06:53:49Z
author_association: MEMBER
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
+
+export async function getSigningClient (): Promise<any> {
path: utils/cosmos.ts
user: login: williamchong
body: Can we keep `ISCNSigningClient`?
created_at: 2025-04-02T06:54:16Z
author_association: MEMBER
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
+
+export async function getSigningClient (): Promise<any> {
   if (!iscnSigningClient) {
     const { RPC_URL } = useRuntimeConfig().public
+    const { ISCNSigningClient } = await getISCNLib()
     const c = new ISCNSigningClient()
     await c.connect(RPC_URL)
     iscnSigningClient = c
   }
   return iscnSigningClient
 }
 
-export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<ISCNSigningClient> {
+export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<any> {
path: utils/cosmos.ts
user: login: williamchong
body: Can we keep `ISCNSigningClient`?
created_at: 2025-04-02T06:54:26Z
author_association: MEMBER
diff_hunk: @@ -236,8 +288,6 @@ export async function signCreateRoyltyConfig (
       })
     }
   } catch (err) {
-    // Don't throw on royalty create, not critical for now
-    // eslint-disable-next-line no-console
path: utils/cosmos.ts
user: login: AuroraHuang22
body: [♻️ Refactor ISCN library imports to consolidate and simplify usage](https://github.com/likecoin/nft-book-press/pull/320/commits/ad11d3b863a48cea1c1ee76b3766ab507ad1a4e2)
created_at: 2025-04-03T11:32:05Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
path: utils/cosmos.ts
user: login: AuroraHuang22
body: [♻️ Refactor ISCN library imports to consolidate and simplify usage](https://github.com/likecoin/nft-book-press/pull/320/commits/ad11d3b863a48cea1c1ee76b3766ab507ad1a4e2)
created_at: 2025-04-03T11:32:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
+
+export async function getSigningClient (): Promise<any> {
path: utils/cosmos.ts
user: login: AuroraHuang22
body: [🎨 Import type ISCNSigningClient](https://github.com/likecoin/nft-book-press/pull/320/commits/c2e140d19b20aa9f4a80d5ca9c1f0bc0cd51e439)
created_at: 2025-04-03T11:32:23Z
author_association: CONTRIBUTOR
diff_hunk: @@ -18,19 +17,60 @@ export const royaltyRateBasisPoints = 1000 // 10% as in current chain config
 export const royaltyFeeAmount = 25000 // 2.5%
 export const royaltyUserAmount = 1000000 - royaltyFeeAmount // 1000000 - fee
 
-let iscnSigningClient: ISCNSigningClient | null = null
+let iscnSigningClient: any = null
+let iscnLib: any = null
+let iscnParsingLib: any = null
+let cosmLib: any = null
+let iscnMsgLib: any = null
+let likenftMsgLib: any = null
+
+async function getISCNLib () {
+  if (!iscnLib) {
+    iscnLib = await import(/* webpackChunkName: "iscn" */ '@likecoin/iscn-js')
+  }
+  return iscnLib
+}
+
+async function getISCNParsingLib () {
+  if (!iscnParsingLib) {
+    iscnParsingLib = await import(/* webpackChunkName: "iscn-parsing" */ '@likecoin/iscn-js/dist/iscn/parsing')
+  }
+  return iscnParsingLib
+}
 
-export async function getSigningClient (): Promise<ISCNSigningClient> {
+async function getISCNMsgLib () {
+  if (!iscnMsgLib) {
+    iscnMsgLib = await import(/* webpackChunkName: "iscn-msg" */ '@likecoin/iscn-js/dist/messages/parsing')
+  }
+  return iscnMsgLib
+}
+
+async function getLikeNFTMsgLib () {
+  if (!likenftMsgLib) {
+    likenftMsgLib = await import(/* webpackChunkName: "likenft-msg" */ '@likecoin/iscn-js/dist/messages/likenft')
+  }
+  return likenftMsgLib
+}
+
+async function getCosmLib () {
+  if (!cosmLib) {
+    cosmLib = await import(/* webpackChunkName: "cosmjs" */ '@cosmjs/stargate')
+  }
+  return cosmLib
+}
+
+export async function getSigningClient (): Promise<any> {
   if (!iscnSigningClient) {
     const { RPC_URL } = useRuntimeConfig().public
+    const { ISCNSigningClient } = await getISCNLib()
     const c = new ISCNSigningClient()
     await c.connect(RPC_URL)
     iscnSigningClient = c
   }
   return iscnSigningClient
 }
 
-export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<ISCNSigningClient> {
+export async function getSigningClientWithSigner (signer: OfflineSigner): Promise<any> {
path: utils/cosmos.ts
user: login: AuroraHuang22
body: [🎨 Import type ISCNSigningClient](https://github.com/likecoin/nft-book-press/pull/320/commits/c2e140d19b20aa9f4a80d5ca9c1f0bc0cd51e439)
created_at: 2025-04-03T11:32:26Z
author_association: CONTRIBUTOR

PR comments:
user: login: notion-workspace[bot]
created_at: 2025-04-01T16:14:23Z
body: <a href="https://www.notion.so/merge-iscn-signing-client-and-cosmos-signing-client-in-book-press-1c26658c4c68807680c3ed585d5c395c?pvs=8&n=github_linkback">merge iscn signing client and cosmos signing client in book press</a>
author_association: NONE
user: login: notion-workspace[bot]
created_at: 2025-04-02T03:11:25Z
body: <a href="https://www.notion.so/lazy-load-cosmos-js-and-iscn-js-in-bookpress-1c26658c4c68809ea09cce4db0acc3c3?pvs=8&n=github_linkback">lazy load cosmos-js and iscn-js in bookpress</a>
author_association: NONE