Skip to content
6 changes: 6 additions & 0 deletions ethereum.links.action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,9 @@ entity.ethereum_server.add_server_form:
title: 'Add Ethereum node'
appears_on:
- ethereum.settings

entity.ethereum_address.add_form:
route_name: entity.ethereum_address.add_form
title: 'Add address'
appears_on:
- entity.ethereum_address.collection
6 changes: 6 additions & 0 deletions ethereum.links.menu.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,9 @@ ethereum.settings:
parent: ethereum.admin_index
title: 'Ethereum Network Configuration'
description: 'Configure how Drupal connects to Ethereum.'

entity.ethereum_address.collection:
title: 'Ethereum addresses'
parent: ethereum.admin_index
description: 'Create and manage Ethereum addresses.'
route_name: entity.ethereum_address.collection
4 changes: 4 additions & 0 deletions ethereum.links.task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
entity.ethereum_address.collection:
title: List
route_name: entity.ethereum_address.collection
base_route: entity.ethereum_address.collection
9 changes: 9 additions & 0 deletions ethereum.module
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,15 @@ function ethereum_field_formatter_info_alter(array &$info) {
$info['basic_string']['field_types'][] = 'ethereum_address';
}

/**
* Implements hook_views_data_alter().
*/
function ethereum_views_data_alter(array &$data) {
// Provide a nice list of options for the 'network' filter.
$data['ethereum_address']['network']['filter']['id'] = 'in_operator';
$data['ethereum_address']['network']['filter']['options callback'] = 'Drupal\ethereum\Controller\EthereumController::getNetworksAsOptions';
}

/**
* Implements hook_js_settings_alter().
*
Expand Down
168 changes: 168 additions & 0 deletions src/Entity/EthereumAddress.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
<?php

namespace Drupal\ethereum\Entity;

use Drupal\Core\Entity\ContentEntityBase;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ethereum\EthereumAddressInterface;

/**
* Defines the ethereum_address entity class.
*
* @ContentEntityType(
* id = "ethereum_address",
* label = @Translation("Ethereum address"),
* label_collection = @Translation("Ethereum addresses"),
* label_singular = @Translation("address"),
* label_plural = @Translation("addresses"),
* label_count = @PluralTranslation(
* singular = "@count address",
* plural = "@count addresses"
* ),
* handlers = {
* "storage_schema" = "Drupal\ethereum\EthereumAddressStorageSchema",
* "view_builder" = "Drupal\Core\Entity\EntityViewBuilder",
* "views_data" = "Drupal\views\EntityViewsData",
* "form" = {
* "default" = "Drupal\Core\Entity\ContentEntityForm",
* "delete" = "Drupal\Core\Entity\ContentEntityDeleteForm"
* },
* "route_provider" = {
* "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider",
* },
* "list_builder" = "Drupal\ethereum\EthereumAddressListBuilder",
* },
* admin_permission = "administer site configuration",
* base_table = "ethereum_address",
* entity_keys = {
* "id" = "id",
* "uuid" = "uuid",
* "label" = "address",
* },
* field_ui_base_route = "entity.ethereum_address.collection",
* links = {
* "canonical" = "/admin/config/ethereum/addresses/address/{ethereum_address}",
* "add-form" = "/admin/config/ethereum/addresses/add",
* "edit-form" = "/admin/config/ethereum/addresses/address/{ethereum_address}/edit",
* "delete-form" = "/admin/config/ethereum/addresses/address/{ethereum_address}/delete",
* "collection" = "/admin/config/ethereum/addresses",
* },
* constraints = {
* "EthereumAddressNetwork" = {}
* },
* )
*/
class EthereumAddress extends ContentEntityBase implements EthereumAddressInterface {

/**
* {@inheritdoc}
*/
public function getAddress() {
return $this->get('address')->value;
}

/**
* {@inheritdoc}
*/
public function setAddress($address) {
$this->set('address', $address);
return $this;
}

/**
* {@inheritdoc}
*/
public function getNetworkId() {
return $this->get('network')->value;
}

/**
* {@inheritdoc}
*/
public function setNetworkID($network_id) {
$this->set('network', $network_id);
return $this;
}

/**
* {@inheritdoc}
*/
public function isContract() {
return (bool) $this->get('contract')->value;
}

/**
* {@inheritdoc}
*/
public function setContract($is_contract) {
$this->set('contract', $is_contract);
return $this;
}

/**
* {@inheritdoc}
*/
public static function baseFieldDefinitions(EntityTypeInterface $entity_type) {
$fields = parent::baseFieldDefinitions($entity_type);

// Ensure that we can store as many addresses as possible.
$fields['id']->setSetting('size', 'big');

$fields['address'] = BaseFieldDefinition::create('ethereum_address')
->setLabel(new TranslatableMarkup('Address'))
->setRequired(TRUE)
->setReadOnly(TRUE)
->setDisplayOptions('view', [
'label' => 'hidden',
'type' => 'ethereum_address',
])
->setDisplayOptions('form', [
'type' => 'ethereum_address',
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);;

$fields['network'] = BaseFieldDefinition::create('list_string')
->setLabel(new TranslatableMarkup('Network'))
->setDescription(new TranslatableMarkup('The Ethereum network on which this address exists.'))
->setRequired(TRUE)
->setReadOnly(TRUE)
->setDefaultValueCallback('\Drupal\ethereum\Entity\EthereumAddress::getCurrentNetworkId')
->setSetting('allowed_values_function', '\Drupal\ethereum\Controller\EthereumController::getNetworksAsOptions')
->setDisplayOptions('form', [
'type' => 'options_select',
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);


$fields['contract'] = BaseFieldDefinition::create('boolean')
->setLabel(new TranslatableMarkup('Is contract'))
->setDefaultValue(FALSE)
->setReadOnly(TRUE)
->setDisplayOptions('form', [
'type' => 'boolean_checkbox',
])
->setDisplayConfigurable('view', TRUE)
->setDisplayConfigurable('form', TRUE);

return $fields;
}

/**
* Default value callback for the 'network' base field.
*
* @see ::baseFieldDefinitions()
*
* @return array
* An array of default values.
*/
public static function getCurrentNetworkId() {
$current_server = \Drupal::config('ethereum.settings')->get('current_server');
$server = EthereumServer::load($current_server);
return [$server->getNetworkId()];
}

}
66 changes: 66 additions & 0 deletions src/EthereumAddressInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php

namespace Drupal\ethereum;

use Drupal\Core\Entity\ContentEntityInterface;

/**
* Provides an interface defining an ethereum_address entity.
*/
interface EthereumAddressInterface extends ContentEntityInterface {

/**
* Gets the Ethereum address.
*
* @return string
* The Ethereum address.
*/
public function getAddress();

/**
* Sets the address.
*
* @param string $address
* The address.
*
* @return $this
*/
public function setAddress($address);

/**
* Gets the address' network ID.
*
* @return string
* The Ethereum network ID where this address exists.
*/
public function getNetworkId();

/**
* Sets the address' Ethereum network ID.
*
* @param string $network_id
* The address' network ID.
*
* @return $this
*/
public function setNetworkID($network_id);

/**
* Returns whether the address is a contract.
*
* @return bool
* TRUE if the address is a contract.
*/
public function isContract();

/**
* Sets whether the address is a contract.
*
* @param bool $is_contract
* TRUE to mark this address as a contract, FALSE otherwise.
*
* @return $this
*/
public function setContract($is_contract);

}
36 changes: 36 additions & 0 deletions src/EthereumAddressListBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Drupal\ethereum;

use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityListBuilder;
use Drupal\ethereum\Controller\EthereumController;

/**
* Defines a class to build a listing of ethereum_address entities.
*/
class EthereumAddressListBuilder extends EntityListBuilder {

/**
* {@inheritdoc}
*/
public function buildHeader() {
$header = [
'address' => $this->t('Address'),
'network' => $this->t('Network'),
];
return $header + parent::buildHeader();
}

/**
* {@inheritdoc}
*/
public function buildRow(EntityInterface $entity) {
/** @var \Drupal\ethereum\EthereumAddressInterface $entity */
$networks = EthereumController::getNetworks();
$row['address'] = $entity->getAddress();
$row['network'] = $networks[$entity->getNetworkId()]['label'];
return $row + parent::buildRow($entity);
}

}
51 changes: 51 additions & 0 deletions src/EthereumAddressStorageSchema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Drupal\ethereum;

use Drupal\Core\Entity\ContentEntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema;
use Drupal\Core\Field\FieldStorageDefinitionInterface;

/**
* Defines the ethereum_address schema handler.
*/
class EthereumAddressStorageSchema extends SqlContentEntityStorageSchema {

/**
* {@inheritdoc}
*/
protected function getEntitySchema(ContentEntityTypeInterface $entity_type, $reset = FALSE) {
$schema = parent::getEntitySchema($entity_type, $reset);

// Add a UNIQUE index on the 'address' and 'network' fields because two
// identical addresses can not live on the same network.
$schema[$this->storage->getBaseTable()]['unique keys'] += [
'ethereum_address__address_network' => ['address', 'network'],
];

return $schema;
}

/**
* {@inheritdoc}
*/
protected function getSharedTableFieldSchema(FieldStorageDefinitionInterface $storage_definition, $table_name, array $column_mapping) {
$schema = parent::getSharedTableFieldSchema($storage_definition, $table_name, $column_mapping);
$field_name = $storage_definition->getName();

if ($table_name == $this->storage->getBaseTable()) {
switch ($field_name) {
case 'address':
$schema['fields'][$field_name]['not null'] = TRUE;
break;
case 'network':
$schema['fields'][$field_name]['not null'] = TRUE;
$schema['fields'][$field_name]['length'] = 10;
break;
}
}

return $schema;
}

}
Loading