Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fix for sending message with ESDTTransfer for transaction decoder #186

Merged
merged 4 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from 2 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
26 changes: 16 additions & 10 deletions multiversx_sdk/network_providers/transaction_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def __init__(self) -> None:
self.function_name: Optional[str] = None
self.function_args: Optional[list[str]] = None
self.transfers: Optional[list[TokenTransfer]] = None
self.message: Optional[list[str]] = None
self.transfer_messages: list[bytes] = []
"""
This property is set to the extra arguments passed to ESDTTransfer when transferring tokens to non-smart contract accounts.
"""
Expand All @@ -28,7 +28,7 @@ def to_dict(self) -> dict[str, Any]:
"function_name": self.function_name if self.function_name else "",
"function_args": self.function_args if self.function_args else [],
"transfers": self._transfers_to_dict(),
"message": self.message if self.message else "",
"transfer_messages": [message.decode() for message in self.transfer_messages],
}

def _transfers_to_dict(self) -> list[dict[str, Any]]:
Expand Down Expand Up @@ -89,7 +89,7 @@ def get_normal_transaction_metadata(self, transaction: TransactionOnNetwork) ->
if len(args) == 0 and not transaction.receiver.is_smart_contract():
metadata.function_name = "transfer"
metadata.function_args = []
metadata.message = data_components
metadata.transfer_messages = [data.encode() for data in data_components]
Copy link
Contributor

Choose a reason for hiding this comment

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

Since transfer_messages holds an array of bytes, and data_components contains hex-encoded components, apply a decoding from hex, to get the raw byes? Sorry if I'm mistaken.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Done.


return metadata

Expand Down Expand Up @@ -122,7 +122,7 @@ def get_esdt_transaction_metadata(self, metadata: TransactionMetadata) -> Option
result.function_name = self.hex_to_string(args[2])
result.function_args = args[3:]
else:
result.message = args[2:]
result.transfer_messages = [arg.encode() for arg in args[2:]]

token = Token(identifier)
transfer = TokenTransfer(token, value)
Expand Down Expand Up @@ -159,8 +159,11 @@ def get_nft_transfer_metadata(self, metadata: TransactionMetadata) -> Optional[T
result.transfers = []

if len(args) > 4:
result.function_name = self.hex_to_string(args[4])
result.function_args = args[5:]
if receiver.is_smart_contract():
Copy link
Contributor

Choose a reason for hiding this comment

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

Here, receiver is the actual receiver of the tokens, not tx.receiver, correct?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

yep, the actual receiver

result.function_name = self.hex_to_string(args[4])
result.function_args = args[5:]
else:
result.transfer_messages = [arg.encode() for arg in args[4:]]

token = Token(collection_identifier, self.hex_to_number(nonce))
transfer = TokenTransfer(token, value)
Expand Down Expand Up @@ -216,10 +219,13 @@ def get_multi_transfer_metadata(self, metadata: TransactionMetadata) -> Optional
result.receiver = receiver.to_bech32()

if len(args) > index:
result.function_name = self.hex_to_string(args[index])
index += 1
result.function_args = args[index:]
index += 1
if receiver.is_smart_contract():
result.function_name = self.hex_to_string(args[index])
index += 1
result.function_args = args[index:]
index += 1
else:
result.transfer_messages = [arg.encode() for arg in args[index:]]

return result

Expand Down
46 changes: 43 additions & 3 deletions multiversx_sdk/network_providers/transaction_decoder_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,9 @@ def test_esdt_transfer_with_receiver_in_data_field(self):
assert metadata.transfers
assert metadata.transfers[0].amount == 44239040000000000000
assert metadata.transfers[0].token.identifier == "LAND-40f26f"
assert metadata.message == ["eaeee8fbf3755756fba62ae862feb7627a4881217dabf6990053985afe7a6733"]
assert metadata.transfer_messages == [
"eaeee8fbf3755756fba62ae862feb7627a4881217dabf6990053985afe7a6733".encode()
]

def test_native_transfer(self):
tx_to_decode = get_empty_transaction_on_network()
Expand All @@ -212,7 +214,7 @@ def test_native_transfer(self):
assert metadata.value == 100000000
assert metadata.function_name == "transfer"
assert metadata.function_args == []
assert metadata.message == ["hello"]
assert metadata.transfer_messages == ["hello".encode()]

def test_esdt_transfer_separated_messages(self):
tx_to_decode = get_empty_transaction_on_network()
Expand All @@ -230,4 +232,42 @@ def test_esdt_transfer_separated_messages(self):
assert metadata.transfers
assert metadata.transfers[0].amount == 44239040000000000000
assert metadata.transfers[0].token.identifier == "LAND-40f26f"
assert metadata.message == ["aaaaaa", "bb"]
assert metadata.transfer_messages == ["aaaaaa".encode(), "bb".encode()]

def test_esdtnft_transfer_separated_messages(self):
tx_to_decode = get_empty_transaction_on_network()

tx_to_decode.sender = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")
tx_to_decode.receiver = Address.new_from_bech32(
"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"
)
tx_to_decode.data = "ESDTNFTTransfer@4d4e592d336131636566@01@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@aaaaaaaaaaaaaaaaaaaaaa@aa".encode()

transaction_decoder = TransactionDecoder()
metadata = transaction_decoder.get_transaction_metadata(tx_to_decode)
assert metadata.function_name is None
assert metadata.function_args is None
assert metadata.transfers
assert metadata.transfers[0].amount == 1
assert metadata.transfers[0].token.identifier == "MNY-3a1cef"
assert metadata.transfers[0].token.nonce == 1
assert metadata.transfer_messages == ["aaaaaaaaaaaaaaaaaaaaaa".encode(), "aa".encode()]

def test_multi_esdtnft_transfer_separated_messages(self):
tx_to_decode = get_empty_transaction_on_network()

tx_to_decode.sender = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")
tx_to_decode.receiver = Address.new_from_bech32(
"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"
)
tx_to_decode.data = "MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@01@4d4e592d336131636566@02@01@aaaaaaaa@aa".encode()

transaction_decoder = TransactionDecoder()
metadata = transaction_decoder.get_transaction_metadata(tx_to_decode)
assert metadata.function_name is None
assert metadata.function_args is None
assert metadata.transfers
assert metadata.transfers[0].amount == 1
assert metadata.transfers[0].token.identifier == "MNY-3a1cef"
assert metadata.transfers[0].token.nonce == 2
assert metadata.transfer_messages == ["aaaaaaaa".encode(), "aa".encode()]
Loading