-
Notifications
You must be signed in to change notification settings - Fork 196
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
Feat/neptune service #515
Conversation
WalkthroughThe 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 Changes
Possibly related PRs
Suggested reviewers
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
packages/sdk-ts/src/client/wasm/neptune/service.tsOops! 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
bec0bc4
to
ee7c941
Compare
There was a problem hiding this 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 validationWhile the type guard pattern is correct, consider these improvements:
- The return type could be just
string
since both paths should always return a string- 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 experienceConsider 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 handlingThe 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:
- Add runtime validation for price string format
- 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 directstring
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 documentationWhile 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 typesTo improve error handling across the Neptune service, consider introducing custom error types (e.g.,
NeptuneWithdrawError
) that extend from a baseNeptuneError
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 documentationThere'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 messagesWhen 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 ofconsole.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 loggingSimilar 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
📒 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 theNeptuneService
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:
- Moving this to a configuration file
- Making it environment-dependent
- 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:
- The implementation of
toData()
method explicitly returns an empty object{}
- The Neptune deposit operation doesn't require any additional parameters, unlike other exec args implementations that require specific parameters
- Similar pattern exists in
ExecArgDepositTokens.ts
which also has an emptyParams
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
usesExecArgNeptuneDeposit
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
andExecArgNeptuneDeposit
both follow the same pattern- Both declare their namespaces with
Params
andData
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
:
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:
- 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
- The companion deposit implementation (
ExecArgNeptuneDeposit
) also uses a minimal message structure - 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:
-
ExecArgNeptuneDeposit
:- Properly extends
ExecArgBase
- Implements
lend
operation with empty params/data as required - Used in Neptune service for deposit operations
- Properly extends
-
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
- Properly extends
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
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, | ||
})) | ||
} |
There was a problem hiding this comment.
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:
- Invalid JSON data
- Unexpected data structure
- 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.
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}`) | |
} | |
} |
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, | ||
})) | ||
} |
There was a problem hiding this comment.
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.
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}`) | |
} | |
} |
static fromJSON( | ||
params: ExecArgNeptuneWithdraw.Params, | ||
): ExecArgNeptuneWithdraw { | ||
return new ExecArgNeptuneWithdraw(params) | ||
} |
There was a problem hiding this comment.
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:
- Amount format and value (should be a valid numeric string)
- 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.
const [cw20Price] = prices | ||
const [nativePrice] = prices.reverse() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
const [cw20Price] = prices | |
const [nativePrice] = prices.reverse() | |
const [cw20Price, nativePrice] = prices |
return amountCW20 * redemptionRatio | ||
} |
There was a problem hiding this comment.
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.
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 | |
} |
return amountBank / redemptionRatio | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
return amountBank / redemptionRatio | |
} | |
calculateCw20Amount(amountBank: number, redemptionRatio: number): number { | |
if (redemptionRatio === 0) { | |
throw new Error('Redemption ratio cannot be zero') | |
} | |
return amountBank / redemptionRatio | |
} |
There was a problem hiding this 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
📒 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)
```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}`) | ||
``` |
There was a problem hiding this comment.
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')
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') | ||
} | ||
``` |
There was a problem hiding this comment.
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)
```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}`) | ||
``` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Improve security and transaction handling in examples.
Security and transaction handling improvements needed:
- Never include actual private keys in code, even as examples
- Add gas estimation examples
- Show how to wait for transaction confirmation
- 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)
2d0ce91
to
a563e21
Compare
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' |
There was a problem hiding this comment.
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 } : {}), |
There was a problem hiding this comment.
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 } : {}),
amount: params.amount, | ||
contract: params.contract, | ||
msg: encodedMsg, |
There was a problem hiding this comment.
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 }> { |
There was a problem hiding this comment.
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 }[]
There was a problem hiding this 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 optionsThe 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 configurationThe 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
📒 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
- [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) |
There was a problem hiding this comment.
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)
```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) | ||
``` |
There was a problem hiding this comment.
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()}`)
const redemptionRatio = await neptuneService.fetchRedemptionRatio({ | ||
cw20Asset, | ||
nativeAsset, | ||
}) | ||
|
||
console.log(`Redemption Ratio: ${redemptionRatio}`) | ||
``` |
There was a problem hiding this comment.
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)
}
const apr = 0.1 // 10% APR | ||
|
||
const apy = neptuneService.calculateAPY(apr) | ||
|
||
console.log(`APY (continuously compounded): ${(apy * 100).toFixed(2)}%`) | ||
``` |
There was a problem hiding this comment.
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)}%`
)
const depositMsg = neptuneService.createDepositMsg({ | ||
denom, | ||
amount, | ||
sender: injectiveAddress, | ||
}) | ||
|
||
const txHash = await new MsgBroadcasterWithPk({ | ||
privateKey, | ||
network: Network.MainnetSentry, | ||
}).broadcast({ | ||
msgs: depositMsg, | ||
}) | ||
|
||
console.log(txHash) | ||
``` |
There was a problem hiding this comment.
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)
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, | ||
}, | ||
}) | ||
} |
There was a problem hiding this comment.
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:
- Validating amount format (numeric string)
- Checking for negative values
- 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
/** | ||
* 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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix APY calculation implementation and documentation
Issues found:
- Documentation mentions an unused
compoundingFrequency
parameter - 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.
/** | |
* 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 | |
} |
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 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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:
- Adding a maximum iteration limit
- 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.
Summary by CodeRabbit
Release Notes
New Features
NeptuneService
for interacting with Neptune smart contracts.Enhancements
Types and Interfaces
Documentation
NeptuneService
and its functionalities.