Как кодировать функции смарт-контракта Solidity CRUD: правильный путь
17 мая 2022 г.Вступление
Разработка смарт-контрактов и экономика Web3 все еще находятся в зачаточном состоянии, и во всем мире существует высокий спрос на разработчиков блокчейнов.
Согласно недавнему [отчету LinkedIn] (https://www.linkedin.com/posts/linkedin-news_theworkshift-economy-labormarket-activity-6887062336839016450-67iT/), объявления о вакансиях, содержащие такие термины, как биткойн, блокчейн и другие цифровые активы в 2021 году в США число связанных с ними должностей увеличилось на 395 процентов по сравнению с предыдущим годом. С ростом на 98 процентов это была самая быстрорастущая отрасль в истории, опередившая всю отрасль в четыре раза.
Развитие блокчейна имеет больше шансов найти работу вашей мечты с шестизначной суммой. Самое интересное, что большинство заданий в блокчейне выполняются удаленно, поэтому вам не нужно беспокоиться о местоположении.
Но как вы прыгаете и извлекаете выгоду из этого пространства? Это путем изучения того, как создавать вещи с помощью технологий.
Если вы ищете личного репетитора, который поможет вам ускорить разработку Web3, пожалуйста, запишитесь на занятие со мной.
С учетом сказанного, давайте перейдем к этому уроку…
Зачем вам осваивать функции CRUD в Solidity?
Умение создавать, читать, обновлять и удалять записи из блокчейна — это навык, который вы должны понимать. Да, вы можете удалить что-то из блокчейна (до некоторой степени), используя метод, который вы собираетесь изучить.
Навыки CRUD необходимы для эффективного создания системы, управляемой контентом, и, поскольку блокчейн служит базой данных для неизменного хранения записей, мудрость требует, чтобы вы понимали, как работать с этой технологией.
Опять же, если вы собираетесь работать над проектом блокчейна для компании или клиента, может возникнуть необходимость удалить некоторые ненужные записи, поэтому вам следует ACE свои навыки CRUD в Solidity прямо сейчас.
Что, если вы работаете над проектом блога web3 и знаете, что для очень плохих комментариев нужна кнопка удаления? В этом случае вам нужно будет удалить функциональность.
Вы видите, что хорошее знание CRUD станет неизбежным, когда вы углубитесь в разработку блокчейна.
Кстати, удаление записи из сети блокчейна немного отличается от того, как вы удаляете ее из обычной базы данных. Запись по-прежнему будет существовать в сети, но будет удалена из вашего приложения web3.
Полный пример ниже покажет вам шаг за шагом, как это сделать.
Пример функций CRUD
Это смарт-контракт, который я создал и протестировал; чтобы увидеть, как это работает, вы можете открыть его в редакторе ремиксов и запустить самостоятельно.
Но сначала закончите обучение; ниже приведена важная информация, объясняющая каждую функцию конкретно.
```javascript
//SPDX-идентификатор лицензии: MIT
прочность прагмы ^0,8,7;
договор Блог {
адрес государственного собственника;
uint256 public activePostCounter = 0;
uint256 public inactivePostCounter = 0;
uint256 частный счетчик сообщений = 0;
сопоставление (uint256 => адрес) public delPostOf;
отображение (uint256 => адрес) public authorOf;
отображение (адрес => uint256) общедоступных сообщений;
перечисление деактивировано { НЕТ, ДА }
структура PostStruct {
uint256 постидентификатор;
заголовок строки;
строковое описание;
адрес автора;
Деактивировано удалено;
создан uint256;
обновлен uint256;
PostStruct[] активные сообщения;
PostStruct[] inactivePosts;
действие события (
uint256 идентификатор поста,
строка actionType,
Деактивировано удалено,
адрес индексированного исполнителя,
uint256 создан
модификатор ownerOnly(){
require(msg.sender == owner, "Только владелец зарезервирован");
конструктор () {
владелец = msg.sender;
функция createPost(
название строки памяти,
описание строковой памяти
) внешние возвраты (bool) {
require(bytes(title).length > 0, "Заголовок не может быть пустым");
require(bytes(description).length > 0, "Описание не может быть пустым");
постСчетчик++;
authorOf[postCounter] = msg.sender;
сообщения[msg.sender]++;
активпосткаунтер++;
activePosts.push(
PostStruct(
постСчетчик,
заглавие,
описание,
сообщение.отправитель,
Деактивировано.НЕТ,
блок. временная метка,
block.timestamp
испустить действие (
постСчетчик,
"ПОСТ СОЗДАН",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
вернуть истину;
функция updatePost(
uint256 идентификатор поста,
название строки памяти,
описание строковой памяти
) внешние возвраты (bool) {
require(authorOf[postId] == msg.sender, "Неавторизованный объект");
require(bytes(title).length > 0, "Заголовок не может быть пустым");
require(bytes(description).length > 0, "Описание не может быть пустым");
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
activePosts[i].title = заголовок;
activePosts[i].description = описание;
activePosts[i].updated = block.timestamp;
испустить действие (
идентификатор поста,
"ПОСТ ОБНОВЛЕНО",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
вернуть истину;
функция showPost(
uint256 postId
) внешний вид возвращает (память PostStruct) {
Пост памяти PostStruct;
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
пост = активные посты[i];
обратный пост;
Функция внешнего вида getPosts() возвращает (память PostStruct[]) {
вернуть активные посты;
Функция getDeletedPost() ownerOnly возвращает внешнее представление (PostStruct[] memory) {
вернуть неактивные сообщения;
function deletePost(uint256 postId) external возвращает (bool) {
require(authorOf[postId] == msg.sender, "Неавторизованный объект");
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
activePosts[i].deleted = Деактивировано.YES;
activePosts[i].updated = block.timestamp;
inactivePosts.push(activePosts[i]);
delPostOf[идентификатор сообщения] = автор[идентификатор сообщения];
удалить активные посты[i];
удалить автора[postId];
postsOf[msg.sender]--;
инактивпосткаунтер++;
активпосткаунтер--;
испустить действие (
идентификатор поста,
"ПУБЛИКАЦИЯ УДАЛЕНА",
Деактивировано.ДА,
сообщение.отправитель,
block.timestamp
вернуть истину;
функция restorDeletedPost(
uint256 идентификатор поста,
адрес автора
) внешний возврат ownerOnly (bool) {
require(delPostOf[postId] == автор, "Непревзойденный автор");
for(uint i = 0; i < inactivePosts.length; i++) {
if(inactivePosts[i].postId == postId) {
inactivePosts[i].deleted = Деактивировано.NO;
inactivePosts[i].updated = block.timestamp;
activePosts.push(inactivePosts[i]);
удалить неактивные сообщения[i];
автор[идентификатор сообщения] = delPostOf[идентификатор сообщения];
удалить delPostOf[postId];
сообщения[автора]++;
inactivePostCounter--;
активпосткаунтер++;
испустить действие (
идентификатор поста,
"ПОСТ ВОССТАНОВЛЕН",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
вернуть истину;
Хорошо, давайте разберем этот смарт-контракт шаг за шагом; если вы новичок, не волнуйтесь; Я написал этот пример смарт-контракта, чтобы продемонстрировать простоту.
Шаг 1: Структура смарт-контракта
```javascript
//SPDX-идентификатор лицензии: MIT
прочность прагмы ^0,8,7;
договор Блог {
// здесь идет код...
Это типичная структура смарт-контракта; считайте его классом объектно-ориентированного программирования, потому что на самом деле он таков.
SPDX используется для указания типа лицензии смарт-контракта. Pragma относится к версии компилятора Solidity, которая будет использоваться для смарт-контракта. Наконец, смарт-контракт называется Blog.
Важно отметить, что имя файла всегда должно соответствовать имени класса; это обеспечит согласованность и предотвратит ненужные ошибки в вашем коде.
Шаг 2: Определение переменных контракта
```javascript
адрес государственного собственника;
uint256 public activePostCounter = 0;
uint256 public inactivePostCounter = 0;
uint256 частный счетчик сообщений = 0;
Здесь у нас есть два типа переменных: адрес и uint256. Адрес представляет собой учетную запись пользователя, тогда как uint256 представляет целое число без знака в диапазоне от 0 до 2256–1.
Владелец будет владеть учетной записью развертывателя, а activePostCounter
содержит количество доступных сообщений. inactivePostCounter
отслеживает удаленный пост на тот случай, если его нужно будет восстановить. postCounter
содержит общее количество сообщений в смарт-контракте, но оно является частным.
Шаг 3. Определение сопоставлений
```javascript
сопоставление (uint256 => адрес) public delPostOf;
отображение (uint256 => адрес) public authorOf;
отображение (адрес => uint256) общедоступных сообщений;
authorOf()
— это сопоставленная переменная, которая принимает postId
и возвращает адрес автора сообщения. Принимая во внимание, что postsOf()
отслеживает сообщения автора, а delPostOf() служит в качестве мусорной корзины для каждого автора.
Шаг 4. Определение перечисляемого
```javascript
перечисление деактивировано { НЕТ, ДА }
Это используется, чтобы указать, было ли сообщение удалено. Enum преобразует алфавитное значение в целые числа без знака, начинающиеся с нуля. Например, значения NO и YES станут равными 0 и 1 соответственно.
Шаг 5. Определение структуры
```javascript
структура PostStruct {
uint256 постидентификатор;
заголовок строки;
строковое описание;
адрес автора;
Деактивировано удалено; // Здесь мы используем перечисление
создан uint256;
обновлен uint256;
PostStruct[] активные сообщения;
PostStruct[] inactivePosts;
Структуры используются для определения сложных структур данных, состоящих из двух или более типов данных.
Мы указали в приведенном выше PostStruct
, что сообщение должно иметь идентификатор, заголовок, описание, автора, удаленный ключ, время создания и время обновления.
Далее мы сделали два массива: один для активных постов и один для неактивных постов или удаленных постов. Этот метод предотвращает потерю данных, но вы также можете использовать один массив и включать и выключать только удаленный ключ.
Однако это поднимает еще одну проблему: вам придется прочитать их все в своем внешнем приложении, прежде чем показывать активные сообщения. Я хотел бы избавить вас от этой поездки.
Шаг 6. Определение события
```javascript
действие события (
uint256 идентификатор поста,
строка actionType,
Деактивировано удалено,
адрес индексированного исполнителя,
uint256 создан
Мы определили динамическое событие для передачи важной информации о созданных, обновленных, удаленных и восстановленных функциях соответственно.
Шаг 7: Определение модификатора
модификатор ownerOnly(){
require(msg.sender == owner, "Только владелец зарезервирован");
Модификатор — это функция, которая изменяет поведение другой функции во время компиляции. Можно сказать, что это необходимое условие для выполнения функции.
В приведенном выше модификаторе мы указали, что вызывающая сторона функции, к которой будет прикреплен этот модификатор, должна быть владельцем или исполнителем смарт-контракта.
Шаг 8. Определение конструктора
```javascript
конструктор () {
владелец = msg.sender;
Основываясь на ваших знаниях ООП, конструктор всегда является первой функцией, которая запускается при создании экземпляра класса. Построение ООП взаимно для смарт-контрактов.
Первая функция, которая запускается при развертывании этого смарт-контракта, — это конструктор, и мы указали, что он должен сделать владельцем того, кто развернул смарт-контракт.
Шаг 9: Функция createPost()
```javascript
функция createPost(
название строки памяти,
описание строковой памяти
) внешние возвраты (bool) {
// Проверяет наличие пустой строки
require(bytes(title).length > 0, "Заголовок не может быть пустым");
require(bytes(description).length > 0, "Описание не может быть пустым");
// Выполняет вычисления
постСчетчик++;
authorOf[postCounter] = msg.sender;
сообщения[msg.sender]++;
активпосткаунтер++;
// Добавляет запись в массив
activePosts.push(
PostStruct(
постСчетчик,
заглавие,
описание,
сообщение.отправитель,
Деактивировано.НЕТ,
блок. временная метка,
block.timestamp
// Выдает созданное событие
испустить действие (
постСчетчик,
"ПОСТ СОЗДАН",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
// Возвращает успех
вернуть истину;
Эта функция выполняет пост-создание за пять шагов.
Во-первых, он проверяет, что вы отправляете в смарт-контракт реальную информацию, а не просто пустую строку.
Во-вторых, он выполняет некоторые вычисления, такие как увеличение количества сообщений для блога и для автора, в том числе делает автора владельцем сообщения.
В-третьих, он добавляет пост в «activePosts», используя «PostStruct», определенный ранее.
В-четвертых, он выдает событие «POST CREATED», которое отключает EVM, что необходимо для обогащения информации, полученной в транзакции.
Наконец, мы вернули истинный логический ключ, указывающий, что вся функция выполнена успешно.
Шаг 10: Функция updatePost().
```javascript
функция updatePost(
uint256 идентификатор поста,
название строки памяти,
описание строковой памяти
) внешние возвраты (bool) {
// Проверяет наличие пустой строки
require(authorOf[postId] == msg.sender, "Неавторизованный объект");
require(bytes(title).length > 0, "Заголовок не может быть пустым");
require(bytes(description).length > 0, "Описание не может быть пустым");
// Изменяет запись поста
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
activePosts[i].title = заголовок;
activePosts[i].description = описание;
activePosts[i].updated = block.timestamp;
// Генерирует обновленное событие
испустить действие (
идентификатор поста,
"ПОСТ ОБНОВЛЕНО",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
// Возвращает успех
вернуть истину;
Эта функция работает как функция createPost(). Разница в том, что при проверке пустой строки функция updatePost()
гарантирует, что лицо, обновляющее функцию, является владельцем (автором) сообщения.
Затем он нацеливается на конкретную публикацию по идентификатору и обновляет запись.
Шаг 11: Функция showPost()
```javascript
функция showPost(
uint256 postId
) внешний вид возвращает (память PostStruct) {
Пост памяти PostStruct;
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
пост = активные посты[i];
обратный пост;
Это просто возвращает к нашему сообщению путем рекурсивного поиска совпадения в массиве activePost
.
Шаг 12: Функция getPosts().
```javascript
Функция внешнего вида getPosts() возвращает (память PostStruct[]) {
вернуть активные посты;
Возвращает все доступные активные сообщения в блоге.
Шаг 13: Функция getDeletedPost()
```javascript
функция getDeletedPost()
Внешний вид ownerOnly возвращает (память PostStruct []) {
вернуть неактивные сообщения;
Это просто возвращает все удаленные сообщения и может быть доступно только владельцу блога.
Шаг 14: Функция deletePost()
```javascript
function deletePost(uint256 postId) external возвращает (bool) {
// проверяем, принадлежит ли запись пользователю
require(authorOf[postId] == msg.sender, "Неавторизованный объект");
// находим и удаляем пост
for(uint i = 0; i < activePosts.length; i++) {
if(activePosts[i].postId == postId) {
activePosts[i].deleted = Деактивировано.YES;
activePosts[i].updated = block.timestamp;
inactivePosts.push(activePosts[i]);
delPostOf[идентификатор сообщения] = автор[идентификатор сообщения];
удалить активные посты[i];
удалить автора[postId];
// Перекалибровать счетчики
postsOf[msg.sender]--;
инактивпосткаунтер++;
активпосткаунтер--;
// Выдает событие
испускать действие (
идентификатор поста,
"ПУБЛИКАЦИЯ УДАЛЕНА",
Деактивировано.ДА,
сообщение.отправитель,
block.timestamp
// Возвращает успех
вернуть истину;
Вышеупомянутая функция была достигнута в четыре этапа.
Во-первых, мы проверили, что удаление сообщения принадлежит владельцу, затем мы нашли сообщение, удалили его и сгенерировали событие «POST DELETED», которое также возвращает логическое значение true.
Обратите внимание, что поведение удаления не выполняется, как в обычной базе данных, вместо этого мы указали два массива; активные сообщения
и неактивные сообщения
. Всякий раз, когда мы удаляем пост, он перемещается в массив inactivePosts, и только владелец блога может восстановить его по запросу автора поста.
Шаг 15. Функция пост-восстановления
```javascript
функция restorDeletedPost(
uint256 идентификатор поста,
адрес автора
) внешний возврат ownerOnly (bool) {
// проверяет, существует ли сообщение в корзине пользователя
require(delPostOf[postId] == автор, "Непревзойденный автор");
// Находит и восстанавливает запись к автору
for(uint i = 0; i < inactivePosts.length; i++) {
if(inactivePosts[i].postId == postId) {
inactivePosts[i].deleted = Деактивировано.NO;
inactivePosts[i].updated = block.timestamp;
activePosts.push(inactivePosts[i]);
удалить неактивные сообщения[i];
автор[идентификатор сообщения] = delPostOf[идентификатор сообщения];
удалить delPostOf[postId];
// Перекалибровывает счетчик, чтобы отразить восстановленный пост
сообщения[автора]++;
inactivePostCounter--;
активпосткаунтер++;
// Генерирует событие восстановления
испустить действие (
идентификатор поста,
"ПОСТ ВОССТАНОВЛЕН",
Деактивировано.НЕТ,
сообщение.отправитель,
block.timestamp
// возвращает успех
вернуть истину;
Всякий раз, когда пост восстанавливается, он перемещается из массива inactivePosts в массив activePosts.
Стоит отметить, что вы можете разработать свой шаблон удаления немного иначе, чем мой. Вы можете использовать созданную выше структуру enum Deactivated и удалить ее, только переключив состояние удаления на YES или NO.
Мужчины и братья, именно так вы разрушаете функции Solidity CRUD…
Вывод
Путешествовать с вами по этому руководству было здорово, надеюсь, вы получили ценную информацию о том, как писать CRUD-функции для смарт-контрактов Solidity.
Я хочу сообщить вам о моих частных уроках репетиторства для тех, кто хочет прыгнуть в пространство web3. Если вы заинтересованы, пожалуйста, забронируйте меня на моем сайте.
Это все для этого урока, пожалуйста, поставьте лайк и поделитесь…
Рад видеть вас в следующем уроке, а пока наслаждайтесь!
Об авторе
Госпел Дарлингтон начал свой путь в качестве инженера-программиста в 2016 году. За эти годы он приобрел полноценные навыки работы со стеками JavaScript, такими как React, ReactNative, NextJs, а теперь и с блокчейном.
В настоящее время он работает фрилансером, создает приложения для клиентов и пишет технические руководства, обучая других тому, что делает он.
Евангелие в Дарлингтоне открыто и доступно для вас. Вы можете связаться с ним на LinkedIn, Facebook, Github или на его веб-сайте.
Оригинал