Skip to content

Commit

Permalink
Merge pull request #155 from multiversx/new-relayed-v3
Browse files Browse the repository at this point in the history
Added support for the new RelayedV3
  • Loading branch information
popenta authored Nov 21, 2024
2 parents fb3d420 + f1986fa commit 9e1374f
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 22 deletions.
6 changes: 5 additions & 1 deletion multiversx_sdk/converters/transactions_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ def transaction_to_dictionary(self, transaction: ITransaction) -> Dict[str, Any]
"options": transaction.options,
"guardian": transaction.guardian,
"signature": self._value_to_hex_or_empty(transaction.signature),
"guardianSignature": self._value_to_hex_or_empty(transaction.guardian_signature)
"guardianSignature": self._value_to_hex_or_empty(transaction.guardian_signature),
"relayer": transaction.relayer,
"relayerSignature": self._value_to_hex_or_empty(transaction.relayer_signature)
}

def dictionary_to_transaction(self, dictionary: Dict[str, Any]) -> Transaction:
Expand All @@ -55,6 +57,8 @@ def dictionary_to_transaction(self, dictionary: Dict[str, Any]) -> Transaction:
options=dictionary.get("options", None),
signature=self._bytes_from_hex(dictionary.get("signature", "")),
guardian_signature=self._bytes_from_hex(dictionary.get("guardianSignature", "")),
relayer=dictionary.get("relayer", None),
relayer_signature=self._bytes_from_hex(dictionary.get("relayerSignature", ""))
)

def transaction_on_network_to_outcome(self, transaction_on_network: TransactionOnNetwork) -> TransactionOutcome:
Expand Down
2 changes: 2 additions & 0 deletions multiversx_sdk/core/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class ITransaction(Protocol):
guardian: str
signature: bytes
guardian_signature: bytes
relayer: str
relayer_signature: bytes


class IMessage(Protocol):
Expand Down
32 changes: 17 additions & 15 deletions multiversx_sdk/core/proto/transaction.proto
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,21 @@ package proto;

// Transaction holds all the data needed for a value transfer or SC call
message Transaction {
uint64 Nonce = 1;
bytes Value = 2;
bytes RcvAddr = 3;
bytes RcvUserName = 4;
bytes SndAddr = 5;
bytes SndUserName = 6;
uint64 GasPrice = 7;
uint64 GasLimit = 8;
bytes Data = 9;
bytes ChainID = 10;
uint32 Version = 11;
bytes Signature = 12;
uint32 Options = 13;
bytes GuardAddr = 14;
bytes GuardSignature = 15;
uint64 Nonce = 1;
bytes Value = 2;
bytes RcvAddr = 3;
bytes RcvUserName = 4;
bytes SndAddr = 5;
bytes SndUserName = 6;
uint64 GasPrice = 7;
uint64 GasLimit = 8;
bytes Data = 9;
bytes ChainID = 10;
uint32 Version = 11;
bytes Signature = 12;
uint32 Options = 13;
bytes GuardAddr = 14;
bytes GuardSignature = 15;
bytes Relayer = 16;
bytes RelayerSignature = 17;
}
4 changes: 2 additions & 2 deletions multiversx_sdk/core/proto/transaction_pb2.py

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 6 additions & 2 deletions multiversx_sdk/core/proto/transaction_pb2.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ from typing import ClassVar as _ClassVar, Optional as _Optional
DESCRIPTOR: _descriptor.FileDescriptor

class Transaction(_message.Message):
__slots__ = ["ChainID", "Data", "GasLimit", "GasPrice", "GuardAddr", "GuardSignature", "Nonce", "Options", "RcvAddr", "RcvUserName", "Signature", "SndAddr", "SndUserName", "Value", "Version"]
__slots__ = ["ChainID", "Data", "GasLimit", "GasPrice", "GuardAddr", "GuardSignature", "Nonce", "Options", "RcvAddr", "RcvUserName", "Relayer", "RelayerSignature", "Signature", "SndAddr", "SndUserName", "Value", "Version"]
CHAINID_FIELD_NUMBER: _ClassVar[int]
ChainID: bytes
DATA_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -24,8 +24,12 @@ class Transaction(_message.Message):
Options: int
RCVADDR_FIELD_NUMBER: _ClassVar[int]
RCVUSERNAME_FIELD_NUMBER: _ClassVar[int]
RELAYERSIGNATURE_FIELD_NUMBER: _ClassVar[int]
RELAYER_FIELD_NUMBER: _ClassVar[int]
RcvAddr: bytes
RcvUserName: bytes
Relayer: bytes
RelayerSignature: bytes
SIGNATURE_FIELD_NUMBER: _ClassVar[int]
SNDADDR_FIELD_NUMBER: _ClassVar[int]
SNDUSERNAME_FIELD_NUMBER: _ClassVar[int]
Expand All @@ -36,4 +40,4 @@ class Transaction(_message.Message):
VERSION_FIELD_NUMBER: _ClassVar[int]
Value: bytes
Version: int
def __init__(self, Nonce: _Optional[int] = ..., Value: _Optional[bytes] = ..., RcvAddr: _Optional[bytes] = ..., RcvUserName: _Optional[bytes] = ..., SndAddr: _Optional[bytes] = ..., SndUserName: _Optional[bytes] = ..., GasPrice: _Optional[int] = ..., GasLimit: _Optional[int] = ..., Data: _Optional[bytes] = ..., ChainID: _Optional[bytes] = ..., Version: _Optional[int] = ..., Signature: _Optional[bytes] = ..., Options: _Optional[int] = ..., GuardAddr: _Optional[bytes] = ..., GuardSignature: _Optional[bytes] = ...) -> None: ...
def __init__(self, Nonce: _Optional[int] = ..., Value: _Optional[bytes] = ..., RcvAddr: _Optional[bytes] = ..., RcvUserName: _Optional[bytes] = ..., SndAddr: _Optional[bytes] = ..., SndUserName: _Optional[bytes] = ..., GasPrice: _Optional[int] = ..., GasLimit: _Optional[int] = ..., Data: _Optional[bytes] = ..., ChainID: _Optional[bytes] = ..., Version: _Optional[int] = ..., Signature: _Optional[bytes] = ..., Options: _Optional[int] = ..., GuardAddr: _Optional[bytes] = ..., GuardSignature: _Optional[bytes] = ..., Relayer: _Optional[bytes] = ..., RelayerSignature: _Optional[bytes] = ...) -> None: ...
6 changes: 6 additions & 0 deletions multiversx_sdk/core/proto/transaction_serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class ITransaction(Protocol):
guardian: str
signature: bytes
guardian_signature: bytes
relayer: str
relayer_signature: bytes


class ProtoSerializer:
Expand Down Expand Up @@ -66,4 +68,8 @@ def convert_to_proto_message(self, transaction: ITransaction) -> ProtoTransactio
proto_transaction.GuardAddr = Address.new_from_bech32(guardian_address).get_public_key()
proto_transaction.GuardSignature = transaction.guardian_signature

if transaction.relayer:
proto_transaction.Relayer = Address.new_from_bech32(transaction.relayer).get_public_key()
proto_transaction.RelayerSignature = transaction.relayer_signature

return proto_transaction
7 changes: 6 additions & 1 deletion multiversx_sdk/core/transaction.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ def __init__(self,
options: Optional[int] = None,
guardian: Optional[str] = None,
signature: Optional[bytes] = None,
guardian_signature: Optional[bytes] = None) -> None:
guardian_signature: Optional[bytes] = None,
relayer: Optional[str] = None,
relayer_signature: Optional[bytes] = None) -> None:
self.chain_id = chain_id
self.sender = sender
self.receiver = receiver
Expand All @@ -42,6 +44,9 @@ def __init__(self,
self.guardian = guardian or ""
self.guardian_signature = guardian_signature or bytes()

self.relayer = relayer or ""
self.relayer_signature = relayer_signature or bytes()

def __eq__(self, other: object) -> bool:
if not isinstance(other, Transaction):
return False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class IConfig(Protocol):
chain_id: str
min_gas_limit: int
gas_limit_per_byte: int
extra_gas_limit_for_relayed_v3: int


class RelayedTransactionsFactory:
Expand Down Expand Up @@ -72,6 +73,29 @@ def create_relayed_v2_transaction(self,
options=inner_transaction.options
)

def create_relayed_v3_transaction(self,
transaction: ITransaction,
relayer_address: IAddress) -> Transaction:
"""Relayer address must be in the same shard with sender address."""
gas_limit = transaction.gas_limit + self._config.extra_gas_limit_for_relayed_v3

return Transaction(
sender=transaction.sender,
receiver=transaction.receiver,
gas_limit=gas_limit,
chain_id=transaction.chain_id,
nonce=transaction.nonce,
value=transaction.value,
sender_username=transaction.sender_username,
receiver_username=transaction.receiver_username,
gas_price=transaction.gas_price,
data=transaction.data,
version=transaction.version,
options=transaction.options,
guardian=transaction.guardian,
relayer=relayer_address.to_bech32()
)

def _prepare_inner_transaction_for_relayed_v1(self, inner_transaction: ITransaction) -> str:
sender = Address.new_from_bech32(inner_transaction.sender).to_hex()
receiver = Address.new_from_bech32(inner_transaction.receiver).to_hex()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,29 @@ def test_compute_relayed_v2_transaction(self):
assert relayed_transaction.options == 0
assert relayed_transaction.gas_limit == 60414500
assert relayed_transaction.data.decode() == "relayedTxV2@000000000000000000010000000000000000000000000000000000000002ffff@0f@676574436f6e7472616374436f6e666967@fc3ed87a51ee659f937c1a1ed11c1ae677e99629fae9cc289461f033e6514d1a8cfad1144ae9c1b70f28554d196bd6ba1604240c1c1dc19c959e96c1c3b62d0c"

def test_relayed_v3(self):
alice = self.wallets["alice"]
alice_address = Address.new_from_bech32(alice.label)
bob = self.wallets["bob"]

tx = Transaction(
sender=bob.label,
receiver="erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u",
gas_limit=1_000_000,
chain_id=self.config.chain_id,
data=b"add@07",
nonce=15,
version=2,
options=0
)

relayed_tx = self.factory.create_relayed_v3_transaction(
transaction=tx,
relayer_address=alice_address
)

assert relayed_tx.sender == bob.label
assert relayed_tx.receiver == "erd1qqqqqqqqqqqqqqqpqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqzllls8a5w6u"
assert relayed_tx.relayer == alice.label
assert relayed_tx.gas_limit == 1_050_000
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ def __init__(self, chain_id: str) -> None:
# Configuration for smart contract operations
self.gas_limit_claim_developer_rewards = 6_000_000
self.gas_limit_change_owner_address = 6_000_000

self.extra_gas_limit_for_relayed_v3 = 50_000
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def test_get_nonfungible_token_of_account(self):
address = Address.new_from_bech32('erd1487vz5m4zpxjyqw4flwa3xhnkzg4yrr3mkzf5sf0zgt94hjprc8qazcccl')
result = self.api.get_nonfungible_token_of_account(address, "NFTEST-ec88b8", 1)

assert result.balance == 0
assert result.balance == 1
assert result.nonce == 1
assert result.collection == "NFTEST-ec88b8"
assert result.identifier == "NFTEST-ec88b8-01"
Expand Down
2 changes: 2 additions & 0 deletions multiversx_sdk/network_providers/transactions.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ class ITransaction(Protocol):
guardian: str
signature: bytes
guardian_signature: bytes
relayer: str
relayer_signature: bytes


class TransactionOnNetwork:
Expand Down

0 comments on commit 9e1374f

Please sign in to comment.