Source code for djwebdapp_ethereum.models

from django.db import models

from djwebdapp.models import Transaction
from djwebdapp.normalizers import Normalizer


[docs]class EthereumTransaction(Transaction): """ Base model for Ethereum transactions. .. py:attribute:: abi Smart contract ABI code. .. py:attribute:: bytecode Smart contract bytecode. """ contract = models.ForeignKey( 'self', on_delete=models.CASCADE, related_name='call_set', null=True, blank=True, help_text='Smart contract, appliable to method call', ) caller = models.ForeignKey( 'self', on_delete=models.CASCADE, null=True, related_name='_internal_calls', ) abi = models.JSONField( default=dict, blank=True, null=True, help_text='Smart contract ABI, if this is a smart contract', ) input = models.TextField( blank=True, null=True, help_text='Input hex string if any', ) bytecode = models.TextField( blank=True, null=True, help_text='Contract bytecode if this is a smart contract to deploy', )
[docs] def save(self, *args, **kwargs): """ Sets :py:attr:`~djwebdapp.models.Transaction.has_code` if :py:attr:`bytecode` is set. """ if self.bytecode and self.abi: self.has_code = True return super().save(*args, **kwargs)
[docs]class EthereumContract(EthereumTransaction): """ Base model class for Ethereum Contracts. .. py:attribute:: contract_name Name of the contract files, they are expected to be found in the ``contracts`` sub-directory of the Django App that holds the model that is inheriting from this class (your app) """ contract_name = None normalizer_class = Normalizer class Meta: proxy = True
[docs] def save(self, *args, **kwargs): """ Sets :py:attr:`~djwebdapp_ethereum.models.EthereumTransaction.abi` and :py:attr:`~djwebdapp_ethereum.models.EthereumTransaction.bytecode` if :py:attr:`contract_name` is set. """ if self.contract_name and not self.abi: with open(self.contract_path + '.abi', 'r') as f: self.abi = f.read() if self.contract_name and not self.bytecode: with open(self.contract_path + '.bin', 'r') as f: self.bytecode = f.read() return super().save(*args, **kwargs)
@property def is_internal(self): return bool(self.caller_id) @property def internal_calls(self): if self.is_internal: txgroup_internal_calls_qs = self.caller._internal_calls else: txgroup_internal_calls_qs = self._internal_calls tx_internal_calls_qs = txgroup_internal_calls_qs.filter( nonce__gte=self.nonce if self.nonce else 0, sender__address=self.contract.address, ) return tx_internal_calls_qs.order_by('nonce').all()
[docs]class EthereumCall(EthereumTransaction): """ Base model class for Ethereum contract function calls. """ class Meta: proxy = True