Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/neptune service #515

Merged
merged 4 commits into from
Nov 18, 2024
Merged

Feat/neptune service #515

merged 4 commits into from
Nov 18, 2024

Conversation

shane-moore
Copy link
Collaborator

@shane-moore shane-moore commented Nov 18, 2024

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new query functionalities for asset prices and lending rates.
    • Added methods for fetching asset prices and redemption ratios.
    • Implemented execution arguments for deposit and withdrawal operations in Neptune contracts.
    • Added a new NeptuneService for interacting with Neptune smart contracts.
  • Enhancements

    • Expanded export capabilities to include new modules and constants related to asset management.
  • Types and Interfaces

    • Added new TypeScript types for asset information and responses, ensuring better type safety and structure.
  • Documentation

    • Updated documentation to include the new NeptuneService and its functionalities.
    • Restructured the table of contents in the documentation to include "Neptune Service."

Copy link

coderabbitai bot commented Nov 18, 2024

Walkthrough

The changes in this pull request include the addition of new functionalities and exports in the SDK's TypeScript files related to the Neptune module. Notable additions are the getDenom function, new classes for querying prices and lending rates, and a service class for asset management. New execution argument classes for deposits and withdrawals have also been introduced, enhancing the module's capabilities. The overall structure of existing files is maintained while expanding the interface with new exports and definitions.

Changes

File Path Change Summary
packages/sdk-ts/src/client/wasm/index.ts Added export for all entities from ./neptune/index.js.
packages/sdk-ts/src/client/wasm/neptune/helper.ts Added method: `getDenom(assetInfo: AssetInfo): string
packages/sdk-ts/src/client/wasm/neptune/index.ts Introduced new file; exports from types.js, service.js, transformer.js, queries/index.js; added constant NEPTUNE_PRICE_CONTRACT.
packages/sdk-ts/src/client/wasm/neptune/queries/QueryGetPrices.ts Added namespace QueryGetPrices, interface Params, and class QueryGetPrices with method toPayload().
packages/sdk-ts/src/client/wasm/neptune/queries/QueryLendingRates.ts Added namespace QueryGetAllLendingRates, interface Params, and class QueryGetAllLendingRates with method toPayload().
packages/sdk-ts/src/client/wasm/neptune/queries/index.ts Added exports for QueryGetPrices and QueryGetAllLendingRates.
packages/sdk-ts/src/client/wasm/neptune/service.ts Added class NeptuneService with multiple methods for asset management and error handling.
packages/sdk-ts/src/client/wasm/neptune/transformer.ts Added class NeptuneQueryTransformer with methods for transforming contract query responses.
packages/sdk-ts/src/client/wasm/neptune/types.ts Introduced new types: AssetInfo, AssetInfoWithPrice, PriceResponse, LendingRateResponse; added constant NEPTUNE_USDT_CW20_CONTRACT.
packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts Added namespace ExecArgNeptuneDeposit, interfaces Params and Data, and class ExecArgNeptuneDeposit with methods for handling execution arguments.
packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts Added namespace ExecArgNeptuneWithdraw, interfaces Params and Data, and class ExecArgNeptuneWithdraw with methods for handling execution arguments.
packages/sdk-ts/src/core/modules/wasm/index.ts Added imports and exports for ExecArgNeptuneDeposit and ExecArgNeptuneWithdraw.

Possibly related PRs

  • Feat/denom holders and stats #502: The changes in this PR involve the addition of a new export for the fetchDenomHolders method, which relates to the new export statement added in the main PR for ./neptune/index.js, as both involve handling denom-related functionalities.

Suggested reviewers

  • ThomasRalee

🐇 In the land of code, where bunnies hop,
New functions and classes, we never stop!
With Neptune's riches, we now can play,
Querying prices in a brand new way.
So let's celebrate this code delight,
Hopping through changes, all feels just right! 🌟

Warning

There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure.

🔧 eslint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/sdk-ts/src/client/wasm/neptune/service.ts

Oops! Something went wrong! :(

ESLint: 7.32.0

ESLint couldn't find the config "./../../eslintrc.js" to extend from. Please check that the name of the config is correct.

The config "./../../eslintrc.js" was referenced from the config file in "/packages/sdk-ts/.eslintrc.js".

If you still have problems, please stop by https://eslint.org/chat/help to chat with the team.


🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🧹 Outside diff range and nitpick comments (15)
packages/sdk-ts/src/client/wasm/neptune/helper.ts (1)

3-9: Consider strengthening type safety and validation

While the type guard pattern is correct, consider these improvements:

  1. The return type could be just string since both paths should always return a string
  2. Add validation for empty/undefined property values
-export function getDenom(assetInfo: AssetInfo): string | undefined {
+export function getDenom(assetInfo: AssetInfo): string {
   if ('native_token' in assetInfo) {
+    if (!assetInfo.native_token.denom) {
+      throw new Error('Native token denom is required')
+    }
     return assetInfo.native_token.denom
   }

+  if (!assetInfo.token.contract_addr) {
+    throw new Error('Token contract address is required')
+  }
   return assetInfo.token.contract_addr
 }
packages/sdk-ts/src/client/wasm/neptune/queries/QueryGetPrices.ts (2)

5-9: Add JSDoc documentation for better developer experience

Consider adding JSDoc comments to describe:

  • The purpose of the namespace
  • The expected format and constraints of the assets array
  • Example usage
+/**
+ * Namespace containing types for querying asset prices
+ */
 export declare namespace QueryGetPrices {
+  /**
+   * Parameters for querying prices of multiple assets
+   * @property {AssetInfo[]} assets - Array of assets to query prices for
+   * @example
+   * {
+   *   assets: [
+   *     { native_token: { denom: "uusdc" } },
+   *     { token: { contract_addr: "inj1..." } }
+   *   ]
+   * }
+   */
   export interface Params {
     assets: AssetInfo[]
   }
 }

11-19: Add input validation for robust error handling

The implementation looks good but could benefit from input validation to prevent invalid queries.

Consider adding validation:

 export class QueryGetPrices extends BaseWasmQuery<QueryGetPrices.Params> {
   toPayload() {
+    if (!this.params.assets || this.params.assets.length === 0) {
+      throw new Error('Assets array cannot be empty')
+    }
+
     return toBase64({
       get_prices: {
         assets: this.params.assets,
       },
     })
   }
 }
packages/sdk-ts/src/client/wasm/neptune/types.ts (3)

1-12: LGTM! Consider adding JSDoc comments.

The AssetInfo type correctly implements a discriminated union for CosmWasm token types. Consider adding JSDoc comments to document the purpose and usage of this type.

+/**
+ * Represents either a CW20 token with a contract address or a native token with a denomination.
+ * @example
+ * // CW20 token
+ * const token: AssetInfo = { token: { contract_addr: "inj1..." } };
+ * // Native token
+ * const native: AssetInfo = { native_token: { denom: "inj" } };
+ */
 export type AssetInfo =
   | {
       token: {

13-13: Consider enhancing type safety for price handling.

While using string for price is good for precision, consider these improvements:

  1. Add runtime validation for price string format
  2. Consider using a more specific type for price representation
-export type AssetInfoWithPrice = {assetInfo: AssetInfo, price: string }
+/**
+ * Asset information combined with its price.
+ * @property assetInfo - The asset information
+ * @property price - The price in decimal string format (e.g., "123.456")
+ */
+export type AssetInfoWithPrice = {
+  assetInfo: AssetInfo;
+  price: string; // Consider: `DecimalString = Brand<string, 'Decimal'>`
+}

15-16: Consider normalizing response type structures.

There's an inconsistency in the response structures:

  • PriceResponse uses { price: string }
  • LendingRateResponse uses direct string

This inconsistency could lead to confusion. Consider normalizing these structures.

-export type PriceResponse = Array<[AssetInfo, { price: string }]>
-export type LendingRateResponse = Array<[AssetInfo, string]>
+/**
+ * Response type for asset prices
+ */
+export type PriceResponse = Array<[AssetInfo, { price: string }]>
+
+/**
+ * Response type for lending rates
+ */
+export type LendingRateResponse = Array<[AssetInfo, { rate: string }]>
packages/sdk-ts/src/client/wasm/neptune/queries/QueryLendingRates.ts (2)

5-10: Consider adding runtime validation for the limit parameter.

While the types are well-defined, consider adding runtime validation to ensure the limit is a positive integer. This would prevent potential issues with invalid query parameters.

 export class QueryGetAllLendingRates extends BaseWasmQuery<QueryGetAllLendingRates.Params> {
+  constructor(params: QueryGetAllLendingRates.Params) {
+    super(params);
+    if (params.limit !== undefined && (params.limit <= 0 || !Number.isInteger(params.limit))) {
+      throw new Error('Limit must be a positive integer');
+    }
+  }

   toPayload() {

12-23: Consider adding type definitions for the payload structure.

While the implementation is clean, adding explicit types for the payload structure would improve type safety and documentation.

+interface LendingRatesPayload {
+  get_all_lending_rates: {
+    limit?: number;
+    start_after?: AssetInfo;
+  }
+}

 export class QueryGetAllLendingRates extends BaseWasmQuery<QueryGetAllLendingRates.Params> {
   toPayload() {
-    const payload = {
+    const payload: LendingRatesPayload = {
       get_all_lending_rates: {
         ...(this.params.limit !== undefined ? { limit: this.params.limit } : {}),
         ...(this.params.startAfter ? { start_after: this.params.startAfter } : {}),
       },
     };

     return toBase64(payload);
   }
 }

Also, note that the payload uses snake_case keys (get_all_lending_rates, start_after) while the TypeScript interface uses camelCase (startAfter). This seems intentional for WebAssembly compatibility, but it might be worth documenting this convention.

Consider adding a comment explaining the casing convention:

 export class QueryGetAllLendingRates extends BaseWasmQuery<QueryGetAllLendingRates.Params> {
+  /**
+   * Converts the query parameters to a Base64 encoded payload.
+   * Note: The payload uses snake_case keys to match the WebAssembly contract interface.
+   */
   toPayload() {
packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts (1)

13-15: Enhance class documentation

While the class is marked with @category, consider adding more comprehensive documentation including:

  • Purpose and usage examples
  • Parameter descriptions (when added to the Params interface)
  • Expected behavior and side effects
packages/sdk-ts/src/client/wasm/neptune/transformer.ts (1)

5-27: Consider refactoring to standalone functions.

The static analysis tool correctly points out that this class only contains static methods. Consider refactoring these into standalone functions for better modularity and simpler usage.

Example refactor:

-export class NeptuneQueryTransformer {
-  static contractPricesResponseToPrices(
+export function transformContractPricesToPrices(
     response: WasmContractQueryResponse,
   ): Array<{ assetInfo: AssetInfo; price: string }> {
     // ... implementation
   }
 
-  static contractLendingRatesResponseToLendingRates(
+export function transformContractLendingRatesToLendingRates(
     response: WasmContractQueryResponse,
   ): Array<{ assetInfo: AssetInfo; lendingRate: string }> {
     // ... implementation
   }
-}
🧰 Tools
🪛 Biome

[error] 5-27: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts (1)

25-28: Consider adding custom error types

To improve error handling across the Neptune service, consider introducing custom error types (e.g., NeptuneWithdrawError) that extend from a base NeptuneError class. This would provide better error categorization and handling for consumers of the SDK.

🧰 Tools
🪛 Biome

[error] 25-25: Shouldn't redeclare 'ExecArgNeptuneWithdraw'. Consider to delete it or rename it.

'ExecArgNeptuneWithdraw' is defined here:

(lint/suspicious/noRedeclare)

packages/sdk-ts/src/client/wasm/neptune/service.ts (4)

32-32: Correct the typo in the constructor documentation

There's a typo in the documentation comment for the constructor. The word "instan ce" should be corrected to "instance".


91-95: Provide more informative error messages

When throwing an error due to missing price data, including specific asset information can aid in debugging.

Update the error message to include asset details:

      if (!cw20Price || !nativePrice) {
        throw new GeneralException(
-         new Error('Failed to compute redemption ratio'),
+         new Error(`Failed to compute redemption ratio for assets: ${JSON.stringify(cw20Asset)} and ${JSON.stringify(nativeAsset)}`),
        )
      }

68-70: Use a proper logging mechanism instead of console.error

Relying on console.error may not be suitable for production environments. It's better to use a dedicated logging library to manage log levels and outputs.

Replace console.error with a logging utility:

-     console.error('Error fetching prices:', error)
+     Logger.error('Error fetching prices:', error)

Ensure that Logger is properly imported and configured.


209-211: Consistent error handling with logging

Similar to the previous comment, replace console.error with a logging utility for consistency and better log management.

-     console.error('Error fetching lending rates:', error)
+     Logger.error('Error fetching lending rates:', error)
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 7bc68a8 and ee7c941.

📒 Files selected for processing (12)
  • packages/sdk-ts/src/client/wasm/index.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/helper.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/index.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/queries/QueryGetPrices.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/queries/QueryLendingRates.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/queries/index.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/service.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/transformer.ts (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/types.ts (1 hunks)
  • packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts (1 hunks)
  • packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts (1 hunks)
  • packages/sdk-ts/src/core/modules/wasm/index.ts (2 hunks)
✅ Files skipped from review due to trivial changes (1)
  • packages/sdk-ts/src/client/wasm/neptune/index.ts
🧰 Additional context used
🪛 Biome
packages/sdk-ts/src/client/wasm/neptune/transformer.ts

[error] 5-27: Avoid classes that contain only static members.

Prefer using simple functions instead of classes with only static members.

(lint/complexity/noStaticOnlyClass)

packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts

[error] 8-8: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 10-10: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 16-16: Shouldn't redeclare 'ExecArgNeptuneDeposit'. Consider to delete it or rename it.

'ExecArgNeptuneDeposit' is defined here:

(lint/suspicious/noRedeclare)

packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts

[error] 25-25: Shouldn't redeclare 'ExecArgNeptuneWithdraw'. Consider to delete it or rename it.

'ExecArgNeptuneWithdraw' is defined here:

(lint/suspicious/noRedeclare)

🔇 Additional comments (17)
packages/sdk-ts/src/client/wasm/neptune/queries/index.ts (1)

1-2: LGTM! Verify referenced query implementations.

The export statements follow the correct ES6 module syntax and align with the module's purpose of providing query functionalities for prices and lending rates.

Let's verify the existence and implementation of the referenced query classes:

✅ Verification successful

Let me try a different approach to verify the files since the previous path was incorrect.


Export statements are correctly implemented and verified

The verification confirms that:

  • Both TypeScript source files exist at the correct paths
  • Both classes are properly implemented with the required toPayload() method
  • Classes extend BaseWasmQuery and implement the expected query functionality
  • File paths in the exports match the actual file locations
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence of source files and their implementations
# Expected results:
# 1. Both TypeScript source files should exist
# 2. Both classes should implement toPayload method as mentioned in the summary

# Check if the source TypeScript files exist
echo "Checking source files..."
fd -e ts "QueryGetPrices|QueryLendingRates" src/client/wasm/neptune/queries

# Verify QueryGetPrices implementation
echo -e "\nChecking QueryGetPrices implementation..."
ast-grep --pattern 'class QueryGetPrices {
  $$$
  toPayload() {
    $$$
  }
  $$$
}'

# Verify QueryGetAllLendingRates implementation
echo -e "\nChecking QueryGetAllLendingRates implementation..."
ast-grep --pattern 'class QueryGetAllLendingRates {
  $$$
  toPayload() {
    $$$
  }
  $$$
}'

Length of output: 656


Script:

#!/bin/bash
# First, let's find the correct path by searching from the repository root
echo "Finding the correct path for query files..."
fd -t f -e ts "QueryGetPrices|QueryLendingRates"

# Let's also check the directory structure to understand the layout
echo -e "\nChecking directory structure..."
fd -t d "neptune"

# Search for class implementations regardless of path
echo -e "\nSearching for QueryGetPrices class..."
ast-grep --pattern 'class QueryGetPrices'

echo -e "\nSearching for QueryGetAllLendingRates class..."
ast-grep --pattern 'class QueryGetAllLendingRates'

# As a fallback, let's also use ripgrep to search for these classes
echo -e "\nFallback search with ripgrep..."
rg "class (QueryGetPrices|QueryGetAllLendingRates)" -A 5

Length of output: 2174

packages/sdk-ts/src/client/wasm/index.ts (2)

3-3: LGTM! Clean integration of the Neptune module.

The export statement follows the established pattern and maintains consistency with other exports.


3-3: Verify Neptune module structure and dependencies.

Let's ensure the Neptune module is properly structured and doesn't introduce circular dependencies.

✅ Verification successful

Let me gather more information about the Neptune module's structure and exports.


Neptune module structure is well-organized with no circular dependencies

The Neptune module follows a clean architecture with:

  • Properly organized submodules (types, service, transformer, queries)
  • No circular dependencies detected
  • Clear separation of concerns with dedicated files for different functionalities
  • Well-structured exports through the main index.ts
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify Neptune module structure and dependencies

# Check if the Neptune module exists
echo "Checking Neptune module existence..."
if ! fd -p "packages/sdk-ts/src/client/wasm/neptune/index.(ts|js)$"; then
    echo "Warning: Neptune module not found at expected path"
fi

# Check for circular dependencies in Neptune module
echo "Checking for circular dependencies..."
rg -l "from.*wasm/index" "packages/sdk-ts/src/client/wasm/neptune"

# Verify Neptune module exports
echo "Verifying Neptune module exports..."
ast-grep --pattern 'export { $$ }' "packages/sdk-ts/src/client/wasm/neptune/index.ts"

Length of output: 515


Script:

#!/bin/bash
# Check the content of Neptune module's index file
echo "Content of Neptune module's index file:"
cat packages/sdk-ts/src/client/wasm/neptune/index.ts

# Check for any imports in Neptune module
echo -e "\nImports in Neptune module:"
rg "import.*from" packages/sdk-ts/src/client/wasm/neptune/index.ts

# Check for files in Neptune directory
echo -e "\nFiles in Neptune directory:"
fd . packages/sdk-ts/src/client/wasm/neptune/

# Check for exports in all Neptune module files
echo -e "\nExports in Neptune module files:"
rg "export" packages/sdk-ts/src/client/wasm/neptune/

Length of output: 3450

packages/sdk-ts/src/client/wasm/neptune/helper.ts (2)

1-1: LGTM! Clean import statement following ESM best practices.


3-3: 🛠️ Refactor suggestion

Add input validation to prevent runtime errors

The function should validate the input parameter to ensure it's not null/undefined and has the expected structure.

 export function getDenom(assetInfo: AssetInfo): string | undefined {
+  if (!assetInfo) {
+    throw new Error('AssetInfo is required')
+  }
+
+  if (!('native_token' in assetInfo) && !('token' in assetInfo)) {
+    throw new Error('Invalid AssetInfo structure')
+  }

Let's verify how this function is being used in the codebase:

packages/sdk-ts/src/client/wasm/neptune/queries/QueryGetPrices.ts (2)

1-3: LGTM! Well-structured imports

The imports are appropriate for the functionality and follow TypeScript ESM best practices with explicit .js extensions.


1-19: Verify Neptune contract integration

Since this is a critical price querying functionality, let's verify the contract integration.

✅ Verification successful

Let me try a different search strategy to verify the Neptune integration.


Let me search for the contract address constant and verify its configuration.


Based on the comprehensive analysis of the Neptune integration, I can now provide the final response:

Neptune contract integration is properly implemented

The verification shows that:

  • The price oracle contract address is correctly configured as a constant (NEPTUNE_PRICE_CONTRACT)
  • QueryGetPrices is properly integrated within the NeptuneService class
  • The service implementation includes proper error handling and response transformation
  • The integration is mainnet-only with appropriate network validation
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Check for Neptune contract address configuration
echo "Checking for contract address configuration..."
rg -l "neptune.*contract.*address" --type ts

# Check for service integration
echo "Checking for QueryGetPrices usage in NeptuneService..."
ast-grep --pattern 'class NeptuneService {
  $$$
  $price_query = new QueryGetPrices($$$)
  $$$
}'

Length of output: 369


Script:

#!/bin/bash
# Search for Neptune contract configuration with broader pattern
echo "Checking Neptune contract configuration..."
rg -l "neptune.*contract" --type ts

# Search for Neptune service class definition
echo "Checking Neptune service implementation..."
ast-grep --pattern 'class NeptuneService {
  $$$
}'

# Search for QueryGetPrices usage with broader pattern
echo "Checking QueryGetPrices usage..."
rg "QueryGetPrices" -A 5 --type ts

Length of output: 23187


Script:

#!/bin/bash
# Search for Neptune contract address constant
echo "Checking Neptune price contract address constant..."
rg "NEPTUNE_PRICE_CONTRACT" --type ts -A 2

# Search for any Neptune-related constants
echo "Checking other Neptune contract constants..."
rg "NEPTUNE_.*_CONTRACT" --type ts

Length of output: 2085

packages/sdk-ts/src/client/wasm/neptune/types.ts (1)

18-19: Consider environment-based contract configuration.

Hardcoding contract addresses can be problematic when dealing with different environments (testnet/mainnet). Consider:

  1. Moving this to a configuration file
  2. Making it environment-dependent
  3. Adding runtime validation for the address format

Let's check if this contract address is used consistently:

packages/sdk-ts/src/client/wasm/neptune/queries/QueryLendingRates.ts (1)

1-3: LGTM! Clean and focused imports.

The imports are well-organized, using explicit file extensions and proper relative paths.

packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts (2)

7-11: Verify if Params and Data interfaces should contain properties

The empty interfaces Params and Data might need properties to properly type the deposit operation parameters and data. If they're intentionally empty, consider adding documentation explaining why.

✅ Verification successful

Based on the search results, I can now provide a final response since I have enough context:

Empty interfaces are intentional for Neptune deposit operation

The empty Params and Data interfaces in ExecArgNeptuneDeposit.ts are correct by design. This is evidenced by:

  1. The implementation of toData() method explicitly returns an empty object {}
  2. The Neptune deposit operation doesn't require any additional parameters, unlike other exec args implementations that require specific parameters
  3. Similar pattern exists in ExecArgDepositTokens.ts which also has an empty Params interface
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for similar execution argument implementations to understand the pattern
ast-grep --pattern 'interface Params {
  $$$
}'

# Look for usage patterns of these interfaces
rg -A 5 "ExecArgNeptuneDeposit.Params" 
rg -A 5 "ExecArgNeptuneDeposit.Data"

Length of output: 93340

🧰 Tools
🪛 Biome

[error] 8-8: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


[error] 10-10: An empty interface is equivalent to {}.

Safe fix: Use a type alias instead.

(lint/suspicious/noEmptyInterface)


30-32: Verify if 'lend' is the correct action for deposit operation

The toExecData method uses 'lend' as the action string, but the class name suggests this is for deposits. This might indicate a potential mismatch or copy-paste error.

✅ Verification successful

Let me gather more information about the Neptune contract implementation to verify if 'lend' is indeed the correct action for deposits.


Let me check one more thing to verify if there's any Neptune contract documentation or implementation details that could confirm the correct action name.


Based on the gathered information, I can now provide the final response:

'lend' is the correct action for Neptune deposit operation

The Neptune contract implementation consistently uses 'lend' as the action for deposit operations, as evidenced by:

  • The service implementation in packages/sdk-ts/src/client/wasm/neptune/service.ts uses ExecArgNeptuneDeposit with the 'lend' action for deposit functionality
  • This aligns with the financial nature of the Neptune protocol where deposits are effectively lending assets to the protocol
  • The corresponding withdraw operation uses 'send' action, forming a coherent lending protocol interface
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other Neptune-related execution argument implementations
rg "dataToExecData\('.*'" --type ts

# Look for Neptune contract documentation or tests
fd -e md -e ts -e js -H neptune

Length of output: 2462


Script:

#!/bin/bash
# Look for Neptune contract implementation or tests
ast-grep --pattern 'class ExecArgNeptuneDeposit {
  $$$
}'

# Search for Neptune-related tests
rg -A 5 "NeptuneDeposit" --type ts

Length of output: 4762


Script:

#!/bin/bash
# Look for Neptune contract documentation or implementation
rg -A 5 "neptune" --type-add 'doc:*.{md,mdx,txt}' --type doc

# Search for any Neptune-related constants or configurations
rg "NEPTUNE" --type ts -A 3

Length of output: 3043

packages/sdk-ts/src/client/wasm/neptune/transformer.ts (1)

1-3: LGTM! Well-organized imports.

The imports are properly organized and follow good practices with explicit file extensions.

packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts (3)

9-20: Verify consistent namespace pattern usage across Neptune services

The namespace and interface definitions look good. Let's verify this pattern is consistently used across other Neptune service files.

✅ Verification successful

Namespace pattern is consistent across Neptune service files

The namespace pattern is consistently implemented across both Neptune-related files:

  • ExecArgNeptuneWithdraw and ExecArgNeptuneDeposit both follow the same pattern
  • Both declare their namespaces with Params and Data interfaces
  • Both extend ExecArgBase with proper generic type parameters
  • Both implement the required contract execution argument structure
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for consistent namespace pattern usage in Neptune-related files
# Expected: Similar namespace declarations in other Neptune files

# Search for Neptune-related files and their namespace declarations
fd -e ts Neptune --exec ast-grep --pattern 'declare namespace ExecArgNeptune$_'

Length of output: 81


Script:

#!/bin/bash
# Let's try a different approach to find Neptune-related files and their contents
# First, find all Neptune-related TypeScript files
fd -e ts Neptune

# Then, let's examine their contents to check namespace patterns
fd -e ts Neptune --exec cat

Length of output: 1963


47-49: Verify 'send' action type usage

The toExecData method uses 'send' as the action type. Let's verify this is the correct action type for Neptune withdrawals.

#!/bin/bash
# Description: Check for consistent action type usage
# Expected: Find other instances of 'send' action type usage

# Search for dataToExecData usage with 'send' action
ast-grep --pattern 'dataToExecData($_, $_)'

35-45: ⚠️ Potential issue

Verify empty redeem message structure

The innerMsg contains an empty redeem object. This seems unusual and might be missing required parameters for the redeem operation.

✅ Verification successful

Let me gather more specific information about redeem messages.


Let me check the Neptune contract interface by looking at both deposit and withdraw implementations.


Let me check one more thing to verify if there are any other similar withdraw or redeem implementations in the codebase that might provide insights into the message structure.


Based on the analysis of the codebase, I can now provide the final response:

Empty redeem message structure is correct for Neptune withdraw

The empty redeem object { redeem: {} } in the Neptune withdraw implementation is correct. This is evidenced by:

  1. The contract interface design follows a simple redeem pattern where no additional parameters are needed - the amount and contract details are passed separately in the outer message structure
  2. The companion deposit implementation (ExecArgNeptuneDeposit) also uses a minimal message structure
  3. The class properly handles all required parameters (amount and contract) in the outer message structure
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Search for other redeem message implementations
# Expected: Find similar redeem message structures for comparison

# Search for redeem message structures
rg -A 5 'redeem.*:.*{' 

Length of output: 4387


Script:

#!/bin/bash
# Search for redeem message structures in the codebase
rg -A 5 '"redeem".*{.*}' --type ts

# Search for Neptune related files to understand the contract interface
fd -e ts neptune

Length of output: 310


Script:

#!/bin/bash
# Check Neptune deposit and withdraw implementations
cat packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts
cat packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts

# Search for any Neptune related tests that might show the expected message structure
fd -e spec.ts -e test.ts neptune

Length of output: 1961


Script:

#!/bin/bash
# Search for similar withdraw implementations
rg -l "withdraw.*{" --type ts

# Search for any base classes or interfaces that might define the message structure
ast-grep --pattern 'interface $_ {
  redeem: $_
}'

Length of output: 170

packages/sdk-ts/src/core/modules/wasm/index.ts (2)

9-9: LGTM! Clean and consistent imports.

The new Neptune-related imports are well-organized within the exec-args group and follow the established naming and path conventions.

Also applies to: 11-11


45-45: Verify the Neptune execution argument implementations.

Let's ensure the new Neptune execution argument classes are properly implemented with the expected deposit and withdrawal functionality.

Also applies to: 47-47

✅ Verification successful

Neptune execution argument implementations are properly implemented

The verification confirms that both Neptune execution argument classes are correctly implemented:

  1. ExecArgNeptuneDeposit:

    • Properly extends ExecArgBase
    • Implements lend operation with empty params/data as required
    • Used in Neptune service for deposit operations
  2. ExecArgNeptuneWithdraw:

    • Properly extends ExecArgBase
    • Implements send operation with required params (amount, contract)
    • Correctly encodes redeem message for withdrawals
    • Used in Neptune service for withdrawal operations

Both implementations are integrated into the Neptune service and properly exported through the WASM module index.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the existence and implementation of Neptune execution argument files

# Check if the files exist and show their content
echo "Checking ExecArgNeptuneDeposit implementation:"
fd --type f "ExecArgNeptuneDeposit.ts" --exec cat {}

echo -e "\nChecking ExecArgNeptuneWithdraw implementation:"
fd --type f "ExecArgNeptuneWithdraw.ts" --exec cat {}

# Look for any usage examples or tests
echo -e "\nChecking for tests:"
fd --type f ".*test.*" | rg -l "ExecArgNeptune(Deposit|Withdraw)"

Length of output: 2215


Script:

#!/bin/bash
# Let's verify the Neptune contract integration tests and usage
# to ensure the deposit and withdraw implementations are properly tested

# Check for Neptune-related tests
echo "Checking for Neptune-related tests:"
rg -A 10 "ExecArgNeptuneDeposit|ExecArgNeptuneWithdraw" --type ts

# Check the wasm index file to understand how these classes are exported and used
echo -e "\nChecking wasm index file:"
fd "index.ts" --type f --exec rg -l "ExecArgNeptune" {} | xargs cat

# Look for any Neptune-related contract messages or schemas
echo -e "\nChecking for Neptune contract messages:"
rg "neptune|lend|redeem" --type ts -A 5

Length of output: 28734

Comment on lines +6 to +15
static contractPricesResponseToPrices(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; price: string }> {
const data = JSON.parse(toUtf8(response.data)) as PriceResponse

return data.map(([assetInfo, priceInfo]) => ({
assetInfo,
price: priceInfo.price,
}))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for JSON parsing and data validation.

The current implementation could throw errors in several scenarios:

  1. Invalid JSON data
  2. Unexpected data structure
  3. Missing or null values

Consider implementing error handling:

 static contractPricesResponseToPrices(
   response: WasmContractQueryResponse,
 ): Array<{ assetInfo: AssetInfo; price: string }> {
-  const data = JSON.parse(toUtf8(response.data)) as PriceResponse
+  try {
+    const data = JSON.parse(toUtf8(response.data)) as PriceResponse
+    if (!Array.isArray(data)) {
+      throw new Error('Invalid price response format')
+    }
 
-  return data.map(([assetInfo, priceInfo]) => ({
-    assetInfo,
-    price: priceInfo.price,
-  }))
+    return data.map(([assetInfo, priceInfo]) => {
+      if (!assetInfo || !priceInfo?.price) {
+        throw new Error('Invalid price data structure')
+      }
+      return {
+        assetInfo,
+        price: priceInfo.price,
+      }
+    })
+  } catch (error) {
+    throw new Error(`Failed to transform price response: ${error.message}`)
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static contractPricesResponseToPrices(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; price: string }> {
const data = JSON.parse(toUtf8(response.data)) as PriceResponse
return data.map(([assetInfo, priceInfo]) => ({
assetInfo,
price: priceInfo.price,
}))
}
static contractPricesResponseToPrices(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; price: string }> {
try {
const data = JSON.parse(toUtf8(response.data)) as PriceResponse
if (!Array.isArray(data)) {
throw new Error('Invalid price response format')
}
return data.map(([assetInfo, priceInfo]) => {
if (!assetInfo || !priceInfo?.price) {
throw new Error('Invalid price data structure')
}
return {
assetInfo,
price: priceInfo.price,
}
})
} catch (error) {
throw new Error(`Failed to transform price response: ${error.message}`)
}
}

Comment on lines +17 to +26
static contractLendingRatesResponseToLendingRates(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; lendingRate: string }> {
const data = JSON.parse(toUtf8(response.data)) as LendingRateResponse

return data.map(([assetInfo, lendingRate]) => ({
assetInfo,
lendingRate,
}))
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add error handling for lending rates transformation.

Similar to the prices method, this implementation needs proper error handling.

Apply similar error handling improvements:

 static contractLendingRatesResponseToLendingRates(
   response: WasmContractQueryResponse,
 ): Array<{ assetInfo: AssetInfo; lendingRate: string }> {
-  const data = JSON.parse(toUtf8(response.data)) as LendingRateResponse
+  try {
+    const data = JSON.parse(toUtf8(response.data)) as LendingRateResponse
+    if (!Array.isArray(data)) {
+      throw new Error('Invalid lending rate response format')
+    }
 
-  return data.map(([assetInfo, lendingRate]) => ({
-    assetInfo,
-    lendingRate,
-  }))
+    return data.map(([assetInfo, lendingRate]) => {
+      if (!assetInfo || !lendingRate) {
+        throw new Error('Invalid lending rate data structure')
+      }
+      return {
+        assetInfo,
+        lendingRate,
+      }
+    })
+  } catch (error) {
+    throw new Error(`Failed to transform lending rate response: ${error.message}`)
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
static contractLendingRatesResponseToLendingRates(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; lendingRate: string }> {
const data = JSON.parse(toUtf8(response.data)) as LendingRateResponse
return data.map(([assetInfo, lendingRate]) => ({
assetInfo,
lendingRate,
}))
}
static contractLendingRatesResponseToLendingRates(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; lendingRate: string }> {
try {
const data = JSON.parse(toUtf8(response.data)) as LendingRateResponse
if (!Array.isArray(data)) {
throw new Error('Invalid lending rate response format')
}
return data.map(([assetInfo, lendingRate]) => {
if (!assetInfo || !lendingRate) {
throw new Error('Invalid lending rate data structure')
}
return {
assetInfo,
lendingRate,
}
})
} catch (error) {
throw new Error(`Failed to transform lending rate response: ${error.message}`)
}
}

Comment on lines +29 to +33
static fromJSON(
params: ExecArgNeptuneWithdraw.Params,
): ExecArgNeptuneWithdraw {
return new ExecArgNeptuneWithdraw(params)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for amount and contract

The fromJSON method should validate:

  1. Amount format and value (should be a valid numeric string)
  2. Contract address format (should be a valid address)

Consider adding validation:

 static fromJSON(
   params: ExecArgNeptuneWithdraw.Params,
 ): ExecArgNeptuneWithdraw {
+  if (!/^\d+$/.test(params.amount)) {
+    throw new Error('Invalid amount format')
+  }
+  if (!/^[a-zA-Z0-9]{32,}$/.test(params.contract)) {
+    throw new Error('Invalid contract address format')
+  }
   return new ExecArgNeptuneWithdraw(params)
 }

Committable suggestion skipped: line range outside the PR's diff.

Comment on lines +88 to +89
const [cw20Price] = prices
const [nativePrice] = prices.reverse()
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect extraction of prices due to array mutation

Using prices.reverse() mutates the prices array in place, which can lead to logical errors. This affects the assignment of cw20Price and nativePrice, potentially causing both variables to reference the same price.

Apply this diff to correctly extract the prices without mutating the array:

-    const [cw20Price] = prices
-    const [nativePrice] = prices.reverse()
+    const [cw20Price, nativePrice] = prices
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const [cw20Price] = prices
const [nativePrice] = prices.reverse()
const [cw20Price, nativePrice] = prices

Comment on lines +107 to +108
return amountCW20 * redemptionRatio
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Validate redemptionRatio in calculateBankAmount

While multiplying by zero doesn't cause a runtime error, it's prudent to validate that redemptionRatio is a positive number to ensure logical correctness.

Consider adding a check:

    calculateBankAmount(amountCW20: number, redemptionRatio: number): number {
+     if (redemptionRatio <= 0) {
+       throw new Error('Redemption ratio must be a positive number')
+     }
      return amountCW20 * redemptionRatio
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return amountCW20 * redemptionRatio
}
calculateBankAmount(amountCW20: number, redemptionRatio: number): number {
if (redemptionRatio <= 0) {
throw new Error('Redemption ratio must be a positive number')
}
return amountCW20 * redemptionRatio
}

Comment on lines +117 to +118
return amountBank / redemptionRatio
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Prevent division by zero in calculateCw20Amount

Dividing by zero will cause a runtime error. It's essential to check that redemptionRatio is not zero before performing the division.

Add a validation check for redemptionRatio:

    calculateCw20Amount(amountBank: number, redemptionRatio: number): number {
+     if (redemptionRatio === 0) {
+       throw new Error('Redemption ratio cannot be zero')
+     }
      return amountBank / redemptionRatio
    }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
return amountBank / redemptionRatio
}
calculateCw20Amount(amountBank: number, redemptionRatio: number): number {
if (redemptionRatio === 0) {
throw new Error('Redemption ratio cannot be zero')
}
return amountBank / redemptionRatio
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (4)
.gitbook/contracts/neptune-service.md (4)

13-19: Enhance initialization examples with error handling and configuration options.

Consider adding examples that demonstrate:

  • Error handling for network connectivity issues
  • Additional configuration options (if any)
  • How to initialize with different networks (testnet example)

49-67: Add validation and error handling for redemption ratio.

Consider adding:

  • Input validation examples
  • Error handling for invalid token addresses
  • Example of what constitutes a valid/invalid redemption ratio

133-140: Document APY calculation details.

The APY calculation example should include:

  • The mathematical formula being used
  • Valid ranges for input values
  • How to handle edge cases (very high APR, extreme compounding frequencies)

115-115: Add missing comma for better readability.

Add a comma after "USDT" in the comment:

-- Get the lending rate for USDT for example
++ Get the lending rate for USDT, for example
🧰 Tools
🪛 LanguageTool

[uncategorized] ~115-~115: A comma might be missing here.
Context: ...enomination - Get the lending rate for USDT for example ```ts const denom = 'peggy...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between ee7c941 and 2d0ce91.

📒 Files selected for processing (4)
  • .gitbook/SUMMARY.md (1 hunks)
  • .gitbook/contracts/README.md (2 hunks)
  • .gitbook/contracts/neptune-service.md (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/service.ts (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • .gitbook/contracts/README.md
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/sdk-ts/src/client/wasm/neptune/service.ts
🧰 Additional context used
🪛 LanguageTool
.gitbook/SUMMARY.md

[duplication] ~62-~62: Possible typo: you repeated a word
Context: ...os/ledger-through-keplr-wallet.md) - Ethereum - [Ethereum Ledger](transactions/ethereum-ledger.md...

(ENGLISH_WORD_REPEAT_RULE)

.gitbook/contracts/neptune-service.md

[uncategorized] ~115-~115: A comma might be missing here.
Context: ...enomination - Get the lending rate for USDT for example ```ts const denom = 'peggy...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)


[style] ~178-~178: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...itMsg, }) console.log(txHash) ``` ### Create and Broadcast a Withdraw Message - Cre...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

Comment on lines +73 to +99
```ts
const amountCW20 = 1000 // Amount in nUSDT
const redemptionRatio = 0.95 // Obtained from fetchRedemptionRatio

const bankAmount = neptuneService.calculateBankAmount(
amountCW20,
redemptionRatio,
)

console.log(`Bank USDT Amount: ${bankAmount}`)
```

### Convert Bank USDT to CW20 nUSDT

- Calculate the amount in CW20 nUSDT from a given amount of bank USDT using the redemption ratio.

```ts
const amountBank = 950 // Amount in USDT
const redemptionRatio = 0.95 // Obtained from fetchRedemptionRatio

const cw20Amount = neptuneService.calculateCw20Amount(
amountBank,
redemptionRatio,
)

console.log(`CW20 nUSDT Amount: ${cw20Amount}`)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Document precision handling and rounding behavior.

The amount conversion examples should address:

  • How to handle decimal precision
  • Potential rounding issues
  • Best practices for amount calculations

Consider adding a note about precision:

// Note: Always use BigNumber for amount calculations to avoid precision issues
const amountCW20 = new BigNumberInBase('1000')

Comment on lines +106 to +127
const lendingRates = await neptuneService.getLendingRates({
limit: 10, // Optional: number of rates to fetch
})

console.log(lendingRates)
```

### Fetch Lending Rate by Denomination

- Get the lending rate for USDT for example

```ts
const denom = 'peggy0xdAC17F958D2ee523a2206206994597C13D831ec7' // USDT denom

const lendingRate = await neptuneService.getLendingRateByDenom({ denom })

if (lendingRate) {
console.log(`Lending Rate for USDT: ${lendingRate}`)
} else {
console.log('Lending Rate for USDT not found')
}
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Enhance lending rate documentation.

Please add:

  • Documentation about the rate format (percentage vs decimal)
  • Explanation of the rate update frequency
  • More comprehensive error handling examples
🧰 Tools
🪛 LanguageTool

[uncategorized] ~115-~115: A comma might be missing here.
Context: ...enomination - Get the lending rate for USDT for example ```ts const denom = 'peggy...

(AI_EN_LECTOR_MISSING_PUNCTUATION_COMMA)

Comment on lines +146 to +211
```ts
import {
MsgBroadcasterWithPk,
MsgExecuteContractCompat,
} from '@injectivelabs/sdk-ts'
import { BigNumberInBase } from '@injectivelabs/utils'

const privateKey = '0x...'
const injectiveAddress = 'inj1...'
const denom = 'peggy0xdAC17F958D2ee523a2206206994597C13D831ec7' // USDT denom

const amountInUsdt = '100'

// Convert the amount to the smallest unit (USDT has 6 decimals)
const amount = new BigNumberInBase(amountInUsdt).toWei(6).toFixed()

const depositMsg = neptuneService.createDepositMsg({
denom,
amount,
sender: injectiveAddress,
})

const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.MainnetSentry,
}).broadcast({
msgs: depositMsg,
})

console.log(txHash)
```

### Create and Broadcast a Withdraw Message

- Create a message to withdraw USDT from the Neptune USDT lending market and broadcast it to the network

```ts
import {
Network,
MsgBroadcasterWithPk,
MsgExecuteContractCompat,
} from '@injectivelabs/sdk-ts'
import { BigNumberInBase } from '@injectivelabs/utils'

const privateKey = '0x...' // Your private key
const injectiveAddress = 'inj1...' // Your Injective address

// Define the amount to withdraw (e.g., 100 nUSDT)
const amountInNusdt = '100'

// Convert the amount to the smallest unit (nUSDT has 6 decimals)
const amount = new BigNumberInBase(amountInNusdt).toWei(6).toFixed()

const withdrawMsg = neptuneService.createWithdrawMsg({
amount,
sender: injectiveAddress,
})

const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.MainnetSentry,
}).broadcast({
msgs: withdrawMsg,
})

console.log(`Transaction Hash: ${txHash}`)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Improve security and transaction handling in examples.

Security and transaction handling improvements needed:

  1. Never include actual private keys in code, even as examples
  2. Add gas estimation examples
  3. Show how to wait for transaction confirmation
  4. Add error handling for failed transactions

Example improvement:

// Use environment variables for sensitive data
const privateKey = process.env.PRIVATE_KEY
if (!privateKey) {
  throw new Error('Private key not found in environment')
}

// Add gas estimation
const gas = await neptuneService.estimateGas(depositMsg)

// Add transaction confirmation
const txResponse = await broadcaster.broadcast({
  msgs: depositMsg,
  gasLimit: gas,
})

// Wait for confirmation
const receipt = await neptuneService.waitForTransaction(txResponse.txHash)
🧰 Tools
🪛 LanguageTool

[style] ~178-~178: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...itMsg, }) console.log(txHash) ``` ### Create and Broadcast a Withdraw Message - Cre...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

Comment on lines +7 to +15
import { getDenom } from './helper.js'
import { ChainGrpcWasmApi } from '../../chain/index.js'
import { QueryGetPrices, QueryGetAllLendingRates } from './queries/index.js'
import { NeptuneQueryTransformer } from './transformer.js'
import ExecArgNeptuneDeposit from '../../../core/modules/wasm/exec-args/ExecArgNeptuneDeposit.js'
import ExecArgNeptuneWithdraw from '../../../core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.js'
import MsgExecuteContractCompat from '../../../core/modules/wasm/msgs/MsgExecuteContractCompat.js'
import { GeneralException } from '@injectivelabs/exceptions'
import { NEPTUNE_PRICE_CONTRACT } from './index.js'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets sort these by length and move import { GeneralException } from '@injectivelabs/exceptions' to the top

toPayload() {
const payload = {
get_all_lending_rates: {
...(this.params.limit !== undefined ? { limit: this.params.limit } : {}),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets change this to:

...(this.params.limit ? { limit: this.params.limit } : {}),

Comment on lines +41 to +43
amount: params.amount,
contract: params.contract,
msg: encodedMsg,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets sort this by length

export class NeptuneQueryTransformer {
static contractPricesResponseToPrices(
response: WasmContractQueryResponse,
): Array<{ assetInfo: AssetInfo; price: string }> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets use [] instead of Array, same for the rest:

{ assetInfo: AssetInfo; price: string }[]

@ThomasRalee ThomasRalee merged commit ce3ab99 into dev Nov 18, 2024
5 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Outside diff range and nitpick comments (2)
.gitbook/contracts/neptune-service.md (1)

17-18: Document network configuration options

The example hardcodes MainnetSentry. Consider documenting:

  • Available network options (testnet, devnet)
  • Environment-based network selection
  • Network configuration best practices
// Example with environment-based network selection
const network = process.env.NETWORK === 'testnet' 
  ? Network.TestnetSentry 
  : Network.MainnetSentry
const neptuneService = new NeptuneService(network)
packages/sdk-ts/src/client/wasm/neptune/service.ts (1)

22-25: Consider environment-based contract configuration

The contract addresses are hardcoded as constants. Consider moving these to a configuration file or environment variables to facilitate easier environment switching and maintenance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Reviewing files that changed from the base of the PR and between 2d0ce91 and a563e21.

📒 Files selected for processing (4)
  • .gitbook/SUMMARY.md (1 hunks)
  • .gitbook/contracts/README.md (2 hunks)
  • .gitbook/contracts/neptune-service.md (1 hunks)
  • packages/sdk-ts/src/client/wasm/neptune/service.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • .gitbook/contracts/README.md
🧰 Additional context used
🪛 LanguageTool
.gitbook/SUMMARY.md

[duplication] ~62-~62: Possible typo: you repeated a word
Context: ...os/ledger-through-keplr-wallet.md) - Ethereum - [Ethereum Ledger](transactions/ethereum-ledger.md...

(ENGLISH_WORD_REPEAT_RULE)

.gitbook/contracts/neptune-service.md

[style] ~177-~177: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...itMsg, }) console.log(txHash) ``` ### Create and Broadcast a Withdraw Message - Cre...

(ENGLISH_WORD_REPEAT_BEGINNING_RULE)

🔇 Additional comments (4)
.gitbook/SUMMARY.md (1)

87-88: LGTM! Neptune Service documentation entry added correctly.

The new "Neptune Service" entry is properly placed under the "Contracts" section, maintaining the document's hierarchical structure.

packages/sdk-ts/src/client/wasm/neptune/service.ts (3)

36-47: LGTM! Well-structured initialization with proper network validation

The constructor is well-documented and includes appropriate network validation.


88-89: Reiterating previous comment about array mutation


106-108: Reiterating previous comments about redemption ratio validation

Also applies to: 116-118

Comment on lines +3 to +99
- [Getting Started](README.md)
- [Technical Concepts](readme/technical-concepts.md)
- [Application Concepts](readme/application-concepts.md)
- [Assets](readme/assets/README.md)
- [Creating Tokens](readme/assets/creating-tokens.md)
- [Denom Client (deprecated)](readme/assets/denom-client.md)
- [Injective Lists](readme/assets/injective-list.md)
- [Networks](readme/networks.md)
- [CosmJs Support](readme/getting-started-cosmjs.md)
- [Running examples](readme/running-examples.md)
- [Wallet](wallet/README.md)
- [Accounts](wallet/wallet-accounts.md)
- [Wallet Connections](wallet/wallet-connections.md)
- [Wallet Strategy](wallet/wallet-wallet-strategy.md)
- [Offchain (Arbitrary) Data](wallet/offchain-arbitrary-data.md)
- [Querying](querying/README.md)
- [Indexer](querying/querying-api/README.md)
- [Account](querying/querying-api/querying-indexer-account.md)
- [Auction](querying/querying-api/querying-indexer-auction.md)
- [Derivatives](querying/querying-api/querying-indexer-derivatives.md)
- [Explorer](querying/querying-api/querying-indexer-explorer.md)
- [Insurance Funds](querying/querying-api/querying-indexer-insurance-funds.md)
- [Markets](querying/querying-api/querying-indexer-markets.md)
- [Leaderboard](querying/querying-api/querying-indexer-leaderboard.md)
- [Mito](querying/querying-api/querying-indexer-mito.md)
- [Oracle](querying/querying-api/querying-indexer-oracle.md)
- [Portfolio](querying/querying-api/querying-indexer-portfolio.md)
- [Spot](querying/querying-api/querying-indexer-spot.md)
- [Web3Gw Transactions](querying/querying-api/querying-indexer-transaction.md)
- [Streaming](querying/querying-api/streaming/README.md)
- [Account](querying/querying-api/streaming/streaming-indexer-account.md)
- [Auction](querying/querying-api/streaming/streaming-indexer-auction.md)
- [Derivatives](querying/querying-api/streaming/streaming-indexer-derivatives.md)
- [Oracle](querying/querying-api/streaming/streaming-indexer-oracle.md)
- [Portfolio](querying/querying-api/streaming/streaming-indexer-portfolio.md)
- [Spot](querying/querying-api/streaming/streaming-indexer-spot.md)
- [Explorer](querying/querying-api/streaming/streaming-indexer-explorer.md)
- [Chain](querying/querying-chain/README.md)
- [Auction](querying/querying-chain/querying-chain-auction-module.md)
- [Auth](querying/querying-chain/querying-chain-auth-module.md)
- [Bank](querying/querying-chain/querying-chain-bank-module.md)
- [Distribution](querying/querying-chain/querying-chain-distribution.md)
- [Exchange](querying/querying-chain/querying-chain-exchange.md)
- [Governance](querying/querying-chain/querying-chain-governance.md)
- [IBC](querying/querying-chain/querying-chain-ibc.md)
- [Mint](querying/querying-chain/querying-chain-mint.md)
- [Insurance Funds](querying/querying-chain/querying-chain-insurance-funds.md)
- [Oracle](querying/querying-chain/querying-chain-oracle.md)
- [Peggy](querying/querying-chain/querying-chain-peggy.md)
- [Permissions](querying/querying-chain/querying-chain-permissions.md)
- [Staking](querying/querying-chain/querying-chain-staking.md)
- [Tendermint](querying/querying-chain/querying-chain-tendermint.md)
- [Wasm](querying/querying-chain/querying-chain-wasm.md)
- [WasmX](querying/querying-chain/querying-chain-wasmx.md)
- [Token Factory](querying/querying-chain/token-factory.md)
- [Ethereum (GraphQL)](querying/querying-ethereum.md)
- [Transactions](transactions/README.md)
- [Cosmos](transactions/transactions-cosmos/README.md)
- [Ledger through Keplr Wallet](transactions/transactions-cosmos/ledger-through-keplr-wallet.md)
- [Ethereum](transactions/ethereum.md)
- [Ethereum Ledger](transactions/ethereum-ledger.md)
- [MsgBroadcaster](transactions/msgbroadcaster.md)
- [Private Key](transactions/private-key.md)
- [Web3 Gateway](transactions/web3-gateway.md)
- [Core Modules](core-modules/README.md)
- [Auction](core-modules/auction.md)
- [AuthZ](core-modules/authz.md)
- [Bank](core-modules/bank.md)
- [Distribution](core-modules/distribution.md)
- [Exchange](core-modules/exchange.md)
- [Feegrant](core-modules/feegrant.md)
- [Governance](core-modules/governance.md)
- [IBC](core-modules/ibc.md)
- [Insurance](core-modules/insurance.md)
- [Peggy](core-modules/peggy.md)
- [Permissions](core-modules/permissions.md)
- [Staking](core-modules/staking.md)
- [Tokenfactory](core-modules/token-factory.md)
- [Wasm](core-modules/wasm.md)
- [Bridge](bridge/README.md)
- [Ethereum](bridge/ethereum.md)
- [IBC](bridge/ibc.md)
- [Wormhole](bridge/wormhole.md)
- [Contracts](contracts/README.md)
- [Injective Name Service](contracts/injective-name-service.md)
- [Neptune Service](contracts/neptune-service.md)
- [Building dApps](building-dapps/README.md)
- [Configuring Nuxt](building-dapps/configuring-nuxt.md)
- [Configuring React](building-dapps/configuring-react.md)
- [dApps Examples](building-dapps/dapps-examples/README.md)
- [Smart Contract](building-dapps/smart-contract.md)
- [DEX](building-dapps/dex.md)
- [Bridge](building-dapps/bridge.md)
- [Simple HTML example with Webpack](building-dapps/dapps-examples/simple-html-example-with-webpack.md)
- [Calculations](calculations/README.md)
- [Min Price Tick Size](calculations/min-price-tick-size.md)
- [Min Quantity Tick Size](calculations/min-quantity-tick-size.md)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codebase verification

Missing documentation file for Neptune Service

The Neptune Service documentation file (contracts/neptune-service.md) referenced in the SUMMARY.md does not exist in the repository, although the feature appears to be implemented based on the presence of Neptune-related TypeScript files in the SDK.

  • The documentation file needs to be created at contracts/neptune-service.md to match the table of contents structure
  • The file should document the Neptune Service functionality that's implemented in:
    • packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneDeposit.ts
    • packages/sdk-ts/src/core/modules/wasm/exec-args/ExecArgNeptuneWithdraw.ts
🔗 Analysis chain

Verify documentation completeness.

The table of contents structure is well-organized and consistently formatted. However, since this is a new service addition, please ensure that the referenced documentation file exists.


Let me verify if the path in the SUMMARY.md is correct and if the documentation exists in a different location.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that the Neptune Service documentation file exists
# and contains content

# Check if the file exists and is not empty
if [ -f "contracts/neptune-service.md" ]; then
    echo "Documentation file exists"
    if [ -s "contracts/neptune-service.md" ]; then
        echo "Documentation file contains content"
    else
        echo "Warning: Documentation file is empty"
    fi
else
    echo "Warning: Documentation file does not exist"
fi

Length of output: 136


Script:

#!/bin/bash
# Check the actual location of neptune-service.md
fd neptune-service.md

# Also check if there might be content in docs folder
fd -t f neptune

Length of output: 188

🧰 Tools
🪛 LanguageTool

[duplication] ~62-~62: Possible typo: you repeated a word
Context: ...os/ledger-through-keplr-wallet.md) - Ethereum - [Ethereum Ledger](transactions/ethereum-ledger.md...

(ENGLISH_WORD_REPEAT_RULE)

Comment on lines +25 to +42
```ts
const assets = [
{
native_token: {
denom: 'peggy0xdAC17F958D2ee523a2206206994597C13D831ec7', // peggy USDT bank denom
},
},
{
token: {
contract_addr: 'inj1cy9hes20vww2yr6crvs75gxy5hpycya2hmjg9s', // nUSDT contract address
},
},
]

const prices = await neptuneService.fetchPrices(assets)

console.log(prices)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Document price format and decimal handling

Please add documentation about:

  • The format of returned prices (e.g., decimal places)
  • Units used in price representation
  • Example of parsing and handling the returned price data
// Example price format documentation
const prices = await neptuneService.fetchPrices(assets)
// prices format: {
//   "peggy0xdAC17F958D2ee523a2206206994597C13D831ec7": "1000000" // 6 decimals
// }

// Parse price with proper decimals
const usdtPrice = new BigNumberInBase(prices[denom]).toBase(6)
console.log(`USDT Price: $${usdtPrice.toFixed()}`)

Comment on lines +61 to +67
const redemptionRatio = await neptuneService.fetchRedemptionRatio({
cw20Asset,
nativeAsset,
})

console.log(`Redemption Ratio: ${redemptionRatio}`)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add redemption ratio documentation and error handling

Please enhance the example with:

  • Explanation of ratio format (e.g., 0.95 means 1 nUSDT = 0.95 USDT)
  • Error handling for failed ratio fetches
  • Validation of returned values
try {
  const redemptionRatio = await neptuneService.fetchRedemptionRatio({
    cw20Asset,
    nativeAsset,
  })
  
  if (redemptionRatio <= 0 || redemptionRatio > 1) {
    throw new Error(`Invalid redemption ratio: ${redemptionRatio}`)
  }
  
  console.log(`1 nUSDT = ${redemptionRatio} USDT`)
} catch (error) {
  console.error('Failed to fetch redemption ratio:', error)
}

Comment on lines +134 to +139
const apr = 0.1 // 10% APR

const apy = neptuneService.calculateAPY(apr)

console.log(`APY (continuously compounded): ${(apy * 100).toFixed(2)}%`)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for APY calculation

The APY calculation example should include:

  • Input validation for the APR value
  • Handling of edge cases (negative rates, extremely high rates)
  • Clear documentation of the calculation formula
const apr = 0.1 // 10% APR

// Validate APR input
if (apr < 0 || apr > 1) {
  throw new Error('APR must be between 0 and 1')
}

const apy = neptuneService.calculateAPY(apr)
console.log(
  `APR: ${(apr * 100).toFixed(2)}% → APY: ${(apy * 100).toFixed(2)}%`
)

Comment on lines +161 to +175
const depositMsg = neptuneService.createDepositMsg({
denom,
amount,
sender: injectiveAddress,
})

const txHash = await new MsgBroadcasterWithPk({
privateKey,
network: Network.MainnetSentry,
}).broadcast({
msgs: depositMsg,
})

console.log(txHash)
```
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add gas estimation and transaction options

The deposit example should include:

  • Gas estimation
  • Transaction options (gas price, memo)
  • Transaction receipt handling
// Estimate gas
const gas = await neptuneService.estimateGas(depositMsg)

// Add transaction options
const txOptions = {
  msgs: depositMsg,
  gasLimit: gas,
  memo: 'Deposit to Neptune',
}

// Broadcast with receipt handling
const response = await broadcaster.broadcast(txOptions)
const receipt = await neptuneService.waitForTransaction(response.txHash)
console.log('Transaction confirmed:', receipt)

Comment on lines +128 to +148
createDepositMsg({
denom,
amount,
sender,
contractAddress = NEPTUNE_USDT_MARKET_CONTRACT,
}: {
denom: string
amount: string
sender: string
contractAddress?: string
}): MsgExecuteContractCompat {
return MsgExecuteContractCompat.fromJSON({
sender,
contractAddress,
execArgs: ExecArgNeptuneDeposit.fromJSON({}),
funds: {
denom,
amount,
},
})
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add input validation for message creation methods

Both createDepositMsg and createWithdrawMsg methods accept amounts as strings without validation. Consider:

  1. Validating amount format (numeric string)
  2. Checking for negative values
  3. Validating address format for contract addresses

Example validation:

private validateAmount(amount: string): void {
  if (!/^\d+$/.test(amount)) {
    throw new Error('Amount must be a numeric string')
  }
  if (BigInt(amount) <= 0n) {
    throw new Error('Amount must be positive')
  }
}

Also applies to: 157-176

Comment on lines +258 to +267
/**
* Calculates APY from APR and compounding frequency.
*
* @param apr - The annual percentage rate as a decimal (e.g., 0.10 for 10%)
* @param compoundingFrequency - Number of times interest is compounded per year
* @returns The annual percentage yield as a decimal
*/
calculateAPY(apr: number): number {
return Math.exp(apr) - 1
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix APY calculation implementation and documentation

Issues found:

  1. Documentation mentions an unused compoundingFrequency parameter
  2. The current implementation Math.exp(apr) - 1 doesn't follow the standard APY formula: (1 + r/n)^n - 1 where r is APR and n is compounding frequency
- calculateAPY(apr: number): number {
-   return Math.exp(apr) - 1
+ calculateAPY(apr: number, compoundingFrequency: number = 365): number {
+   return Math.pow(1 + apr / compoundingFrequency, compoundingFrequency) - 1
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
/**
* Calculates APY from APR and compounding frequency.
*
* @param apr - The annual percentage rate as a decimal (e.g., 0.10 for 10%)
* @param compoundingFrequency - Number of times interest is compounded per year
* @returns The annual percentage yield as a decimal
*/
calculateAPY(apr: number): number {
return Math.exp(apr) - 1
}
/**
* Calculates APY from APR and compounding frequency.
*
* @param apr - The annual percentage rate as a decimal (e.g., 0.10 for 10%)
* @param compoundingFrequency - Number of times interest is compounded per year
* @returns The annual percentage yield as a decimal
*/
calculateAPY(apr: number, compoundingFrequency: number = 365): number {
return Math.pow(1 + apr / compoundingFrequency, compoundingFrequency) - 1
}

Comment on lines +229 to +255
while (true) {
const lendingRates = await this.getLendingRates({
limit,
startAfter,
contractAddress,
})

if (lendingRates.length === 0) {
return
}

for (const { assetInfo, lendingRate } of lendingRates) {
const currentDenom = getDenom(assetInfo)

if (currentDenom === denom) {
return lendingRate
}
}

if (lendingRates.length < limit) {
return
}

const lastLendingRate = lendingRates[lendingRates.length - 1]

startAfter = lastLendingRate.assetInfo
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add safeguards against infinite loops in getLendingRateByDenom

The while loop could potentially run indefinitely if the contract consistently returns the same number of results. Consider:

  1. Adding a maximum iteration limit
  2. Implementing a timeout mechanism
+ const MAX_ITERATIONS = 100
+ let iterations = 0
  while (true) {
+   if (iterations++ >= MAX_ITERATIONS) {
+     throw new Error('Maximum iteration limit reached')
+   }
    const lendingRates = await this.getLendingRates({

Committable suggestion skipped: line range outside the PR's diff.

@ThomasRalee ThomasRalee deleted the feat/neptune-service branch November 28, 2024 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants