# HF18: Изменения в cli\_wallet

***Эта страница содержит информацию об изменениях в клиентском приложении cli\_wallet, предоставляющих возможность создания транзакции произвольного вида в ручном режиме.***

Клиентское приложение `cli_wallet` (виртуальный кошелек) поставляется вместе с программой-эмулятором демоном (от англ. daemon). Данное приложение является одним из основных программных устройств, широко используемым участниками биржевых торгов. Приложение обеспечивает выполнение балансовых операций со счетами виртуальных кошельков клиентов, а также создание постов, голосование за посты и пр.

Целью доработок `cli_wallet` в HF·18 являлось создание удобного программного инструмента, обеспечивающего создание транзакции произвольного вида в ручном режиме.

В предыдущих версиях блокчейна создание транзакции выполнялось только в автоматическом режиме с подключением JS-, Python- и GO-библиотек. Главными достоинствами автоматического создания транзакции являлись быстрота и избавление пользователей от трудоемких операций. Недостатком такой реализации являлось наличие фиксированного набора команд, ограничивающего пользователей в возможности манипулирования параметрами.

В версии HF·18 создан конструктор, обеспечивающий формирование транзакций с произвольным набором выполняемых операций. С помощью конструктора пользователь может задать перечень операций с их описанием. Пользователь также может добавлять, изменять и редактировать операции в создаваемой транзакции. Каждая отдельная операция выполняется отдельным методом, входящим в состав методов `cli_wallet`.

Доработка заключается в добавлении необходимых методов в `cli_wallet` и выполнена в соответствии с требованиями поставленной задачи №542.

## Новые методы в cli\_wallet для расширения возможностей API

Клиентское приложение `cli_wallet` дополнено новыми методами, реализующими новый программный компонент — конструктор транзакций. В отличие от предыдущих версий блокчейна пользователь с помощью конструктора может формировать транзакцию произвольного вида по своему усмотрению. Кроме этого, конструктор позволяет создавать несколько транзакций для одновременного выполнения операций и идентифицировать каждую отдельную транзакцию. Доработка не вносит изменения в работу API, а только расширяет его возможности. Только два метода — `create_account` и `create_account_with_keys`, входящие в прежний состав методов приложения `cli_wallet` были незначительно модифицированы.

### Метод create\_account\_delegated

Этот метод позволяет создавать публичные ключи `owner`, `active`, `posting` и `memo` для нового аккаунта. За создание аккаунта в качестве комиссионных отчислений с баланса кошелька создателя аккаунта (автора) снимается определенная сумма `fee`. Величина этих отчислений не может быть меньше значения параметра `account_creation_fee`, устанавливаемого по результатам голосования делегатов. Параметр `fee` показывает изначальный базовый баланс кошелька аккаунта, необходимый для его существования в системе. С баланса кошелька создателя аккаунта снимается криптовалюта в виде Голоса (Golos) и зачисляется на баланс кошелька нового аккаунта в виде Силы Голоса (VESTS). Размер комиссионных отчислений, а также другую информацию от блокчейна, можно найти в выдаче команды `wallet`, имеющей вид `“account_creation_fee”:”X.000 GOLOS”`.

Затрачиваемое на создание аккаунта количество криптовалюты не может быть возвращено обратно в кошелек создателя.

Создатель аккаунта может делегировать часть Силы Голоса на новый аккаунт. В этом случае делегированная часть будет также списана с баланса Силы Голоса его кошелька и зачислена на баланс Силы Голоса нового аккаунта. Делегированная Сила Голоса может быть возвращена в кошелек создателя через определенный период, длительность которого определяется голосованием.

Метод имеет следующий вид:

```
annotated_signed_transaction create_account_delegated(
    string creator,
    asset steem_fee, 
    asset delegated_vests, 
    string new_account_name,
    string json_meta,
    bool broadcast
);
```

где:\
`creator` — пользователь, который создает новый аккаунт;\
`steem_fee` — сумма комиссионных отчислений в криптовалюте Голос, снимаемая с баланса кошелька пользователя за создание нового аккаунта и зачисляемая на баланс кошелька созданного аккаунта в криптовалюте Сила Голоса. Эта сумма не может быть возвращена обратно в кошелек создателя аккаунта;\
`delegated_vests` — сумма комиссионных отчислений в криптовалюте Сила Голоса, снимаемая с баланса кошелька пользователя за операцию делегирования и зачисляемая на баланс кошелька нового аккаунта в криптовалюте Сила Голоса. Эта сумма может быть возвращена обратно в кошелек создателя аккаунта по истечении определенного периода, устанавливаемого голосованием делегатов;\
`new_account_name` — имя нового аккаунта;\
`json_meta` — метаданные профиля нового аккаунта поля `json_metadata`;\
`broadcast` — ‘true’, если транзакция пересылается на демон; ‘false’, если выполняется базовый контроль с выдачей подписанной транзакции на консоль.

### Метод create\_account\_with\_keys\_delegated

Этот метод используется для создания новых аккаунтов через вызов операции `account_create`. В отличие от метода `create_account`, который обеспечивает генерацию ключей для нового аккаунта автоматически, метод `create_account_with_keys_delegated` требует явного задания ключей для нового аккаунта. Создатель аккаунта обязан иметь соответствующий ключ.

Созданный аккаунт не может контролироваться его кошельком. С баланса кошелька создателя снимается сумма комиссионных отчислений в криптовалюте Голос и зачисляется на баланс кошелька нового аккаунта в криптовалюте Сила Голоса. Метод имеет следующий вид:

```
annotated_signed_transaction create_account_with_keys_delegated(
    string creator,
    asset steem_fee,
    asset delegated_vests,
    string newname,
    string json_meta,
    public_key_type owner,
    public_key_type active,
    public_key_type posting,
    public_key_type memo,
    bool broadcast
) const;
```

где:\
`creator` — пользователь, который создает новый аккаунт;\
`steem_fee` — сумма комиссионных отчислений в криптовалюте Голос, снимаемая с баланса кошелька пользователя за создание нового аккаунта и зачисляемая на баланс кошелька созданного аккаунта в криптовалюте Сила Голоса. Эта сумма не может быть возвращена обратно в кошелек создателя аккаунта;\
`delegated_vests` — сумма комиссионных отчислений в криптовалюте Сила Голоса, снимаемая с баланса кошелька пользователя за операцию делегирования и зачисляемая на баланс кошелька нового аккаунта в криптовалюте Сила Голоса. Эта сумма может быть возвращена обратно в кошелек создателя аккаунта по истечении определенного периода, устанавливаемого голосованием делегатов;\
`newname` — имя нового аккаунта;\
`json_meta` — метаданные профиля нового аккаунта поля `json_metadata`;\
`owner` — значение публичного ключа `owner` нового аккаунта;\
`active` — значение публичного ключа `active` нового аккаунта;\
`posting` — значение публичного ключа `posting` нового аккаунта;\
`memo` — значение публичного ключа `memo` нового аккаунта;\
`broadcast` — ‘true’, если транзакция пересылается на демон.

### Метод delegate\_vesting\_shares

Метод обеспечивает делегирование части криптовалюты Силы Голоса с одного аккаунта на другой. Метод имеет следующий вид:

```
annotated_signed_transaction delegate_vesting_shares(
    string delegator,
    string delegatee,
    asset vesting_shares,
    bool broadcast
);
```

где:\
`delegator` — имя аккаунта, который делегирует Силу Голоса;\
`delegatee` — имя аккаунта, на который делегируется Сила Голоса;\
`vesting_shares` — сумма делегирования;\
`broadcast` — ‘true’, если транзакция пересылается на демон.

### Метод begin\_builder\_transaction

Метод вызывает операцию создания конструктора транзакций и возвращает уникальный номер созданного конструктора. Начальное значение уникального номера принимается равным «0» и увеличивается на единицу с каждым вызовом метода. Метод имеет следующий вид:

```
transaction_handle_type begin_builder_transaction();
```

### Метод get\_prototype\_operation

Метод используется для получения и заполнения шаблона для операции, создаваемой с помощью другого метода `add_operation_to_builder_transaction`. Метод возвращает неинициализированный объект в виде заданной последовательности операций. Созданный объект может быть дополнен любой операцией с помощью вызова `add_operation_to_builder_transaction()`.

Предварительно необходимо определить json-формат данных операции, чтобы получить соответствующий шаблон. Метод имеет следующий вид:

```
operation get_prototype_operation(
    string operation_type
);
```

где:\
`operation_type` — тип операции. Операция должна быть определена в файле `steem/chain/operations.hpp`.

### Метод add\_operation\_to\_builder\_transaction

Этот метод используется для добавления операции в список операций конструктора транзакций. Метод имеет следующий вид:

```
void add_operation_to_builder_transaction(
    transaction_handle_type handle,
    const operation& op
);
```

где:\
`handle` — уникальный номер конструктора;\
`op` — добавляемая операция.

### Метод add\_operation\_copy\_to\_builder\_transaction

Метод обеспечивает копирование операции между конструкторами транзакций. Каждый их конструкторов идентифицируется значением параметра `handler`, возвращаемого методом `begin_builder_transaction()`. Метод имеет следующий вид:

```
void add_operation_copy_to_builder_transaction(
    transaction_handle_type src_handle,
    transaction_handle_type dst_handle,
    uint32_t op_index
);
```

где:\
`src_handle` — уникальный номер конструктора, из которого копируется операция;\
`dst_handle` — уникальный номер конструктора, на который копируется операция;\
`op_index` — номер копируемой операции.

### Метод replace\_operation\_in\_builder\_transaction

Метод обеспечивает замену операции в конструкторе транзакций под номером `op_index` на операцию `op`. Метод имеет следующий вид:

```
void replace_operation_in_builder_transaction(
    transaction_handle_type handle,
    unsigned op_index,
    const operation& op
);
```

где:\
`handle` — уникальный номер конструктора;\
`op_index` — номер операции в конструкторе транзакций, которую необходимо заменить;\
`op` — заменяющая операция.

### Метод preview\_builder\_transaction

Метод обеспечивает поиск и получение конструктора транзакций по заданному идентификационному номеру из списка конструкторов. Метод имеет следующий вид:

```
transaction preview_builder_transaction(
    transaction_handle_type handle
);
```

где:\
`handle` — уникальный номер получаемого конструктора.

### Метод sign\_builder\_transaction

Метод используется для подписания всех транзакций в конструкторе транзакций. Метод имеет следующий вид:

```
signed_transaction sign_builder_transaction(
    transaction_handle_type handle,
    bool broadcast
);
```

где:\
`handle` — уникальный номер конструктора транзакций;\
`broadcast` — ‘true’, если подписанные транзакции необходимо переслать на демон.

### Метод propose\_builder\_transaction

Метод используется для создания конструктора предлагаемых транзакций. Метод имеет следующий вид:

```
signed_transaction propose_builder_transaction(
    transaction_handle_type handle,
    std::string author,
    std::string title,
    std::string memo,
    time_point_sec expiration = time_point::now() + fc::minutes(1),
    time_point_sec review_period_time = time_point::min(),
    bool broadcast
);
```

где:\
`handle` — уникальный номер создаваемого конструктора транзакций;\
`author` — автор предлагаемой транзакции;\
`title` — заголовок предлагаемой транзакции;\
`memo` — примечание, текст которого дополняет смысловое значение заголовка;\
`expiration` — время, по истечении которого прекращается подписание транзакции;\
`review_period_time` — период, выделенный для подписания транзакции;\
`broadcast` — ‘true’, если транзакция пересылается на демон.

### Метод remove\_builder\_transaction

Метод обеспечивает удаление конструктора транзакций по заданному идентификационному номеру. Метод имеет следующий вид:

```
void remove_builder_transaction(
    transaction_handle_type handle
);
```

где:\
`handle` — уникальный номер конструктора транзакций. Этот номер уменьшается на единицу после каждого вызова метода.

### Метод approve\_proposal

Метод обеспечивает проверку и сбор подписей на предложенную транзакцию. Метод возвращает подписанную версию транзакции.

Поскольку для подписи транзакции используются три типа ключей (`owner`, `active` и `posting`), подсчет подписей каждого типа ключей выполняется отдельно. Для этого в методе находится специальный структурный параметр `delta`, в котором содержатся актуальные данные результатов голосования по каждому типу ключей. Структура параметра имеет следующий вид:

```javascript
struct approval_delta {
    vector<string> active_approvals_to_add; // список необходимых аккаунтов, которые должны
            // поставитьподпись вида «active» для одобрения предложенной транзакции
    vector<string> active_approvals_to_remove; // список необходимых аккаунтов, чьи подписи
            // вида «active» должны быть удалены из списка подписей, которые одобрили
            // транзакцию
    vector<string> owner_approvals_to_add; // список необходимых аккаунтов, которые должны  
            // поставить подпись вида «owner» для одобрения предложенной транзакции
    vector<string> owner_approvals_to_remove; // список необходимых аккаунтов, чьи подписи  
            // вида «owner» должны быть удалены из списка подписей, которые одобрили
            // транзакцию
    vector<string> posting_approvals_to_add; // список необходимых аккаунтов, которые должны
            // поставить подпись вида «posting» для одобрения предложенной транзакции
    vector<string> posting_approvals_to_remove; // список необходимых аккаунтов, чьи подписи
            // вида «posting» должны быть удалены из списка подписей, которые одобрили
            // транзакцию
    vector<string> key_approvals_to_add; // список подписей вида «public», которые необходимо
            // получить для одобрения транзакции
    vector<string> key_approvals_to_remove; // список подписей вида «public», которые необходимо
            // удалить из списка подписей, которые одобрили транзакцию
}
```

Метод имеет следующий вид:

```
signed_transaction approve_proposal(
    std::string author,
    std::string title,
    approval_delta delta,
    bool broadcast
);
```

где:\
`author` — автор, предложенной транзакции;\
`title` — заголовок предложенной на подпись транзакции;\
`delta` — список подписей, необходимых для одобрения транзакции. В JSON-формате список может быть пустым;\
`broadcast` — ‘true’, если транзакция пересылается на демон; ‘false’, если выполняется базовый контроль с выдачей подписанной транзакции на консоль.

### Метод get\_proposed\_transactions

Метод обеспечивает получение информации о всех предложенных транзакция, применительно к одному и тому же аккаунту. Для получения информации об ограниченном количестве транзакций, необходимо задать начальный номер транзакции и пороговое значение `limit`. Метод имеет следующий вид:

```
std::vector<database_api::proposal_api_object> get_proposed_transactions(
    std::string account,
    uint32_t from,
    uint32_t limit
);
```

где:\
`account` — аккаунт, информацию о предложенных транзакциях которого необходимо получить;\
`from` — начальный номер транзакции;\
`limit` — пороговое значение количества транзакций.

## Модифицированные методы в приложении cli\_wallet

Следующие методы не являются новыми в приложении `cli_wallet` и уже использовались в предыдущих версиях блокчейна. Они изменены незначительно.

### Метод create\_account

Метод обеспечивает создание аккаунта с автоматической генерацией ключей. Метод использует операцию `account_create` и возвращает созданный аккаунт. Доработка состоит из добавления параметра `fee`. Метод имеет следующий вид:

```
annotated_signed_transaction create_account(
    string creator,
    string new_account_name,
    string json_meta,
    asset fee,
    bool broadcast
);
```

где:\
`creator` — пользователь, создающий новый акаунт;\
`new_account_name` — имя нового аккаунта;\
`json_meta` — метаданные профиля нового аккаунта поля `json_metadata`;\
`fee` — сумма комиссионных отчислений в криптовалюте Голос, снимаемая с баланса кошелька пользователя за создание нового аккаунта и зачисляемая на баланс кошелька созданного аккаунта в криптовалюте Сила Голоса. Эта сумма не может быть меньше значения `account_creation_fee`, устанавливаемого по результатам голосования делегатов;\
`broadcast` — ‘true’, если транзакция пересылается на демон; ‘false’, если выполняется базовый контроль с выдачей подписанной транзакции на консоль.

### Метод create\_account\_with\_keys

Метод обеспечивает создание аккаунта и требует явного задания ключей. Доработка состоит из добавления параметра `fee`. Метод имеет следующий вид:

```
annotated_signed_transaction create_account_with_keys(  
    string creator,  
    string newname,  
    string json_meta,  
    asset fee,  
    public_key_type owner,  
    public_key_type active,  
    public_key_type posting,  
    public_key_type memo,  
    bool broadcast  
) const;
```

где:\
`creator` — пользователь, который создает новый аккаунт;\
`newname` — имя нового аккаунта;\
`json_meta` — метаданные профиля нового аккаунта поля json\_metadata;\
`fee` — сумма комиссионных отчислений в криптовалюте Голос, снимаемая с баланса кошелька пользователя за создание нового аккаунта и зачисляемая на баланс кошелька созданного аккаунта в криптовалюте Сила Голоса. Эта сумма не может быть меньше значения `account_creation_fee`, устанавливаемого по результатам голосования делегатов;\
`owner` — значение публичного ключа `owner` нового аккаунта;\
`active` — значение публичного ключа `active` нового аккаунта;\
`posting` — значение публичного ключа `posting` нового аккаунта;\
`memo` — значение публичного ключа `memo` нового аккаунта;\
`broadcast` — ‘true’, если транзакция пересылается на демон.

## Этапы создания транзакций произвольной формы

Процедура создания транзакций, подписания и передача их на демон в ручном режиме включает в себя следующие основные этапы:

**1. Создание конструктора транзакций.** На начальном этапе необходимо по API вызвать метод `begin_builder_transaction`. В результате вызова будет получено значение параметра `HANDLE` — идентификационный номер конструктора транзакций. По этому номеру будет вызываться созданный конструктор для формирования транзакций.

**2. Создание набора операций.** На этом этапе создается набор необходимых для выполнения в транзакции операций с помощью вызова `add_operation_to_builder_transaction $HANDLE [opID, {operation}]` по API. Полученный на начальном этапе конструктор позволяет создать произвольный набор операций в ручном режиме, а также изменять и редактировать их. Каждая из операций будет доступна по присвоенному ей идентификационному номеру `opID`, получаемого с помощью вызова `get_prototype_operation <operation-type>`. Конструктор обеспечивает построение нескольких транзакций параллельно.

**3. Формирование суммы необходимых комиссионных отчислений.** На этом этапе определяется сумма комиссионных отчислений за сформированный набор операций для каждой из транзакций. Пользователь может либо определить размер комиссионных отчислений за каждую операцию в отдельности, либо воспользоваться вызовом метода `set_fees_on_builder_transaction` для автоматического определения общей суммы комиссионных отчислений.\
Метод `set_fees_on_builder_transaction` не дорабатывался и вызывается так же как и в предыдущей версии блокчейна.

**4. Подписание и передача на демон предложенной транзакции.** На заключительном этапе необходимо вызвать `sign_builder_transaction $HANDLE true`. Предложенная транзакция будет автоматически отправлена на подпись и затем передана на демон.

**Note**\
Из-за доработки `cli_wallet` изменилась выдача метода `get_ops_in_block`. В предыдущих версиях выдача этого метода имела следующий вид:

```
vector<operation_api_object> get_ops_in_block(
    uint32_t <blockquote></blockquote>_num,
    bool only_virtual
);
```

Вид измененной выдачи get\_ops\_in\_block:

```
vector<golos::plugins::operation_history::applied_operation> get_ops_in_block(
    uint32_t block_num,
    bool only_virtual
);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://wiki.golos.id/developers/hardforks/hf18_cli_wallet_changes.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
