Skip to content

feat(solana): deposit command #317

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

Merged
merged 43 commits into from
Jun 9, 2025
Merged

feat(solana): deposit command #317

merged 43 commits into from
Jun 9, 2025

Conversation

fadeev
Copy link
Member

@fadeev fadeev commented May 2, 2025

Deposit SOL

✅ Devnet

yarn zetachain solana deposit \
  --amount 0.001 \
  --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 \
  --network devnet \
  --private-key $PRIVATE_KEY

https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/crosschain/inboundHashToCctxData/3Tw2S8HPbFAN7xtMase8oLa23d1f9etacTfhuREbGnccuSHTkREbtM9sB3H2H5pYbEhpWMs74wA3QS5wxhSnGsSM

✅ Localnet

yarn zetachain solana deposit \
  --amount 0.001 \
  --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 \
  --network localnet  \
  --mnemonic "grape subway rack mean march bubble carry avoid muffin consider thing street"

Deposit SPL

✅ Devnet

yarn zetachain solana deposit \
  --amount 0.001 \
  --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 \
  --network devnet \
  --mint Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr \
  --private-key $PRIVATE_KEY

https://zetachain-athens.blockpi.network/lcd/v1/public/zeta-chain/crosschain/inboundHashToCctxData/5LjZVoeCScPqmVBkPGrY4LWX3ukDE2f8z28vjbEbDwJPtmmUPKG1o6D8T3uc61h78NKisxQyABhYMmnVi2secydr

✅ Localnet

SOLANA
┌─────────────────────────┬────────────────────────────────────────────────┐
│ (index)                 │ Values                                         │
├─────────────────────────┼────────────────────────────────────────────────┤
│ SPL-20 USDC             │ 'GeAXJsYXV5nm6SQMyaRmQ6mj4KDWZfTJ55FyLsb6yeAc' │
│ gatewayProgram          │ '94U5AHQMKkV5txNJ17QPXWoh474PheGou6cNP2FEuL1d' │
│ gatewayTokenAccountUSDC │ '9EFHsQj3Grc29H3xXMbcdZ3P6osBpgUoLvcJFw8cmZV7' │
│ userTokenAccountUSDC    │ 'E2nTupEqLRkr4d4dJUno87wyu7L9ku7LCKJgHKsojw9v' │
│ tokenProgram            │ 'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'  │
└─────────────────────────┴────────────────────────────────────────────────┘

Right now it's a bit confusing, because by default localnet airdrops SPL tokens only to the account defined in ~/.config/solana/id.json, and not to the address associated with the default mnemonic below.

yarn zetachain solana deposit \
  --amount 0.001 \
  --recipient 0x4955a3F38ff86ae92A914445099caa8eA2B9bA32 \
  --mnemonic "grape subway rack mean march bubble carry avoid muffin consider thing street" \
  --network localnet \
  --mint GeAXJsYXV5nm6SQMyaRmQ6mj4KDWZfTJ55FyLsb6yeAc

Summary by CodeRabbit

  • New Features

    • Introduced a CLI command to enable Solana token deposits, supporting both native SOL and SPL tokens, with flexible wallet authentication and network selection.
    • Added validation schema for Solana deposit options to improve input reliability.
    • Exported constants for Solana token program ID and supported networks.
  • Chores

    • Updated Node.js version to 21 in build, lint, and test workflows for improved compatibility.
    • Upgraded a Solana protocol dependency to a newer version.
  • Improvements

    • Enhanced account creation to accept both base58 and hex-encoded private keys, returning keys in base58 format.
    • Updated Solana transaction handling to use development versions of gateway interfaces for improved integration.
    • Refined private key handling to support multiple formats and improved mnemonic-based keypair generation.
    • Consolidated imports for Solana keypair creation to streamline codebase.
    • Replaced hex prefix trimming utility with a new, dedicated function and added tests to ensure correct behavior.

Copy link
Contributor

coderabbitai bot commented May 2, 2025

📝 Walkthrough

Walkthrough

The updates include raising the Node.js version from 18 to 21 in all GitHub Actions workflows, upgrading the @zetachain/protocol-contracts-solana dependency, and introducing a new Solana deposit CLI command. Supporting changes add network constants, enhance Solana account creation to accept multiple key formats, and introduce schema validation for deposit options. Additionally, utility functions for trimming "0x" prefixes were refactored and tested.

Changes

Files/Group Change Summary
.github/workflows/build.yaml
.github/workflows/lint.yaml
.github/workflows/test.yaml
Node.js version updated from 18 to 21 in all GitHub Actions workflows.
package.json Upgraded @zetachain/protocol-contracts-solana dependency from 2.0.0-rc1 to 3.0.2-rc2.
packages/client/src/solanaDeposit.ts
packages/client/src/solanaDepositAndCall.ts
Changed Gateway_IDL import path to development version; explicitly imported and used Connection from @solana/web3.js; cast connection argument in transaction sending logic.
packages/commands/src/solana/deposit.ts Added a new Solana deposit CLI command supporting SOL and SPL token deposits, with wallet derivation from mnemonic or base58 private key and network selection. Exports new helper functions and command.
packages/commands/src/solana/index.ts Registered the new depositCommand as a subcommand of solanaCommand.
utils/accounts.ts Enhanced createSolanaAccount to accept private keys in base58 or hex, returning base58-encoded private keys.
types/shared.constants.ts Added exported constants: SOLANA_TOKEN_PROGRAM and SOLANA_NETWORKS.
utils/solana.commands.helpers.ts New module exporting solanaDepositOptionsSchema using zod for deposit command option validation; functions to derive Solana Keypair from mnemonic or base58 private key; function to create CLI command with common Solana options.
packages/tasks/src/solanaDeposit.ts
packages/tasks/src/solanaDepositAndCall.ts
Consolidated imports by replacing direct Keypair import from @solana/web3.js with web3 from @coral-xyz/anchor; updated Keypair usage accordingly.
types/accounts.types.ts Updated Solana account schema by renaming secretKey field to privateKey.
packages/commands/src/bitcoin/inscription/call.ts
packages/commands/src/bitcoin/inscription/depositAndCall.ts
packages/commands/src/bitcoin/inscription/encode.ts
test/bitcoinEncode.test.ts
Replaced import and usage of trimOx with new trim0x utility function for trimming "0x" prefix from hex strings.
utils/bitcoinEncode.ts Removed the exported trimOx function.
utils/trim0x.ts Added new utility function trim0x to remove "0x" prefix from hex strings.
utils/index.ts Added export for the new trim0x utility module.
test/trim0x.test.ts Added new test suite for the trim0x utility function verifying correct prefix trimming behavior.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI (depositCommand)
    participant KeypairHelper
    participant SolanaProvider
    participant GatewayProgram

    User->>CLI (depositCommand): Run deposit command with options
    CLI (depositCommand)->>KeypairHelper: Derive Keypair (from mnemonic or private key)
    KeypairHelper-->>CLI (depositCommand): Return Keypair
    CLI (depositCommand)->>SolanaProvider: Connect to selected network
    SolanaProvider-->>CLI (depositCommand): Return provider
    CLI (depositCommand)->>GatewayProgram: Initialize with IDL and provider
    CLI (depositCommand)->>GatewayProgram: Call deposit/depositSplToken with params
    GatewayProgram-->>CLI (depositCommand): Return transaction hash
    CLI (depositCommand)->>User: Output transaction hash
Loading

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • SPL-20: Entity not found: Issue - Could not find referenced Issue.

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 00348fb and 720d40d.

📒 Files selected for processing (1)
  • test/solana.commands.helpers.test.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • test/solana.commands.helpers.test.ts
✨ Finishing Touches
  • 📝 Generate Docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this 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.

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.

@github-actions github-actions bot added the feat label May 2, 2025
@fadeev fadeev linked an issue May 2, 2025 that may be closed by this pull request
@fadeev fadeev marked this pull request as ready for review May 5, 2025 17:14
@fadeev fadeev requested review from a team as code owners May 5, 2025 17:14
Copy link
Contributor

@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: 5

🧹 Nitpick comments (2)
packages/commands/src/solana/deposit.ts (2)

124-124: Purpose of null parameter is unclear.

Both depositSplToken and deposit methods have a null parameter, but there's no comment explaining what this parameter is for.

Add comments to explain the purpose of this parameter:

- null
+ null // Message parameter - null means no additional message data

Also applies to: 141-141


161-163: Consider adding a default network.

The network option doesn't have a default value, which means it must be explicitly provided. Consider setting a default, such as "devnet" for ease of use.

.addOption(
-  new Option("--network <network>", "Solana network").choices(networks)
+  new Option("--network <network>", "Solana network").choices(networks).default("devnet")
)
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5aff2a2 and fc1b6e8.

⛔ Files ignored due to path filters (29)
  • typechain-types/@uniswap/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-core/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-core/contracts/interfaces/callback/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-core/contracts/interfaces/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-core/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-periphery/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-periphery/contracts/interfaces/ISwapRouter.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-periphery/contracts/interfaces/index.ts is excluded by !typechain-types/**
  • typechain-types/@uniswap/v3-periphery/index.ts is excluded by !typechain-types/**
  • typechain-types/contracts/SwapHelpers.sol/SwapLibrary.ts is excluded by !typechain-types/**
  • typechain-types/contracts/SwapHelpers.sol/index.ts is excluded by !typechain-types/**
  • typechain-types/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-core/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-core/contracts/interfaces/callback/IUniswapV3SwapCallback__factory.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-core/contracts/interfaces/callback/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-core/contracts/interfaces/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-core/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-periphery/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-periphery/contracts/interfaces/ISwapRouter__factory.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-periphery/contracts/interfaces/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/@uniswap/v3-periphery/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/contracts/SwapHelpers.sol/SwapLibrary__factory.ts is excluded by !typechain-types/**
  • typechain-types/factories/contracts/SwapHelpers.sol/index.ts is excluded by !typechain-types/**
  • typechain-types/factories/contracts/index.ts is excluded by !typechain-types/**
  • typechain-types/hardhat.d.ts is excluded by !typechain-types/**
  • typechain-types/index.ts is excluded by !typechain-types/**
  • yarn.lock is excluded by !**/yarn.lock, !**/*.lock
📒 Files selected for processing (8)
  • .github/workflows/build.yaml (1 hunks)
  • .github/workflows/lint.yaml (1 hunks)
  • .github/workflows/test.yaml (1 hunks)
  • package.json (2 hunks)
  • packages/client/src/solanaDeposit.ts (1 hunks)
  • packages/client/src/solanaDepositAndCall.ts (1 hunks)
  • packages/commands/src/solana/deposit.ts (1 hunks)
  • packages/commands/src/solana/index.ts (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
packages/commands/src/solana/deposit.ts (1)
packages/tasks/src/account.ts (1)
  • main (121-169)
🔇 Additional comments (14)
package.json (1)

121-121: Dependency bump for @zetachain/protocol-contracts-solana
Updated the Solana protocol-contracts dependency from 2.0.0-rc1 to 3.0.2-rc2. Ensure compatibility with the new Gateway IDL and that the yarn.lock has been updated and committed to avoid version mismatches.

.github/workflows/lint.yaml (1)

18-18: Upgrade Node.js runtime to 21
Aligns the lint workflow environment with build and test pipelines. actions/setup-node@v3 supports Node.js 21 out of the box.

.github/workflows/build.yaml (1)

18-18: Upgrade Node.js runtime to 21
Consistent Node.js version across CI ensures uniform behavior. No additional changes needed.

.github/workflows/test.yaml (1)

18-18: Upgrade Node.js runtime to 21
Brings the test workflow in line with build and lint jobs—good for consistency.

packages/client/src/solanaDeposit.ts (1)

8-8:

✅ Verification successful

Switch to development Gateway IDL path
The import was changed to @zetachain/protocol-contracts-solana/dev/idl/gateway.json. Confirm that this path exists in version 3.0.2-rc2 of the package and that any reference in solanaDepositAndCall.ts matches.

To verify, you can run:


🏁 Script executed:

#!/usr/bin/env bash
# Verify that the development IDL exists in the installed package
if [ ! -f "node_modules/@zetachain/protocol-contracts-solana/dev/idl/gateway.json" ]; then
  echo "ERROR: dev/idl/gateway.json not found in protocol-contracts-solana"
  exit 1
else
  echo "OK: Gateway IDL file found"
fi

Length of output: 150


🏁 Script executed:

#!/usr/bin/env bash
# Verify that solanaDepositAndCall.ts uses the same development IDL path
rg -n 'from\s+".*@zetachain/protocol-contracts-solana/dev/idl/gateway.json"' packages/client/src/solanaDepositAndCall.ts || \
echo "WARNING: No matching import of gateway.json found in solanaDepositAndCall.ts"

Length of output: 209


Development Gateway IDL path verified
The import path @zetachain/protocol-contracts-solana/dev/idl/gateway.json exists in version 3.0.2-rc2 and is consistently used in both files; no changes required.

• packages/client/src/solanaDeposit.ts — line 8
• packages/client/src/solanaDepositAndCall.ts — line 8

packages/client/src/solanaDepositAndCall.ts (1)

8-8: Updated Gateway IDL import path to use development version.

The import path for the Gateway IDL has been updated to use the development version from the /dev directory. This change aligns with the dependency upgrade to @zetachain/[email protected] and supports the new deposit functionality.

packages/commands/src/solana/index.ts (1)

3-3: New deposit command successfully integrated.

The deposit command import and registration look good. This properly exposes the new Solana deposit functionality to the CLI.

Also applies to: 11-11

packages/commands/src/solana/deposit.ts (7)

1-15: Import statements look good.

All necessary dependencies are imported for Solana interaction, token handling, and CLI commands. Both development and production Gateway IDLs are properly imported.


18-28: DepositOptions interface is well-defined.

The interface provides all necessary parameters for deposit operations, supporting both native SOL and SPL token deposits.


30-47: Key derivation functions implemented correctly.

The helper functions properly implement keypair derivation from both mnemonics and base58-encoded private keys with appropriate error handling.


54-61: Wallet initialization looks good.

Properly handles keypair initialization from either private key or mnemonic with appropriate error handling.


63-68: API endpoint selection is correct.

The code properly selects the appropriate Solana API endpoint based on the network parameter.


149-164: Command definition looks good.

The CLI command is well-defined with appropriate required and optional parameters. The usage of Option with choices for network is a good practice.


51-52:

❌ Incorrect review comment

Consider environment-specific IDL selection.

The code selects the Gateway IDL based on network, but uses the same IDL for both mainnet and devnet. Ensure this approach is correct as mainnet may require a stable IDL version.


🏁 Script executed:

#!/bin/bash
# Check if there are references to different IDL usage for mainnet vs devnet
rg -A 5 -B 5 "mainnet.*IDL|devnet.*IDL" --type ts

Length of output: 744


🏁 Script executed:

#!/bin/bash
# Locate where GATEWAY_DEV_IDL and GATEWAY_PROD_IDL are defined to verify if a separate devnet IDL exists
rg -n "GATEWAY_DEV_IDL" --type ts
rg -n "GATEWAY_PROD_IDL" --type ts

Length of output: 565


No separate devnet IDL exists
The @zetachain/protocol-contracts-solana package only provides two IDLs—

  • dev/idl/gateway.json (used for localnet)
  • prod/idl/gateway.json (used for everything else, including both devnet and mainnet)

As such, using GATEWAY_PROD_IDL for both devnet and mainnet is intentional and correct. No changes are required unless you plan to introduce a distinct devnet IDL.

• File: packages/commands/src/solana/deposit.ts
Lines: 51–52

Likely an incorrect or invalid review comment.

@fadeev fadeev marked this pull request as draft May 8, 2025 10:33
@fadeev fadeev linked an issue May 8, 2025 that may be closed by this pull request
@fadeev
Copy link
Member Author

fadeev commented May 17, 2025

Modified accounts import --type solana to correctly import base58 private key.

@fadeev fadeev marked this pull request as ready for review May 19, 2025 08:27
Copy link
Contributor

@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: 0

🧹 Nitpick comments (3)
utils/solana.commands.helpers.ts (3)

5-14: Consider adding stricter validation for field formats

The schema efficiently defines the required fields and their types, but could benefit from more specific format validation:

  • amount should validate that it's a valid number string
  • recipient should validate as a valid Solana address (base58 encoded public key)
  • mint should validate as a valid Solana address when provided
  • network should restrict to supported networks (devnet, localnet, mainnet)
 export const solanaDepositOptionsSchema = z
   .object({
-    amount: z.string(),
+    amount: z.string().refine((val) => !isNaN(parseFloat(val)), {
+      message: "Amount must be a valid number",
+    }),
     mint: z.string().optional(),
     mnemonic: z.string().optional(),
-    network: z.string(),
+    network: z.enum(["devnet", "localnet", "mainnet"]),
     privateKey: z.string().optional(),
-    recipient: z.string(),
+    recipient: z.string().regex(/^[1-9A-HJ-NP-Za-km-z]{32,44}$/, {
+      message: "Recipient must be a valid Solana address",
+    }),
     tokenProgram: z.string().default(SOLANA_TOKEN_PROGRAM),
   })

15-17: Consider enforcing at least one authentication method

The refinement correctly ensures that both authentication methods aren't provided simultaneously, but doesn't enforce that at least one is provided.

   .refine((data) => !(data.mnemonic && data.privateKey), {
     message: "Only one of mnemonic or privateKey can be provided, not both",
   });
+  .refine((data) => !!(data.mnemonic || data.privateKey), {
+    message: "Either mnemonic or privateKey must be provided",
+  });

1-18: Add JSDoc comments for better documentation

Consider adding JSDoc comments to explain the purpose of the schema and document each field's requirements. This would improve developer experience and make the code more maintainable.

+/**
+ * Schema for validating Solana deposit command options.
+ * Used to ensure all required fields are present and correctly formatted.
+ */
 export const solanaDepositOptionsSchema = z
   .object({
+    /**
+     * Amount to deposit, must be a valid number as string
+     */
     amount: z.string(),
+    /**
+     * Optional SPL token mint address for token deposits.
+     * Required when depositing SPL tokens, not used for SOL deposits.
+     */
     mint: z.string().optional(),
+    /**
+     * Optional BIP39 mnemonic phrase for wallet derivation.
+     * Mutually exclusive with privateKey.
+     */
     mnemonic: z.string().optional(),
+    /**
+     * Solana network to use (devnet, localnet, mainnet)
+     */
     network: z.string(),
+    /**
+     * Optional base58-encoded private key for wallet.
+     * Mutually exclusive with mnemonic.
+     */
     privateKey: z.string().optional(),
+    /**
+     * Destination Solana address for the deposit
+     */
     recipient: z.string(),
+    /**
+     * Token program address, defaults to standard Solana token program
+     */
     tokenProgram: z.string().default(SOLANA_TOKEN_PROGRAM),
   })
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6d8cca and 255aec5.

📒 Files selected for processing (2)
  • packages/commands/src/solana/deposit.ts (1 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/commands/src/solana/deposit.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
utils/solana.commands.helpers.ts (1)
types/shared.constants.ts (1)
  • SOLANA_TOKEN_PROGRAM (2-3)
🔇 Additional comments (1)
utils/solana.commands.helpers.ts (1)

1-4: Nice clean imports!

The imports are well-organized with clear separation between external libraries (zod) and internal modules.

@fadeev fadeev requested a review from hernan-clich May 21, 2025 08:54
Copy link
Contributor

@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: 2

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 58b43da and 1278c16.

📒 Files selected for processing (3)
  • packages/commands/src/solana/deposit.ts (1 hunks)
  • utils/accounts.ts (2 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • utils/accounts.ts
  • packages/commands/src/solana/deposit.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
utils/solana.commands.helpers.ts (1)
types/shared.constants.ts (1)
  • SOLANA_TOKEN_PROGRAM (2-3)
🔇 Additional comments (2)
utils/solana.commands.helpers.ts (2)

1-6: LGTM! Clean imports with appropriate dependencies.

The imports are well-organized and all dependencies are used appropriately for Solana operations, mnemonic handling, base58 encoding, and schema validation.


30-41: LGTM! Robust private key handling with proper error handling.

The function correctly:

  • Decodes base58-encoded private keys (standard for Solana)
  • Uses appropriate Solana keypair creation method
  • Provides clear error messaging for invalid formats
  • Handles exceptions gracefully

Copy link
Contributor

@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: 1

♻️ Duplicate comments (2)
utils/solana.commands.helpers.ts (2)

12-24: Add validation to ensure at least one authentication method is provided.

The schema correctly enforces mutual exclusivity between mnemonic and privateKey, but it doesn't ensure that at least one authentication method is provided. This could lead to runtime errors when trying to create a keypair.

Apply this diff to ensure at least one authentication method is provided:

  .refine((data) => !(data.mnemonic && data.privateKey), {
    message: "Only one of mnemonic or privateKey can be provided, not both",
  })
+ .refine((data) => data.mnemonic || data.privateKey, {
+   message: "Either mnemonic or privateKey must be provided",
+ });

26-32: Add error handling for invalid mnemonic phrases.

The function correctly implements BIP39 mnemonic to seed conversion and proper seed slicing for Solana keypairs. However, it lacks explicit error handling for invalid mnemonic phrases.

Apply this diff to add proper error handling:

export const keypairFromMnemonic = async (
  mnemonic: string
): Promise<anchor.web3.Keypair> => {
+ if (!bip39.validateMnemonic(mnemonic)) {
+   throw new Error("Invalid mnemonic phrase");
+ }
  const seed = await bip39.mnemonicToSeed(mnemonic);
  const seedSlice = new Uint8Array(seed).slice(0, 32);
  return anchor.web3.Keypair.fromSeed(seedSlice);
};
🧹 Nitpick comments (1)
packages/commands/src/solana/deposit.ts (1)

30-35: Potential undefined keypair issue.

The code doesn't handle the case where neither privateKey nor mnemonic is provided, which could lead to keypair being undefined. While the schema validation should prevent this, adding explicit error handling would improve robustness.

Apply this diff to add explicit error handling:

  let keypair: anchor.web3.Keypair;
  if (options.privateKey) {
    keypair = keypairFromPrivateKey(options.privateKey);
  } else if (options.mnemonic) {
    keypair = await keypairFromMnemonic(options.mnemonic);
+ } else {
+   throw new Error("Either mnemonic or privateKey must be provided");
  }
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1278c16 and 195b7a6.

📒 Files selected for processing (2)
  • packages/commands/src/solana/deposit.ts (1 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
packages/commands/src/solana/deposit.ts (1)
Learnt from: fadeev
PR: zeta-chain/toolkit#317
File: packages/commands/src/solana/deposit.ts:140-140
Timestamp: 2025-05-21T08:42:41.583Z
Learning: The native SOL deposit method in the Solana Gateway program works correctly with an empty accounts object, as the program handles the necessary accounts internally.
🧬 Code Graph Analysis (2)
utils/solana.commands.helpers.ts (1)
types/shared.constants.ts (2)
  • SOLANA_TOKEN_PROGRAM (2-3)
  • SOLANA_NETWORKS (4-4)
packages/commands/src/solana/deposit.ts (4)
utils/solana.commands.helpers.ts (4)
  • solanaDepositOptionsSchema (12-24)
  • keypairFromPrivateKey (34-45)
  • keypairFromMnemonic (26-32)
  • createSolanaCommandWithCommonOptions (47-64)
utils/handleError.ts (1)
  • handleError (31-45)
types/shared.constants.ts (1)
  • SOLANA_TOKEN_PROGRAM (2-3)
utils/validateAndParseSchema.ts (1)
  • validateAndParseSchema (28-59)
🪛 GitHub Check: build
packages/commands/src/solana/deposit.ts

[failure] 1-1:
Run autofix to sort these imports!

🪛 ESLint
packages/commands/src/solana/deposit.ts

[error] 1-21: Run autofix to sort these imports!

(simple-import-sort/imports)

🪛 GitHub Actions: Lint
packages/commands/src/solana/deposit.ts

[error] 1-1: ESLint: Run autofix to sort these imports! (simple-import-sort/imports)

🔇 Additional comments (8)
utils/solana.commands.helpers.ts (2)

34-45: Excellent error handling for private key validation.

The keypairFromPrivateKey function properly handles base58 decoding errors and provides clear error messages. The implementation correctly uses try-catch to handle invalid private key formats.


47-64: Well-designed command helper function.

The createSolanaCommandWithCommonOptions function provides a clean abstraction for creating Solana commands with common options. The use of conflicts() ensures mutual exclusivity between mnemonic and private-key options, and the choices restriction for networks is appropriate.

packages/commands/src/solana/deposit.ts (6)

46-46: Non-null assertion should be safe here.

The non-null assertion (keypair!) is acceptable here since the schema validation ensures that a keypair will be created from either mnemonic or privateKey. However, the previous suggestion to add explicit error handling would eliminate the need for this assertion.


61-88: Excellent decimal handling and balance validation.

The implementation correctly fetches the actual decimal places from the mint info for SPL tokens and validates the user's token balance before attempting the transaction. This addresses previous review feedback and ensures accurate token handling.


127-136: Good SOL balance validation.

The SOL balance check prevents failed transactions by ensuring sufficient funds are available before attempting the deposit. The conversion to lamports and balance comparison logic is correct.


143-143: Empty accounts object is acceptable for native SOL deposits.

Based on the retrieved learnings, the native SOL deposit method in the Solana Gateway program works correctly with an empty accounts object, as the program handles the necessary accounts internally.


147-154: Proper error handling with context.

The error handling uses the shared handleError utility to provide context and properly exits the process on failure. This ensures users receive clear error messages when transactions fail.


157-175: Well-structured command definition.

The command is properly structured using the shared helper function and includes appropriate schema validation. The use of validateAndParseSchema with exitOnError: true ensures proper validation and user-friendly error messages.

Copy link
Contributor

@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: 0

♻️ Duplicate comments (1)
packages/commands/src/solana/deposit.ts (1)

1-23: Import sorting issue flagged by ESLint.

The imports need to be reordered according to the project's ESLint configuration.

🧹 Nitpick comments (1)
packages/commands/src/solana/deposit.ts (1)

32-45: Improve type safety by restructuring keypair initialization.

The current code uses non-null assertions throughout the file, which could be avoided with better TypeScript flow analysis.

Consider restructuring the keypair creation to avoid non-null assertions:

-let keypair: anchor.web3.Keypair;
-if (options.privateKey) {
-  keypair = keypairFromPrivateKey(options.privateKey);
-} else if (options.mnemonic) {
-  keypair = await keypairFromMnemonic(options.mnemonic);
-} else if (options.name) {
-  const privateKey = getAccountData<SolanaAccountData>(
-    "solana",
-    options.name
-  )?.privateKey;
-  keypair = keypairFromPrivateKey(privateKey!);
-} else {
-  throw new Error("No account provided");
-}
+const keypair = await (async (): Promise<anchor.web3.Keypair> => {
+  if (options.privateKey) {
+    return keypairFromPrivateKey(options.privateKey);
+  } else if (options.mnemonic) {
+    return await keypairFromMnemonic(options.mnemonic);
+  } else if (options.name) {
+    const accountData = getAccountData<SolanaAccountData>("solana", options.name);
+    if (!accountData?.privateKey) {
+      throw new Error(`No private key found for account: ${options.name}`);
+    }
+    return keypairFromPrivateKey(accountData.privateKey);
+  } else {
+    throw new Error("No account provided");
+  }
+})();

This eliminates the need for non-null assertions later in the code.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 195b7a6 and ffe2311.

📒 Files selected for processing (3)
  • packages/commands/src/solana/deposit.ts (1 hunks)
  • types/accounts.types.ts (1 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • utils/solana.commands.helpers.ts
🧰 Additional context used
🧠 Learnings (1)
packages/commands/src/solana/deposit.ts (1)
Learnt from: fadeev
PR: zeta-chain/toolkit#317
File: packages/commands/src/solana/deposit.ts:140-140
Timestamp: 2025-05-21T08:42:41.583Z
Learning: The native SOL deposit method in the Solana Gateway program works correctly with an empty accounts object, as the program handles the necessary accounts internally.
🔇 Additional comments (3)
types/accounts.types.ts (1)

31-31: LGTM! Schema update aligns with private key standardization.

The renaming from secretKey to privateKey improves consistency across the codebase and aligns with the updated private key handling that now supports base58-encoded strings.

packages/commands/src/solana/deposit.ts (2)

69-165: Well-implemented deposit logic with proper error handling.

The implementation correctly handles both SOL and SPL token deposits with the following improvements from past reviews:

  • ✅ Dynamic decimal fetching for SPL tokens
  • ✅ Balance checks for both SOL and SPL tokens
  • ✅ Proper error handling with try-catch
  • ✅ Schema validation using Zod

The empty accounts object for native SOL deposits is intentional as confirmed by previous feedback.


167-185: Command definition follows established patterns.

The command setup using createSolanaCommandWithCommonOptions and schema validation is well-structured and consistent with the project's patterns.

@fadeev fadeev requested a review from hernan-clich May 28, 2025 10:12
Copy link
Contributor

@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: 0

🧹 Nitpick comments (1)
test/trim0x.test.ts (1)

34-38: Fix misleading test description.

The test name suggests "case-insensitive" behavior, but the function is actually case-sensitive (only removes lowercase "0x", not uppercase "0X"). The test logic and expectation are correct, but the name is misleading.

-  it("should handle case-insensitive 0x prefix", () => {
+  it("should not remove uppercase 0X prefix (case-sensitive)", () => {
📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b35a0d5 and 65e592b.

📒 Files selected for processing (9)
  • packages/commands/src/bitcoin/inscription/call.ts (2 hunks)
  • packages/commands/src/bitcoin/inscription/depositAndCall.ts (2 hunks)
  • packages/commands/src/bitcoin/inscription/encode.ts (2 hunks)
  • test/bitcoinEncode.test.ts (2 hunks)
  • test/trim0x.test.ts (1 hunks)
  • utils/bitcoinEncode.ts (0 hunks)
  • utils/index.ts (1 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
  • utils/trim0x.ts (1 hunks)
💤 Files with no reviewable changes (1)
  • utils/bitcoinEncode.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/commands/src/bitcoin/inscription/depositAndCall.ts
  • utils/trim0x.ts
  • test/bitcoinEncode.test.ts
  • packages/commands/src/bitcoin/inscription/call.ts
  • packages/commands/src/bitcoin/inscription/encode.ts
  • utils/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • utils/solana.commands.helpers.ts
🧰 Additional context used
🧬 Code Graph Analysis (1)
test/trim0x.test.ts (1)
utils/trim0x.ts (1)
  • trim0x (6-8)
🔇 Additional comments (5)
test/trim0x.test.ts (5)

1-8: LGTM: Basic functionality test is correct.

The test correctly validates that the trim0x function removes the lowercase "0x" prefix from hexadecimal strings.


10-14: LGTM: No-prefix test is correct.

The test correctly validates that strings without the "0x" prefix remain unchanged.


16-20: LGTM: Empty string handling test is correct.

The test correctly validates that empty strings are handled gracefully.


22-26: LGTM: Edge case test is correct.

The test correctly validates that a string containing only "0x" results in an empty string after trimming.


28-32: LGTM: Middle occurrence test is correct.

The test correctly validates that "0x" appearing in the middle of a string is not removed, confirming the function only trims from the start.

Copy link
Contributor

@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: 1

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 65e592b and 00348fb.

📒 Files selected for processing (2)
  • test/solana.commands.helpers.test.ts (1 hunks)
  • utils/solana.commands.helpers.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • utils/solana.commands.helpers.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: build
  • GitHub Check: build
🔇 Additional comments (4)
test/solana.commands.helpers.test.ts (4)

1-4: LGTM! Clean imports and dependencies.

The imports are well-organized and include all necessary dependencies for testing Solana keypair functionality.


6-11: Excellent test setup with consistent test data.

Using Keypair.generate() to create test data ensures consistent and valid keypairs across all tests. The preparation of both base58 and hex formats is well thought out.


12-19: Good base58 format test coverage.

The test correctly verifies keypair creation from base58 format by comparing public keys, which is the appropriate validation approach.


21-35: Comprehensive hex format validation.

Good coverage of hex format scenarios including both with and without the "0x" prefix. The tests properly validate the resulting keypairs.

Copy link
Member

@hernan-clich hernan-clich left a comment

Choose a reason for hiding this comment

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

Tested ACK

@fadeev fadeev merged commit e0cf476 into main Jun 9, 2025
10 checks passed
@fadeev fadeev deleted the solana-deposit branch June 9, 2025 08:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Command: solana deposit
2 participants