Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions lib/application/wallet/utils.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import "package:blockchain_utils/bech32/bech32_base.dart";
import "package:blockchain_utils/bip/address/addr_dec_utils.dart";
import "package:blockchain_utils/bip/address/eth_addr.dart";
import "package:blockchain_utils/bip/coin_conf/constant/coins_conf.dart";
import "package:blockchain_utils/hex/hex.dart";

class EthBech32Converter {
/// Encodes an Ethereum address in Bech32 format.
/// This method takes a hexadecimal Ethereum address and a prefix,
/// converts the address to bytes, and then encodes to Bech32-format address.
///
/// Parameters:
/// - hexAddress: The hexadecimal representation of the Ethereum address.
/// - prefix: The Bech32 prefix to be used for encoding.
///
/// Returns:
/// A Bech32-encoded address.
///
/// Throws:
/// - AssertionError: If the length of the cleaned hexadecimal address is not equal to the expected Ethereum address length.
static String ethAddressToBech32(String ethAddress, prefix) {

final cleanHex = AddrDecUtils.validateAndRemovePrefix(
ethAddress, CoinsConf.ethereum.params.addrPrefix!
);
assert(
cleanHex.length == EthAddrConst.addrLen,
"Invalid Ethereum address length: ${cleanHex.length}, expected: ${EthAddrConst.addrLen}"
);
final hexAddressBytes = hex.decode(cleanHex);
return Bech32Encoder.encode(prefix, hexAddressBytes);
Comment on lines +23 to +31
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Consider replacing assertions with proper exception handling.

Using assertions for input validation can be problematic in production builds where assertions may be disabled. Consider throwing specific exceptions instead for better error handling and debugging.

-    assert(
-    cleanHex.length == EthAddrConst.addrLen,
-    "Invalid Ethereum address length: ${cleanHex.length}, expected: ${EthAddrConst.addrLen}"
-    );
+    if (cleanHex.length != EthAddrConst.addrLen) {
+      throw ArgumentError(
+        "Invalid Ethereum address length: ${cleanHex.length}, expected: ${EthAddrConst.addrLen}"
+      );
+    }
🤖 Prompt for AI Agents
In lib/application/wallet/utils.dart around lines 23 to 31, replace the
assertion that checks the Ethereum address length with proper exception
handling. Instead of using assert, throw a specific exception (e.g.,
ArgumentError) when the address length is invalid to ensure the validation works
in production and provides clear error feedback.

}

/// Decodes a Bech32-encoded address.
/// This method takes a Bech32-encoded address
/// and decodes it to its hexadecimal representation.
///
/// Parameters:
/// - bech32Address: The Bech32-encoded Ethereum address.
///
/// Returns:
/// A string representing the Ethereum address.
static String bech32ToEthAddress(String bech32Address, prefix) {
final decoded = Bech32Decoder.decode(prefix, bech32Address);
final hexEncoded = hex.encode(decoded);
assert(
hexEncoded.length == EthAddrConst.addrLen,
"Invalid Ethereum address length: ${hexEncoded.length}, expected: ${EthAddrConst.addrLen}"
);
Comment on lines +46 to +49
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Replace assertion with proper exception handling.

Similar to the previous method, use proper exception handling instead of assertions for production reliability.

-    assert(
-    hexEncoded.length == EthAddrConst.addrLen,
-    "Invalid Ethereum address length: ${hexEncoded.length}, expected: ${EthAddrConst.addrLen}"
-    );
+    if (hexEncoded.length != EthAddrConst.addrLen) {
+      throw ArgumentError(
+        "Invalid Ethereum address length: ${hexEncoded.length}, expected: ${EthAddrConst.addrLen}"
+      );
+    }
📝 Committable suggestion

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

Suggested change
assert(
hexEncoded.length == EthAddrConst.addrLen,
"Invalid Ethereum address length: ${hexEncoded.length}, expected: ${EthAddrConst.addrLen}"
);
if (hexEncoded.length != EthAddrConst.addrLen) {
throw ArgumentError(
"Invalid Ethereum address length: ${hexEncoded.length}, expected: ${EthAddrConst.addrLen}"
);
}
🤖 Prompt for AI Agents
In lib/application/wallet/utils.dart around lines 46 to 49, replace the assert
statement that checks the Ethereum address length with proper exception handling
by throwing an exception when the length is invalid. This ensures the check is
enforced in production environments where assertions may be disabled.

return "${CoinsConf.ethereum.params.addrPrefix!}$hexEncoded";
}
}
9 changes: 9 additions & 0 deletions lib/application/wallet/wallet_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import "package:cosmos_sdk/cosmos_sdk.dart";
import "package:hnotes/application/wallet/utils.dart";
import "package:hnotes/infrastructure/blockchain/wallet_repository.dart";
import "package:hnotes/infrastructure/constants.dart";
import "package:hnotes/infrastructure/local_storage/secrets/secrets_repository.dart";
import "package:rxdart/rxdart.dart";

Expand Down Expand Up @@ -40,6 +42,13 @@ class WalletBloc {
String receiver,
{TransactionConfirmationCallback? confirmTransaction}
) async {
if (receiver.startsWith("0x")) {
receiver = EthBech32Converter.ethAddressToBech32(
receiver,
chainAddressPrefix
);
}
Comment on lines +45 to +50
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add error handling for address conversion.

The address conversion could fail due to invalid input addresses, but there's no error handling around the conversion. This could cause the entire sendToken operation to fail unexpectedly.

-    if (receiver.startsWith("0x")) {
-      receiver = EthBech32Converter.ethAddressToBech32(
-          receiver,
-          chainAddressPrefix
-      );
-    }
+    if (receiver.startsWith("0x")) {
+      try {
+        receiver = EthBech32Converter.ethAddressToBech32(
+            receiver,
+            chainAddressPrefix
+        );
+      } catch (e) {
+        throw ArgumentError("Failed to convert Ethereum address: $e");
+      }
+    }
📝 Committable suggestion

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

Suggested change
if (receiver.startsWith("0x")) {
receiver = EthBech32Converter.ethAddressToBech32(
receiver,
chainAddressPrefix
);
}
if (receiver.startsWith("0x")) {
try {
receiver = EthBech32Converter.ethAddressToBech32(
receiver,
chainAddressPrefix
);
} catch (e) {
throw ArgumentError("Failed to convert Ethereum address: $e");
}
}
🤖 Prompt for AI Agents
In lib/application/wallet/wallet_bloc.dart around lines 45 to 50, the code
converts an Ethereum address to Bech32 format without error handling, which may
cause the sendToken operation to fail if the input address is invalid. Wrap the
conversion call in a try-catch block to catch any exceptions thrown during
conversion, and handle the error gracefully by logging it or emitting an error
state to prevent the entire operation from failing unexpectedly.


final message = MsgSend(
fromAddress: CosmosBaseAddress(sender),
toAddress: CosmosBaseAddress(receiver),
Expand Down