Перейти к содержанию

Документы

Документ — это объект, несущий юридически-значимую информацию, необходимую для работы кооператива и подтверждения прав пайщиков или других участников. Взаимодействие с документом включает в себя его подготовку, подписание и публикацию в блокчейне. При этом документ всегда состоит из двух частей:

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

Приватная часть — хранится во внутренней базе данных платформы MONO. Эта часть содержит личные или иные конфиденциальные данные пайщика, информацию о содержании документа, подписи, дополнительные детали и всё то, что не должно публиковаться публично. Из неё же берётся необходимая информация для генерации, регенерации и сверки документа с его публичной частью, которая была зафиксирована в блокчейне.

При этом все документы, публикуемые в блокчейне, анонимизированно фиксируются через соответствующие смарт-контракты, что обеспечивает прозрачный и неизменяемый учёт без раскрытия приватных сведений.

flowchart TD
    A("Цифровой Документ") 
    B("Обезличенная часть")
    C("Приватная часть")

    A -->|зафиксировано в блокчейне| B
    A -->|хранится в MONO| C

Фиксация документов

Каждый раз, когда пользователь (пайщик) формирует документ, он генерируется платформой MONO на основании данных, которые уже есть во внутренней базе кооператива. При генерации создаётся как PDF-версия (бинарное представление), так и HTML-версия (для удобного отображения в интерфейсе). Параллельно формируется hash PDF-файла и метаданные, необходимые для будущей регенерации.

Когда пользователь подписывает сформированный документ (PDF-хэш), подпись вместе с публичным ключом и мета-данными отправляется обратно на платформу MONO, и уже MONO публикует эту информацию в блокчейн через вызов соответствующих мутаций смарт-контрактов.

Таким образом, пайщик напрямую не отправляет документ в блокчейн: за него это делает MONO, храня всю детальную информацию у себя, но публикуя в блокчейне лишь зашифрованные или анонимизированные данные, достаточные для удостоверения подлинности документа.

Структура данных в блокчейне

Смарт-контракты в блокчейне фиксируют документ в обезличенном виде. Вызов мутации, отвечающей за публикацию документа, сохраняет в блокчейне следующую структуру:

interface ISignedDocument {
  hash: <string>         // Хэш-сумма подписанного PDF-документа
  signature: <string>    // Подпись хэш-суммы
  public_key: <string>   // Публичный ключ, которым подписан документ
  meta: <object>         // Строка с JSON-объектом мета-информации о документе
}

Где hash - позволяет однозначно идентифицировать документ, signature и public_key обеспечивают криптографическую верификацию подлинности подписи, а meta содержит дополнительную информацию (в формате JSON), позволяющую в будущем восстановить содержание документа (используя данные из внутренней базы MONO).

Таким образом, вся конфиденциальная часть документа (тексты, личные данные, детали договора и т.д.) не вводятся в публичный реестр блокчейна. Блокчейн хранит лишь контрольные суммы и ограниченный набор открытых сведений, необходимые для проверки и восстановления документа.

Процесс генерации и подписания документа

sequenceDiagram
    participant U as Пайщик (Пользователь)
    participant M as MONO
    participant BC as Блокчейн (смарт-контракт)

    U->>M: 1) Запрос на генерацию документа (Generate...)
    M->>U: Возвращает IGeneratedDocument <br/>(PDF/HTML, хэш, метаданные)
    U->>U: 2) Подписывает документ<br/>(hash) приватным ключом
    U->>M: Передаёт подписанный документ (signature, public_key)
    M->>BC: 3) Публикует ISignedDocument<br/>(hash, signature, public_key, meta)
    BC-->>M: Извлекает и сохраняет публичные данные (хэш и пр.)

Инициирующее действие

Пользователь инициирует процесс, вызывая мутацию с префиксом Generate. На примере генерации ползовательского соглашения:

🛠️ SDK: Mutations.Agreements.GenerateUserAgreement

На примере подписи пользовательского соглашения 🛠️ SDK: Mutations.Agreements.GenerateUserAgreement:

import { Mutations } from '@coopenomics/sdk';

const variables: Mutations.Agreements.GenerateUserAgreement.IInput = {
  data: {
    block_num?: <null | number>; // Номер блока, на котором был создан документ
    coopname: <string>; // Название кооператива, связанное с документом
    created_at?: <null | string>; // Дата и время создания документа
    generator?: <null | string>; // Имя генератора, использованного для создания документа
    lang?: <null | string>; // Язык документа
    links?: <null | string[]>; // Ссылки, связанные с документом
    timezone?: <null | string>; // Часовой пояс, в котором был создан документ
    title?: <null | string>; // Название документа
    username: <string>; // Имя пользователя, создавшего документ
    version?: <null | string>; // Версия генератора, использованного для создания документа
  };
  options?: {
    skip_save?: <null | boolean>; // Пропустить сохранение
  };
};

const { [Mutations.Agreements.GenerateUserAgreement.name]: result } = await client.Mutation(
  Mutations.Agreements.GenerateUserAgreement.mutation,
  { variables }
);

В ответ MONO формирует документ:

interface IGeneratedDocument {
  binary: <string>      // base64-кодированное содержимое PDF
  full_title: <string>  // Полное название документа
  hash: <string>        // Хэш-сумма PDF-файла
  html: <string>        // HTML-версия документа
  meta: <MetaDocument>  // Объект метаданных
}

Подпись документа

На полученный hash документ пользователь накладывает цифровую подпись с помощью своего приватного ключа в классе Document

import { Classes } from '@coopenomics/sdk'

//создать фабрику и установить ключ для подписи
const documentFactory = new Classes.Document(<wif>) 

//подписать ранее сгенерированный документ
const signedDocument: ISignedDocument = documentFactory.sign(generatedDocument)

Также вместо создания новой фабрики документов, можно использовать фабрику из ранее созданного клиента:

//устанавливаем ключ, если ранее вход в клиенте с помощью login не исполнялся
client.document.setWif(<wif>)

//подписываем документ
const signedDocument: ISignedDocument = client.document.sign(generatedDocument)

Если экземпляр клиента ранее вызывал метод client.login(...) для входа, то класс client.Document уже содержит приватный ключ wif и может подписывать документы без повторной установки ключа.

В результате, будет получен объект с подписанным документом, пригодным к использованию в мутациях MONO.

Публикация в блокчейне

Для отправки документа необходимо вызвать соответствующую ему мутацию MONO и передать подписанный документ в качестве аргумента. MONO произведет необходимые проверки и опубликует документ в блокчейне, вызвав соответствующий мутации кооперативный смарт-контракт.

Например, в процессе регистрации пайщика необходимо отправить сразу несколько сгенерированных и подписанных документов:

import { Mutations } from '@coopenomics/sdk';

const variables: Mutations.Participants.RegisterParticipant.IInput = {
  data: {
    privacy_agreement: {
      hash: <string>; // Хэш документа
      meta: {
        block_num: <number>; // Номер блока, на котором был создан документ
        coopname: <string>; // Название кооператива, связанное с документом
        created_at: <string>; // Дата и время создания документа
        generator: <string>; // Имя генератора, использованного для создания документа
        lang: <string>; // Язык документа
        links: <string[]>; // Ссылки, связанные с документом
        registry_id: <number>; // ID документа в реестре
        timezone: <string>; // Часовой пояс, в котором был создан документ
        title: <string>; // Название документа
        username: <string>; // Имя пользователя, создавшего документ
        version: <string>; // Версия генератора, использованного для создания документа
      };
      public_key: <string>; // Публичный ключ документа
      signature: <string>; // Подпись документа
    };
    signature_agreement: {
      hash: <string>; // Хэш документа
      meta: {
        block_num: <number>; // Номер блока, на котором был создан документ
        coopname: <string>; // Название кооператива, связанное с документом
        created_at: <string>; // Дата и время создания документа
        generator: <string>; // Имя генератора, использованного для создания документа
        lang: <string>; // Язык документа
        links: <string[]>; // Ссылки, связанные с документом
        registry_id: <number>; // ID документа в реестре
        timezone: <string>; // Часовой пояс, в котором был создан документ
        title: <string>; // Название документа
        username: <string>; // Имя пользователя, создавшего документ
        version: <string>; // Версия генератора, использованного для создания документа
      };
      public_key: <string>; // Публичный ключ документа
      signature: <string>; // Подпись документа
    };
    statement: {
      hash: <string>; // Хэш документа
      meta: {
        block_num: <number>; // Номер блока, на котором был создан документ
        braname: <string>; // Имя аккаунта кооперативного участка
        coopname: <string>; // Название кооператива, связанное с документом
        created_at: <string>; // Дата и время создания документа
        generator: <string>; // Имя генератора, использованного для создания документа
        lang: <string>; // Язык документа
        links: <string[]>; // Ссылки, связанные с документом
        registry_id: <number>; // ID документа в реестре
        signature: <string>; // Изображение собственноручной подписи (base-64)
        skip_save: <boolean>; // Флаг пропуска сохранения документа (используется для предварительной генерации и демонстрации пользователю)
        timezone: <string>; // Часовой пояс, в котором был создан документ
        title: <string>; // Название документа
        username: <string>; // Имя пользователя, создавшего документ
        version: <string>; // Версия генератора, использованного для создания документа
      };
      public_key: <string>; // Публичный ключ документа
      signature: <string>; // Подпись документа
    };
    user_agreement: {
      hash: <string>; // Хэш документа
      meta: {
        block_num: <number>; // Номер блока, на котором был создан документ
        coopname: <string>; // Название кооператива, связанное с документом
        created_at: <string>; // Дата и время создания документа
        generator: <string>; // Имя генератора, использованного для создания документа
        lang: <string>; // Язык документа
        links: <string[]>; // Ссылки, связанные с документом
        registry_id: <number>; // ID документа в реестре
        timezone: <string>; // Часовой пояс, в котором был создан документ
        title: <string>; // Название документа
        username: <string>; // Имя пользователя, создавшего документ
        version: <string>; // Версия генератора, использованного для создания документа
      };
      public_key: <string>; // Публичный ключ документа
      signature: <string>; // Подпись документа
    };
    username: <string>; // Имя аккаунта пайщика
    wallet_agreement: {
      hash: <string>; // Хэш документа
      meta: {
        block_num: <number>; // Номер блока, на котором был создан документ
        coopname: <string>; // Название кооператива, связанное с документом
        created_at: <string>; // Дата и время создания документа
        generator: <string>; // Имя генератора, использованного для создания документа
        lang: <string>; // Язык документа
        links: <string[]>; // Ссылки, связанные с документом
        registry_id: <number>; // ID документа в реестре
        timezone: <string>; // Часовой пояс, в котором был создан документ
        title: <string>; // Название документа
        username: <string>; // Имя пользователя, создавшего документ
        version: <string>; // Версия генератора, использованного для создания документа
      };
      public_key: <string>; // Публичный ключ документа
      signature: <string>; // Подпись документа
    };
  };
};

const { [Mutations.Participants.RegisterParticipant.name]: result } = await client.Mutation(
  Mutations.Participants.RegisterParticipant.mutation,
  { variables }
);

В результате её исполнения, публичные данные документов (хэш, подпись, публичный ключ и мета-данные) зафиксируются в блокчейне, а кооперативный смарт-контракт регистрации продолжит своё исполнение по ходу своей бизнес-логики.

Пакет документов

Пакет документов представляет собой набор всех документов, относящихся к определённому процессу внутри кооператива (например, вступление в кооператив, взнос или возврат имущества имущества, подписание соглашений и т.д.).

Минимальный пакет всегда содержит хотя бы одно заявление (StatementDetail), опубликованное в блокчейне. В зависимости от бизнес-логики смарт-контракта, к заявлению могут добавляться и другие документы:

  • Протокол Решения (DecisionDetail), содержащий данные о том, как совет кооператива принял решение по заявлению.

  • Акты (ActDetail), завершающие юридически значимые действия, например, передача имущества.

  • Связанные документы (GeneratedDocument), которые могут прикладываться к заявлению и подписываться вместе с ним (соглашения об использовании платформы, политике конфиденциальности и т.д.).

MONO собирает документы, связанные с исходным заявлением, в единый пакет. В этом пакете сохраняются как публичные данные, извлечённые из блокчейна (подписи, хэши, статусы), так и приватные данные (конкретное содержимое документов), которые могут быть показаны только тем, кто имеет право их видеть (пайщик, члены совета, председатель и т.д.).

Если после публикации документа в блокчейне с помощью соответствующей мутации, логика смарт-контракта подразумевает, что необходимо собрать совет кооператива для голосования по вопросу в заявлении, то автоматически создаётся объект будущего протокола решения (DecisionDetail), в котором фиксируется процесс голосования и утверждения.

Структурно пакет может выглядеть так, как показано в диаграмме (см. «Структурная диаграмма пакета документов»).

graph LR
    A["📂 Пакет документов (DocumentPackage)"] -->|Содержит| B["📄 Заявление (StatementDetail)"]
    A -->|Может содержать| C["📜 Протокол Решения (DecisionDetail)"]
    A -->|Может содержать| D["📜 Акты (ActDetail)"]
    A -->|Может содержать| E["🔗 Связанные документы (GeneratedDocument)"]

    B -->|Основано на| F["⚡ Расширенное действие в блокчейне (ExtendedBlockchainAction)"]
    B -->|Содержит| G["📑 Документ заявления (GeneratedDocument)"]

    C -->|Основано на| H["⚡ Расширенное действие в блокчейне (ExtendedBlockchainAction)"]
    C -->|Содержит| I["📑 Документ протокола решения (GeneratedDocument)"]
    C -->|Голоса| J["✅ Голоса 'за' (ExtendedBlockchainAction)"] & K["❌ Голоса 'против' (ExtendedBlockchainAction)"]

    D -->|Может содержать| L["⚡ Расширенное действие в блокчейне (ExtendedBlockchainAction)"]
    D -->|Связан с| M["📑 Документ акта (GeneratedDocument)"]

    F -->|Содержит| Z["👤 Информацию о заявителе"]
    H -->|Содержит| X["👤 Информацию о председателе"]
    J & K -->|Содержит| O["👤 Информацию о члене совета"]    
    L -->|Содержит| MM["👤 Информацию о председателе (КУ)"]
    L -->|Содержит| NN["👤 Информацию о пайщике"]

Статусы документов

При публикации в блокчейне каждый документ, в зависимости от контекста и бизнес-логики, получает статус:

  • submitted (входящий) — документ ещё не завершён, ему требуется решение совета или иное дальнейшее действие.

  • resolved (принятый) — документ получил финальную юридическую силу. Это означает, что все необходимые действия выполнены, голоса совета собраны (если были нужны), акт подписан (если требовалось), и смарт-контракт отметил его как завершённый.

  • rejected (отклонённый) - документ отклонён. Это означает, что изначально входящий документ отклонён в процессе рассмотрения советом.

flowchart LR
    A("submitted (входящий)") --> B("rejected (отклоненный)")
    A --> C("resolved (принятый)")

При этом все статусы навсегда сохраняются в блокчейне для каждого документа. Даже если документ, находящийся в статусе submitted, в итоге отклонён советом, он всё равно останется в этом статусе (и дополнительно переходит в rejected), так как данные в публичном реестре не редактируются и не удаляются задним числом.

Соответственно:

  • Входящий (submitted) документ отражает факт, что не все требования закрыты и решение по нему ещё может быть не принято либо принято отрицательно (но мы увидим это не по статусу, а по факту отсутствия закрывающего действия).

  • Принятый (resolved) документ свидетельствует о завершённом процессе и имеет всю юридическую силу в реестре кооператива.

  • Отклоненный (rejected) документ свидетельствует о прерванном процессе и не имеет юридической силы.

Регенерация документов и хранение в MONO

Внутренняя база MONO хранит всё документы, их приватные части, исторические данные, а также привязку к хэшам, которые были опубликованы в блокчейне. Когда пользователь или член совета запрашивает пакет документов, MONO:

  • Извлекает публичные данные по документам из блокчейна (через смарт-контракты).

  • Находит приватные данные в своей БД, сопоставляя их по hash.

  • Собирает итоговый пакет, в котором каждому опубликованному действию (ExtendedBlockchainAction) соответствует документ с нужными вложениями (PDF, HTML, метаданные).

Благодаря этому подходу, платформа может регенерировать любой документ в том же виде, в котором он был подписан и отправлен в блокчейн, и сверить заново сгенерированный документ с тем, который был опубликован в блокчейне, тем самым, верифицировав то, что документ создан корректно, а цифровая подпись на нём - валидна.

Связанные документы

Часто к заявлению или другому документу требуется приложить дополнительные договоры, согласия, соглашения и прочие документы, которые, в свою очередь, могут быть подписаны и закреплены криптографически. Это делается путём добавления в поле meta списка (массива) хэш-сумм связанных документов. Подписывая один документ, пайщик тем самым подтверждает связь с другими документами и своё согласие с ними именно в той версии, с которой он ознакомлен.

Пример: когда пользователь вступает в кооператив, он одновременно потверждает согласие с политикой конфиденциальности, условиями целевой программы «Цифрового Кошелька», а также правила использования простой электронной подписи и пользовательское соглашение. Хэши всех этих документов указываются в поле meta инициирующего заявления на вступление в кооператив, а подробное содержимое каждого документа хранится в базе MONO.

В итоге, вся последовательность от первого инициирующего заявления до заключительного акта, если он предусмотрен бизнес-логикой, превращается в связный пакет документов:

flowchart LR
    Z("Инициирующее заявление<br/>(submitted)") -->|Если требуется решение совета| A("Собрание совета и голосование")
    Z -->|Если решение совета не требуется| B("Перевод<br/>в resolved")
    A -->|Решение принято| D("Подпись актов (при необходимости)")
    A -->|Решение не принято| C("Отклонение -> rejected")
    D -->|Подписи получены| B("resolved")
  • Заявление (StatementDetail) и его подпись в блокчейне инициирует цепочку принятия решений или сразу переводит документ в статус resolved (принятое), если решение по вопросу не требуется;

  • Протокол решения (DecisionDetail) собирает голоса членов совета и ожидает утверждения подписью председателя, если это предусмотрено смарт-контрактом как реакция на инициирующее заявление;

  • Акты (ActDetail) подписывается пайщиком и председателем (кооперативного участка), если такое требование есть у смарт-контракта как реакция на инициирующее заявление. Крайняя подпись на акте переводит документ в статус resolved и фиксирует его в реестре;

  • Прикреплённые (связанные) документы, позволяющие зафиксировать другие важные файлы в рамках этого же пакета;

Такой пакет становится частью списка всех «принятых» решений и документов кооператива, который в любой момент может быть выгружен для проведения аудита, юридических проверок или отчетности перед надзорными органами.

Получить список пакетов документов

🛠️ SDK: Queries.Documents.GetDocuments | 🔗 GraphQL API: Query.getDocuments

import { Queries } from '@coopenomics/sdk';

const variables: Queries.Documents.GetDocuments.IInput = {
  data: {
    filter: {
      additionalFilters?: <any>;
      receiver: <string>;
    };
    limit?: <null | number>;
    page?: <null | number>;
    type?: <null | string>;
  };
};

const { [Queries.Documents.GetDocuments.name]: result } = await client.Query(
  Queries.Documents.GetDocuments.query,
  { variables }
);

Результат исполнения:

interface IOutput {
  getDocuments: {
    currentPage: <number>; // Текущая страница
    items: <{
        acts: <{
            action?: {
              account: <string>;
              account_ram_deltas: <{
                  account: <string>;
                  delta: <number>;
                }[]>;
              action_ordinal: <number>;
              authorization: <{
                  actor: <string>;
                  permission: <string>;
                }[]>;
              block_id: <string>;
              block_num: <number>;
              chain_id: <string>;
              console: <string>;
              context_free: <boolean>;
              creator_action_ordinal: <number>;
              data: <unknown>; // Данные действия в формате JSON
              elapsed: <number>;
              global_sequence: <string>;
              name: <string>;
              receipt: {
                abi_sequence: <number>;
                act_digest: <string>;
                auth_sequence: <{
                    account: <string>;
                    sequence: <string>;
                  }[]>;
                code_sequence: <number>;
                global_sequence: <string>;
                receiver: <string>;
                recv_sequence: <string>;
              };
              receiver: <string>;
              transaction_id: <string>;
              user?: <({ username: string; email: string; birthdate: string; first_name: string; full_address: string; last_name: string; middle_name: string; phone: string; passport?: { number: number; code: string; issued_at: string; issued_by: string; series: number; } | undefined; } | { ...; } | { ...; }) & {}>; // Доп. данные о пользователе (физ/ИП/организация)
            };
            document?: {
              binary: <string>; // Бинарное содержимое документа (base64)
              full_title: <string>; // Полное название документа
              hash: <string>; // Хэш документа
              html: <string>; // HTML содержимое документа
              meta: {
                block_num: <number>; // Номер блока, на котором был создан документ
                coopname: <string>; // Название кооператива, связанное с документом
                created_at: <string>; // Дата и время создания документа
                generator: <string>; // Имя генератора, использованного для создания документа
                lang: <string>; // Язык документа
                links: <string[]>; // Ссылки, связанные с документом
                registry_id: <number>; // ID документа в реестре
                timezone: <string>; // Часовой пояс, в котором был создан документ
                title: <string>; // Название документа
                username: <string>; // Имя пользователя, создавшего документ
                version: <string>; // Версия генератора, использованного для создания документа
              };
            };
          }[]>; // Массив объект(ов) актов, относящихся к заявлению
        decision: {
          action: {
            account: <string>;
            account_ram_deltas: <{
                account: <string>;
                delta: <number>;
              }[]>;
            action_ordinal: <number>;
            authorization: <{
                actor: <string>;
                permission: <string>;
              }[]>;
            block_id: <string>;
            block_num: <number>;
            chain_id: <string>;
            console: <string>;
            context_free: <boolean>;
            creator_action_ordinal: <number>;
            data: <unknown>; // Данные действия в формате JSON
            elapsed: <number>;
            global_sequence: <string>;
            name: <string>;
            receipt: {
              abi_sequence: <number>;
              act_digest: <string>;
              auth_sequence: <{
                  account: <string>;
                  sequence: <string>;
                }[]>;
              code_sequence: <number>;
              global_sequence: <string>;
              receiver: <string>;
              recv_sequence: <string>;
            };
            receiver: <string>;
            transaction_id: <string>;
            user?: <({ username: string; email: string; birthdate: string; first_name: string; full_address: string; last_name: string; middle_name: string; phone: string; passport?: { number: number; code: string; issued_at: string; issued_by: string; series: number; } | undefined; } | { ...; } | { ...; }) & {}>; // Доп. данные о пользователе (физ/ИП/организация)
          };
          document: <unknown>;
          votes_against: <{
              account: <string>;
              account_ram_deltas: <{
                  account: <string>;
                  delta: <number>;
                }[]>;
              action_ordinal: <number>;
              authorization: <{
                  actor: <string>;
                  permission: <string>;
                }[]>;
              block_id: <string>;
              block_num: <number>;
              chain_id: <string>;
              console: <string>;
              context_free: <boolean>;
              creator_action_ordinal: <number>;
              data: <unknown>; // Данные действия в формате JSON
              elapsed: <number>;
              global_sequence: <string>;
              name: <string>;
              receipt: {
                abi_sequence: <number>;
                act_digest: <string>;
                auth_sequence: <{
                    account: <string>;
                    sequence: <string>;
                  }[]>;
                code_sequence: <number>;
                global_sequence: <string>;
                receiver: <string>;
                recv_sequence: <string>;
              };
              receiver: <string>;
              transaction_id: <string>;
              user?: <({ username: string; email: string; birthdate: string; first_name: string; full_address: string; last_name: string; middle_name: string; phone: string; passport?: { number: number; code: string; issued_at: string; issued_by: string; series: number; } | undefined; } | { ...; } | { ...; }) & {}>; // Доп. данные о пользователе (физ/ИП/организация)
            }[]>;
          votes_for: <{
              account: <string>;
              account_ram_deltas: <{
                  account: <string>;
                  delta: <number>;
                }[]>;
              action_ordinal: <number>;
              authorization: <{
                  actor: <string>;
                  permission: <string>;
                }[]>;
              block_id: <string>;
              block_num: <number>;
              chain_id: <string>;
              console: <string>;
              context_free: <boolean>;
              creator_action_ordinal: <number>;
              data: <unknown>; // Данные действия в формате JSON
              elapsed: <number>;
              global_sequence: <string>;
              name: <string>;
              receipt: {
                abi_sequence: <number>;
                act_digest: <string>;
                auth_sequence: <{
                    account: <string>;
                    sequence: <string>;
                  }[]>;
                code_sequence: <number>;
                global_sequence: <string>;
                receiver: <string>;
                recv_sequence: <string>;
              };
              receiver: <string>;
              transaction_id: <string>;
              user?: <({ username: string; email: string; birthdate: string; first_name: string; full_address: string; last_name: string; middle_name: string; phone: string; passport?: { number: number; code: string; issued_at: string; issued_by: string; series: number; } | undefined; } | { ...; } | { ...; }) & {}>; // Доп. данные о пользователе (физ/ИП/организация)
            }[]>;
        };
        links: <{
            binary: <string>; // Бинарное содержимое документа (base64)
            full_title: <string>; // Полное название документа
            hash: <string>; // Хэш документа
            html: <string>; // HTML содержимое документа
            meta: {
              block_num: <number>; // Номер блока, на котором был создан документ
              coopname: <string>; // Название кооператива, связанное с документом
              created_at: <string>; // Дата и время создания документа
              generator: <string>; // Имя генератора, использованного для создания документа
              lang: <string>; // Язык документа
              links: <string[]>; // Ссылки, связанные с документом
              registry_id: <number>; // ID документа в реестре
              timezone: <string>; // Часовой пояс, в котором был создан документ
              title: <string>; // Название документа
              username: <string>; // Имя пользователя, создавшего документ
              version: <string>; // Версия генератора, использованного для создания документа
            };
          }[]>; // Массив связанных документов, извлечённых из мета-данных
        statement: {
          action: {
            account: <string>;
            account_ram_deltas: <{
                account: <string>;
                delta: <number>;
              }[]>;
            action_ordinal: <number>;
            authorization: <{
                actor: <string>;
                permission: <string>;
              }[]>;
            block_id: <string>;
            block_num: <number>;
            chain_id: <string>;
            console: <string>;
            context_free: <boolean>;
            creator_action_ordinal: <number>;
            data: <unknown>; // Данные действия в формате JSON
            elapsed: <number>;
            global_sequence: <string>;
            name: <string>;
            receipt: {
              abi_sequence: <number>;
              act_digest: <string>;
              auth_sequence: <{
                  account: <string>;
                  sequence: <string>;
                }[]>;
              code_sequence: <number>;
              global_sequence: <string>;
              receiver: <string>;
              recv_sequence: <string>;
            };
            receiver: <string>;
            transaction_id: <string>;
            user?: <({ username: string; email: string; birthdate: string; first_name: string; full_address: string; last_name: string; middle_name: string; phone: string; passport?: { number: number; code: string; issued_at: string; issued_by: string; series: number; } | undefined; } | { ...; } | { ...; }) & {}>; // Доп. данные о пользователе (физ/ИП/организация)
          };
          document: <unknown>;
        };
      }[]>; // Элементы текущей страницы
    totalCount: <number>; // Общее количество элементов
    totalPages: <number>; // Общее количество страниц
  };
}