From 57b6611085f171282d2ab3b866b8996a3d170005 Mon Sep 17 00:00:00 2001 From: "Vladimir N. Korotenko" Date: Mon, 10 Nov 2025 12:30:48 +0300 Subject: [PATCH] Initial --- .gitignore | 484 + README.MD | 1 + dm-cli.v2.html | 1811 +++ dm-cli/AccountStatus.cpp | 237 + dm-cli/AccountStatus.hpp | 33 + dm-cli/AccountUpdate.cpp | 299 + dm-cli/AccountUpdate.hpp | 27 + dm-cli/Deals.cpp | 104 + dm-cli/Deals.hpp | 36 + dm-cli/ExecCommand.cpp | 25 + dm-cli/ExecCommand.hpp | 5 + dm-cli/InputParser.hpp | 75 + dm-cli/Makefile | 18 + dm-cli/PrintFile.cpp | 23 + dm-cli/PrintFile.hpp | 4 + dm-cli/ReadFile.cpp | 26 + dm-cli/Replace.cpp | 9 + dm-cli/ShowDebug.cpp | 22 + dm-cli/account_status_en.txt | 9 + dm-cli/account_status_ru.txt | 9 + dm-cli/account_update_en.txt | 15 + dm-cli/base64.cpp | 94 + dm-cli/base64.h | 12 + dm-cli/check.sh | 1 + dm-cli/cleanHtml.cpp | 28 + dm-cli/cleanHtml.h | 9 + dm-cli/common.hpp | 53 + dm-cli/createdistr.sh | 1 + dm-cli/deal_cancel_en.txt | 12 + dm-cli/deal_cancel_ru.txt | 12 + dm-cli/deal_complete_en.txt | 6 + dm-cli/deal_complete_ru.txt | 6 + dm-cli/deal_negative_en.txt | 12 + dm-cli/deal_negative_ru.txt | 12 + dm-cli/deal_status_en.txt | 7 + dm-cli/deal_status_ru.txt | 7 + dm-cli/deals_en.txt | 17 + dm-cli/deals_ru.txt | 17 + dm-cli/help.cpp | 19 + dm-cli/json.hpp | 22875 ++++++++++++++++++++++++++++++ dm-cli/main.cpp | 115 + dm-cli/main_help_en.txt | 23 + dm-cli/main_help_ru.txt | 23 + dm-cli/tpl/accountupdatebtm.txt | 1 + dm-cli/tpl/accountupdatepgp.txt | 1 + dm-cli/tpl/accountupdateurl.txt | 1 + vc/dm-cli.sln | 28 + vc/dm-cli.vcxproj | 197 + vc/dm-cli.vcxproj.filters | 144 + 49 files changed, 27005 insertions(+) create mode 100644 .gitignore create mode 100644 README.MD create mode 100644 dm-cli.v2.html create mode 100644 dm-cli/AccountStatus.cpp create mode 100644 dm-cli/AccountStatus.hpp create mode 100644 dm-cli/AccountUpdate.cpp create mode 100644 dm-cli/AccountUpdate.hpp create mode 100644 dm-cli/Deals.cpp create mode 100644 dm-cli/Deals.hpp create mode 100644 dm-cli/ExecCommand.cpp create mode 100644 dm-cli/ExecCommand.hpp create mode 100644 dm-cli/InputParser.hpp create mode 100644 dm-cli/Makefile create mode 100644 dm-cli/PrintFile.cpp create mode 100644 dm-cli/PrintFile.hpp create mode 100644 dm-cli/ReadFile.cpp create mode 100644 dm-cli/Replace.cpp create mode 100644 dm-cli/ShowDebug.cpp create mode 100644 dm-cli/account_status_en.txt create mode 100644 dm-cli/account_status_ru.txt create mode 100644 dm-cli/account_update_en.txt create mode 100644 dm-cli/base64.cpp create mode 100644 dm-cli/base64.h create mode 100644 dm-cli/check.sh create mode 100644 dm-cli/cleanHtml.cpp create mode 100644 dm-cli/cleanHtml.h create mode 100644 dm-cli/common.hpp create mode 100644 dm-cli/createdistr.sh create mode 100644 dm-cli/deal_cancel_en.txt create mode 100644 dm-cli/deal_cancel_ru.txt create mode 100644 dm-cli/deal_complete_en.txt create mode 100644 dm-cli/deal_complete_ru.txt create mode 100644 dm-cli/deal_negative_en.txt create mode 100644 dm-cli/deal_negative_ru.txt create mode 100644 dm-cli/deal_status_en.txt create mode 100644 dm-cli/deal_status_ru.txt create mode 100644 dm-cli/deals_en.txt create mode 100644 dm-cli/deals_ru.txt create mode 100644 dm-cli/help.cpp create mode 100644 dm-cli/json.hpp create mode 100644 dm-cli/main.cpp create mode 100644 dm-cli/main_help_en.txt create mode 100644 dm-cli/main_help_ru.txt create mode 100644 dm-cli/tpl/accountupdatebtm.txt create mode 100644 dm-cli/tpl/accountupdatepgp.txt create mode 100644 dm-cli/tpl/accountupdateurl.txt create mode 100644 vc/dm-cli.sln create mode 100644 vc/dm-cli.vcxproj create mode 100644 vc/dm-cli.vcxproj.filters diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc78471 --- /dev/null +++ b/.gitignore @@ -0,0 +1,484 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from `dotnet new gitignore` + +# dotenv files +.env + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Ww][Ii][Nn]32/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET +project.lock.json +project.fragment.lock.json +artifacts/ + +# Tye +.tye/ + +# ASP.NET Scaffolding +ScaffoldingReadMe.txt + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.obj +*.iobj +*.pch +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.tlog +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*.json +coverage*.xml +coverage*.info + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio 6 auto-generated project file (contains which files were open etc.) +*.vbp + +# Visual Studio 6 workspace and project file (working project files containing files to include in project) +*.dsw +*.dsp + +# Visual Studio 6 technical files +*.ncb +*.aps + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# Visual Studio History (VSHistory) files +.vshistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# Fody - auto-generated XML schema +FodyWeavers.xsd + +# VS Code files for those working on multiple tools +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +*.code-workspace + +# Local History for Visual Studio Code +.history/ + +# Windows Installer files from build outputs +*.cab +*.msi +*.msix +*.msm +*.msp + +# JetBrains Rider +*.sln.iml +.idea/ + +## +## Visual studio for Mac +## + + +# globs +Makefile.in +*.userprefs +*.usertasks +config.make +config.status +aclocal.m4 +install-sh +autom4te.cache/ +*.tar.gz +tarballs/ +test-results/ + +# Mac bundle stuff +*.dmg +*.app + +# content below from: https://github.com/github/gitignore/blob/main/Global/macOS.gitignore +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# content below from: https://github.com/github/gitignore/blob/main/Global/Windows.gitignore +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# Vim temporary swap files +*.swp diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..55b0503 --- /dev/null +++ b/README.MD @@ -0,0 +1 @@ +dm-cli \ No newline at end of file diff --git a/dm-cli.v2.html b/dm-cli.v2.html new file mode 100644 index 0000000..fbf942f --- /dev/null +++ b/dm-cli.v2.html @@ -0,0 +1,1811 @@ + + + + + + + +ТЗ: CLI клиент для apostol-dm + + + + + + +
+
+

1. Введение

+
+
+

Приложение dm-cli - интерфейс командной строки для доступа к функциям модуля сделок (dm) сервиса обработки bitcoin платежей BitDeals. Приложение должно предоставлять доступ к основной функциональности dm через командную строку.

+
+
+

Ресурсы:

+
+
+ +
+
+
+
+

2. Общие требования

+
+
+
    +
  1. +

    В режиме работы --debug приложение должно дополнительно выводить данные API запросов и ответов.

    +
  2. +
  3. +

    Значение параметра --address приложения должно принимать IP адрес и порт, или URL путь, например https://testnet-dm2.bitdeals.org/dm/ .

    +
  4. +
+
+
+
+
+

3. Функции dm-cli

+
+
+

3.1. Документация по использованию

+
+
    +
  1. +

    Приложение должно выводить справку по использованию приложения по ключу -h или --help

    +
  2. +
  3. +

    Если переменная в значении: LANG=ru_RU.UTF-8, то справка должна быть на русском языке.

    +
    +

    +Пример сообщения 'dm-cli --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli [global] <group> [<args>]
    +
    +Global options:
    +  --debug              print debug information, input and output API requests
    +  --address <ip:port>  address of the bitdeals dm, default: 127.0.0.1:4999
    +  --help               print condensed help for all subcommands
    +  --version            print version string
    +
    +    dm-cli account status <bitcoin_address>
    +        Show account data details
    +    dm-cli account update [options]
    +        Update your account data
    +
    +    dm-cli deal create
    +        Create a new deal
    +    dm-cli deal status
    +        Show deal data details
    +    dm-cli deal complete
    +        Complete deal
    +    dm-cli deal cancel
    +        Cancel deal
    +    dm-cli deal negative
    +        Leave negative feedback
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli [глобальные параметры] <группа> [<аргументы>]
    +
    +Глобальные параметры:
    +  --debug              выводить отладочную информацию, входные и выходные API-запросы
    +  --address <ip:port>  адрес модуля сделок (dm), по умолчанию: 127.0.0.1:4999
    +  --help               вывести краткую справку по всем подкомандам
    +  --version            вывести строку версии
    +
    +    dm-cli account status <биткоин адрес>
    +        Показать учётные данные аккаунта
    +    dm-cli account update [параметры]
    +        Изменить учётные данные аккаунта
    +
    +    dm-cli deal create
    +        Создать новую сделку
    +    dm-cli deal status
    +        Показать данные сделки
    +    dm-cli deal complete
    +        Завершить сделку
    +    dm-cli deal cancel
    +        Отменить сделку
    +    dm-cli deal negative
    +        Оставить негативный отзыв
    +
    +
    +
    +

    +
    +
  4. +
+
+
+
+

3.2. Запрос данных пользователей

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli account status --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli account status [options] <bitcoin_address>
    +
    +    Show info about a bitdeals user.
    +
    +    -f|--feedbacks [p|n]      Show last 1K received feedbacks.
    +                              Use p or n to filter only positive or negative feedbacks.
    +    -i|--info                 Show user account details.
    +    -r|--rating               Show user rating information.
    +    -s|--status               Show user account status (default action).
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli account status [параметры] <биткоин адрес>
    +
    +    Показать информацию о пользователе bitdeals.
    +
    +    -f|--feedbacks [p|n]      Показать последнюю 1 тыс. полученных отзывов.
    +                              Используй p или n для фильтрации только позитивных или негативных отзывов.
    +    -i|--info                 Показать данные учётной записи.
    +    -r|--rating               Показать данные рейтинга.
    +    -s|--status               Показать статус пользователя (действие по умолчанию).
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос статуса (--status) пользователя mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp:

      +
      +
      +
      curl "https://testnet-dm.bitdeals.org/api/v1/account/status?address=mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp"
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {
      +  "id": "c381f540d48c1d34",
      +  "action": "Status",
      +  "address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp",
      +  "result": {
      +    "success": true,
      +    "message": "Open"
      +  },
      +  "payload": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJhdXRob3IiIGNvbnRlbnQ9IkJpdERlYWxzIFBheW1lbnQgU2VydmljZSI+CjwvaGVhZD4KPGJvZHk+CjxwcmU+SGVsbG8sIDxiPm1udW1IczlIUU1ydzJRMWlLTE5ueDlOekV4UzduTUxteXA8L2I+IQoKWW91ciBhY2NvdW50IHN0YXR1czogPGI+T3BlbjwvYj4KCi0tLS0tIEJJVENPSU4gUFVCTElDIEtFWSAtLS0tLQoKPGI+MDI0ZjIyNmNkMzdhYjdlNzY4ZGU3YjY4OTQ2ZDY2MWQwNjdlZjFkNThhMTgzMjU0MjI1YTRmOTFmNmFlODkxOGVlPC9iPgoKLS0tLS0gUEdQIFBVQkxJQyBLRVkgLS0tLS0KCjxiPnB1YiAgMTAyNFIvNDlkZmNjYjk3YjkwNzRjNiAyMDI1LTA4LTA0Cgp1aWQgQWNjb3VudF9VUkwgKGh0dHBzOi8vZXhhbXBsZS0zMjA4OTI4MTIzLmNvbSkKc2lnICBzaWcgICA0OWRmY2NiOTdiOTA3NGM2IDIwMjUtMDgtMDQgICAgICAgICAgICAgICAgICAgIAoKc3ViICAxMDI0Ui80MDYwZjlkNDdkMzgyZGUyIDIwMjUtMDgtMDQKc2lnIHNiaW5kICA0OWRmY2NiOTdiOTA3NGM2IDIwMjUtMDgtMDQgICAgICAgICAgICAgICAgICAgIAo8L2I+Ci0tLS0tIEFDQ09VTlQgVVJMIExJU1QgLS0tLS0KCjxhIGhyZWY9Imh0dHBzOi8vZXhhbXBsZS0zMjA4OTI4MTIzLmNvbSI+aHR0cHM6Ly9leGFtcGxlLTMyMDg5MjgxMjMuY29tPC9hPgoKLS0tLS0gVFJVU1RFRCBVUkwgTElTVCAtLS0tLQoKPGEgaHJlZj0iaHR0cDovLzE3MC43NS4xNzMuNzA6NDk5OSI+aHR0cDovLzE3MC43NS4xNzMuNzA6NDk5OTwvYT4KPGEgaHJlZj0iaHR0cHM6Ly9wbGFjYXJkLnpyLWNvZGUuY29tIj5odHRwczovL3BsYWNhcmQuenItY29kZS5jb208L2E+CjxhIGhyZWY9Imh0dHBzOi8vdGVzdG5ldC5iaXRkZWFscy5vcmciPmh0dHBzOi8vdGVzdG5ldC5iaXRkZWFscy5vcmc8L2E+CjxhIGhyZWY9Imh0dHA6Ly9wbGFjYXJkLnpyLWNvZGUuY29tIj5odHRwOi8vcGxhY2FyZC56ci1jb2RlLmNvbTwvYT4KPGEgaHJlZj0iaHR0cDovL3Rlc3RuZXQtZG0uYml0ZGVhbHMub3JnIj5odHRwOi8vdGVzdG5ldC1kbS5iaXRkZWFscy5vcmc8L2E+CjxhIGhyZWY9Imh0dHBzOi8vdGVzdG5ldC1kbTIuYml0ZGVhbHMub3JnIj5odHRwczovL3Rlc3RuZXQtZG0yLmJpdGRlYWxzLm9yZzwvYT4KPGEgaHJlZj0iaHR0cDovL3Rlc3RuZXQtZG0yLmJpdGRlYWxzLm9yZyI+aHR0cDovL3Rlc3RuZXQtZG0yLmJpdGRlYWxzLm9yZzwvYT4KPGEgaHJlZj0iaHR0cDovL2xvY2FsaG9zdDo0OTk5Ij5odHRwOi8vbG9jYWxob3N0OjQ5OTk8L2E+CjxhIGhyZWY9Imh0dHA6Ly90ZXN0bmV0LmJpdGRlYWxzLm9yZyI+aHR0cDovL3Rlc3RuZXQuYml0ZGVhbHMub3JnPC9hPgo8YSBocmVmPSJodHRwOi8vcGxhY2FyZC5iaXRkZWFscy5vcmciPmh0dHA6Ly9wbGFjYXJkLmJpdGRlYWxzLm9yZzwvYT4KPGEgaHJlZj0iaHR0cHM6Ly9wbGFjYXJkLmJpdGRlYWxzLm9yZyI+aHR0cHM6Ly9wbGFjYXJkLmJpdGRlYWxzLm9yZzwvYT4KPGEgaHJlZj0iaHR0cHM6Ly90ZXN0bmV0LWRtLmJpdGRlYWxzLm9yZyI+aHR0cHM6Ly90ZXN0bmV0LWRtLmJpdGRlYWxzLm9yZzwvYT4KPGEgaHJlZj0iaHR0cHM6Ly90ZXN0bmV0Mi5iaXRkZWFscy5vcmciPmh0dHBzOi8vdGVzdG5ldDIuYml0ZGVhbHMub3JnPC9hPgo8YSBocmVmPSJodHRwOi8vdGVzdG5ldDIuYml0ZGVhbHMub3JnIj5odHRwOi8vdGVzdG5ldDIuYml0ZGVhbHMub3JnPC9hPgo8YSBocmVmPSJodHRwczovL3BsYWNhcmQyLmJpdGRlYWxzLm9yZyI+aHR0cHM6Ly9wbGFjYXJkMi5iaXRkZWFscy5vcmc8L2E+CjxhIGhyZWY9Imh0dHA6Ly9wbGFjYXJkMi5iaXRkZWFscy5vcmciPmh0dHA6Ly9wbGFjYXJkMi5iaXRkZWFscy5vcmc8L2E+CjxhIGhyZWY9Imh0dHBzOi8vZXhhbXBsZS0zMjA4OTI4MTIzLmNvbSI+aHR0cHM6Ly9leGFtcGxlLTMyMDg5MjgxMjMuY29tPC9hPgoKCi0tLS0tClRoYW5rIHlvdSwKQml0RGVhbHMuPC9wcmU+CjwvYm9keT4KPC9odG1sPgo="
      +}
      +
      +
      +
      +
      +

      +
      +
    2. +
    3. +

      Запрос информации (--info) о пользователе mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/user/profile" \
      +    -H "Content-Type: application/json"
      +    -d '{"code":"mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC"}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {
      +  "id": "65380112-e797-4041-8254-0c8878ea36e2",
      +  "userid": "fdbde2fe-d7c4-42d4-a6fd-39c58a17afac",
      +  "created": "2023-03-15T17:03:32.192766+03:00",
      +  "code": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +  "address": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +  "bitmessages": [
      +    "BM-2cWUG4jmW9CwKtNYv6nrJFTiNL4f8Ys8Dd"
      +  ],
      +  "module": "mynFyJJkRhsbB6y1Q5kTgDGckVz2m9NKH8",
      +  "btckey": "02128188a04564583a8540bcd584116d7de1d04dbbcc79c8fd5d45e6a1a65c7031",
      +  "pgpkey": "-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmI0EaByQKQEEAMfwUb7ErrEBDLkjYNwxFvzqdekC3+gR/GpyKOz55kNX/Cwm6ohS\nkNJGVlTR73pXSrQV0c14Dwzgf+HCBFamx1toOCW72GytX71aom2uXHLy8JOzc7bk\naQ+wLti0ghx+cdwvgRuJV5co2tlTxh87iariasP3Dgas4wtRrNvDcQNNABEBAAG0\nJEFjY291bnRfVVJMIChodHRwOi8vcmFuZG9tLXNpdGUuY29tKYjOBBMBCgA4FiEE\nnvbbPXqkDv91aLC/44t8noXtKDgFAmgckCkCGwMFCwkIBwMFFQoJCAsFFgIDAQAC\nHgECF4AACgkQ44t8noXtKDhovwP/eSVEE4234FPSAbI04DFSwt+TtwTqlFHV4O0d\nIzoGHNrQDB/jROugZtRsYR5mQtKbRuSSZTxZZikoJAufG3GBaq4JbDVsYQWRYl/G\ncxmOlS3u+qzjLCDKnn7VDDer+Ewbj2Cc4feH4eJe5vk7TOlXRAfPjV+Mm1gxTVUg\ncw44f624jQRoHJApAQQAu1u/UED5BYEblglb399KDyWHWRPSgM7yQvQHSUxUG4y9\nvzyDC303Hj238RI3AsYRF61EoriHlwAibf2d5LXwPpQrBuKyAzOPus3AIsVPqerK\naQB9poEpdHFr6qhDBumm1uHDKeFMhMcObI0Spz1Y5vUfJq5bMV3KGoYcxlac5bEA\nEQEAAYi2BBgBCgAgFiEEnvbbPXqkDv91aLC/44t8noXtKDgFAmgckCkCGwwACgkQ\n44t8noXtKDj1uwP+IS11c2N2dGLzpTHdujN1NVrvPxGur3lAxIidG57fGwK76RYm\nCrXws6SHORphBUw8nYzE1k9ZTOaZ4c/cNYYpDv6sxYqbFcco5WB1BnGUqtXUj4eK\n8vtje+VeZ+DOPmjUIEd3lMcTJo9sUXzLUxwiFIk89IGXSieOJ5QL+8M/M38=\n=4NLS\n-----END PGP PUBLIC KEY BLOCK-----",
      +  "urlaccount": [
      +    "https://testnet.bitdeals.org",
      +    "http://random-site.com"
      +  ],
      +  "urltrusted": [
      +    "https://testnet.bitdeals.org",
      +    "http://170.75.173.70:4999",
      +    "https://placard.zr-code.com",
      +    "http://testnet-dm.bitdeals.org:4999",
      +    "http://placard.zr-code.com",
      +    "http://testnet-dm.bitdeals.org",
      +    "https://testnet-dm2.bitdeals.org",
      +    "http://testnet-dm2.bitdeals.org",
      +    "http://testnet.bitdeals.org",
      +    "https://testnet-dm.bitdeals.org",
      +    "https://placard.bitdeals.org",
      +    "http://placard.bitdeals.org",
      +    "http://testnet2.bitdeals.org",
      +    "https://testnet2.bitdeals.org",
      +    "http://placard2.bitdeals.org",
      +    "https://placard2.bitdeals.org",
      +    "http://random-site.com"
      +  ],
      +  "seller": {
      +    "count": 11,
      +    "positive": 5
      +  },
      +  "customer": {
      +    "count": 604,
      +    "positive": 36
      +  },
      +  "state": "2565936d-6798-4035-b30d-9b1d388f40a6",
      +  "statecode": "enabled",
      +  "statelabel": "Open"
      +}
      +
      +
      +
      +

      +
      +
    4. +
    5. +

      Запрос списка отзывов (--feedbacks) пользователя mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/deal/feedback/list" \
      +    -H "Content-Type: application/json" \
      +    -d '{"search":[{"field":"sellercode","compare":"EQL","value":"mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC"}],"orderby":["date DESC"],"reclimit":1000,"recoffset":0}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      [
      +  {
      +    "deal": "d63350a1-8483-4c0f-87d2-8a4920f7bdba",
      +    "date": "2025-09-17T11:40:11",
      +    "sum": 0.002,
      +    "seller": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "sellercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "customer": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "customercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "leave_before": "2025-09-17T13:00:00",
      +    "status": null,
      +    "statustext": "none",
      +    "comments": "cancel deal test comment message 3",
      +    "refund": null
      +  },
      +  {
      +    "deal": "7e82e9c3-0e85-4635-8b53-6da7e541e6e3",
      +    "date": "2025-09-17T11:29:35",
      +    "sum": 0.002,
      +    "seller": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "sellercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "customer": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "customercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "leave_before": "2025-09-17T12:50:01",
      +    "status": -1,
      +    "statustext": "negative",
      +    "comments": "negative comment text for test",
      +    "refund": null
      +  },
      +  {
      +    "deal": "3f989f08-b5a0-4ceb-80a5-acd18a6559d4",
      +    "date": "2025-09-17T11:28:28",
      +    "sum": 0.002,
      +    "seller": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "sellercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "customer": "65380112-e797-4041-8254-0c8878ea36e2",
      +    "customercode": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC",
      +    "leave_before": "2025-09-17T12:50:01",
      +    "status": 0,
      +    "statustext": "neutral",
      +    "comments": null,
      +    "refund": "50"
      +  }
      +]
      +
      +
      +
      +

      +
      +
    6. +
    +
    +
  4. +
  5. +

    Примеры вывода команд dm-cli account:

    +
    +

    +dm-cli account status mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp: +

    +
    +
    +
    +
    Hello, mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp!
    +
    +Your account status: Open
    +
    +----- BITCOIN PUBLIC KEY -----
    +
    +024f226cd37ab7e768de7b68946d661d067ef1d58a183254225a4f91f6ae8918ee
    +
    +----- PGP PUBLIC KEY -----
    +
    +pub  1024R/49dfccb97b9074c6 2025-08-04
    +
    +uid Account_URL (https://example-3208928123.com)
    +sig  sig   49dfccb97b9074c6 2025-08-04
    +
    +sub  1024R/4060f9d47d382de2 2025-08-04
    +sig sbind  49dfccb97b9074c6 2025-08-04
    +
    +----- ACCOUNT URL LIST -----
    +
    +https://example-3208928123.com
    +
    +----- TRUSTED URL LIST -----
    +
    +http://170.75.173.70:4999
    +https://placard.zr-code.com
    +https://testnet.bitdeals.org
    +http://placard.zr-code.com
    +http://testnet-dm.bitdeals.org
    +https://testnet-dm2.bitdeals.org
    +http://testnet-dm2.bitdeals.org
    +http://localhost:4999
    +http://testnet.bitdeals.org
    +http://placard.bitdeals.org
    +https://placard.bitdeals.org
    +https://testnet-dm.bitdeals.org
    +https://testnet2.bitdeals.org
    +http://testnet2.bitdeals.org
    +https://placard2.bitdeals.org
    +http://placard2.bitdeals.org
    +https://example-3208928123.com
    +
    +
    +-----
    +Thank you,
    +BitDeals.
    +
    +
    +
    +

    +
    +
    +

    +dm-cli account --info mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC: +

    +
    +
    +
    +
    bitcoin: mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC
    +btckey: 02128188a04564583a8540bcd584116d7de1d04dbbcc79c8fd5d45e6a1a65c7031
    +bitmessage: BM-2cWUG4jmW9CwKtNYv6nrJFTiNL4f8Ys8Dd
    +pgpkey: |
    +  -----BEGIN PGP PUBLIC KEY BLOCK-----
    +
    +  mI0EaByQKQEEAMfwUb7ErrEBDLkjYNwxFvzqdekC3+gR/GpyKOz55kNX/Cwm6ohS
    +  kNJGVlTR73pXSrQV0c14Dwzgf+HCBFamx1toOCW72GytX71aom2uXHLy8JOzc7bk
    +  aQ+wLti0ghx+cdwvgRuJV5co2tlTxh87iariasP3Dgas4wtRrNvDcQNNABEBAAG0
    +  JEFjY291bnRfVVJMIChodHRwOi8vcmFuZG9tLXNpdGUuY29tKYjOBBMBCgA4FiEE
    +  nvbbPXqkDv91aLC/44t8noXtKDgFAmgckCkCGwMFCwkIBwMFFQoJCAsFFgIDAQAC
    +  HgECF4AACgkQ44t8noXtKDhovwP/eSVEE4234FPSAbI04DFSwt+TtwTqlFHV4O0d
    +  IzoGHNrQDB/jROugZtRsYR5mQtKbRuSSZTxZZikoJAufG3GBaq4JbDVsYQWRYl/G
    +  cxmOlS3u+qzjLCDKnn7VDDer+Ewbj2Cc4feH4eJe5vk7TOlXRAfPjV+Mm1gxTVUg
    +  cw44f624jQRoHJApAQQAu1u/UED5BYEblglb399KDyWHWRPSgM7yQvQHSUxUG4y9
    +  vzyDC303Hj238RI3AsYRF61EoriHlwAibf2d5LXwPpQrBuKyAzOPus3AIsVPqerK
    +  aQB9poEpdHFr6qhDBumm1uHDKeFMhMcObI0Spz1Y5vUfJq5bMV3KGoYcxlac5bEA
    +  EQEAAYi2BBgBCgAgFiEEnvbbPXqkDv91aLC/44t8noXtKDgFAmgckCkCGwwACgkQ
    +  44t8noXtKDj1uwP+IS11c2N2dGLzpTHdujN1NVrvPxGur3lAxIidG57fGwK76RYm
    +  CrXws6SHORphBUw8nYzE1k9ZTOaZ4c/cNYYpDv6sxYqbFcco5WB1BnGUqtXUj4eK
    +  8vtje+VeZ+DOPmjUIEd3lMcTJo9sUXzLUxwiFIk89IGXSieOJ5QL+8M/M38=
    +  =4NLS
    +  -----END PGP PUBLIC KEY BLOCK-----
    +
    +
    +
    +

    +
    +
    +

    +dm-cli account --feedbacks p mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp: +

    +
    +
    +
    +
    - deal: ff5f337f-e0ab-4515-857f-3a0c8530dcd3
    +  date: '2025-10-05T15:29:23'
    +  statustext: positive
    +  comments: positive comment about the deal
    +- deal: b7657c83-1502-4a33-8d35-4317a8d5e086
    +  date: '2025-09-17T10:44:50'
    +  statustext: positive
    +  comments: null
    +- deal: 1a79222f-401c-4a73-8f3f-3f0184db3fbb
    +  date: '2025-08-04T10:42:36'
    +  statustext: positive
    +  comments: null
    +- deal: ecc50f4c-4477-4eee-84b7-f8b2ba3755a3
    +  date: '2025-08-04T08:42:46'
    +  statustext: positive
    +  comments: null
    +- deal: aa7ff721-8b15-42f4-8de0-a79bdf47fd55
    +  date: '2025-08-01T08:46:16'
    +  statustext: positive
    +  comments: null
    +- deal: 34010ce2-6775-474d-8316-3bbcea736d8e
    +  date: '2025-08-01T08:14:23'
    +  statustext: positive
    +  comments: null
    +
    +
    +
    +

    +
    +
    +

    +dm-cli account --rating mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC: +

    +
    +
    +
    +
    created: 2023-03-15
    +seller:
    +  count: 11
    +  positive: 5
    +customer:
    +  count: 604
    +  positive: 36
    +
    +
    +
    +

    +
    +
  6. +
+
+
+
+

3.3. Изменение учётных данных пользователя

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli account update --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli account update [options] <bitcoin_address>
    +
    +    Update user account data.
    +
    +    To change the account data you should sign the current date and new user data
    +    with your bitcoin private key. For example, current date, new bitmessage, signature:
    +    2020-01-01
    +    BM-2cUuxYUFWLCrtpKRMdHCpU1QKEuFtHh7vu
    +    IEF1ysyhu8ps0m5xSJaZZg/5hBylmcWQQggkGO7yNN8iMf/EA2O287kxi58xCDDtxvdsC0TWqylVE5MT5CouamU=
    +
    +    -d|--date <yyyy-mm-dd>    Current date.
    +    -s|--signature <sig>      Bitcoin signature.
    +    -p|--pgp <pgp>            Set up an armored RSA pgp key.
    +    -u|--url [+/-]<url>       Add/remove an url to trusted list.
    +    -b|--bitmessage           Change bitmessage address.
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli account update [параметры] <биткоин адрес>
    +
    +    Изменить учётные данные пользователя.
    +
    +    Для изменения учётных данных вы должны подписать текущую дату и новые данные пользователя
    +    вашим приватным биткоин ключом. Например, текущая дата, новый битмессадж, подпись:
    +    2020-01-01
    +    BM-2cUuxYUFWLCrtpKRMdHCpU1QKEuFtHh7vu
    +    IEF1ysyhu8ps0m5xSJaZZg/5hBylmcWQQggkGO7yNN8iMf/EA2O287kxi58xCDDtxvdsC0TWqylVE5MT5CouamU=
    +
    +    -d|--date <yyyy-mm-dd>    Текущая дата.
    +    -s|--signature <sig>      Биткоин подпись.
    +    -p|--pgp <pgp>            Установить armored RSA pgp ключ.
    +    -u|--url [+/-]<url>       Добавить/удалить url в trusted список.
    +    -b|--bitmessage           Изменить битмессадж адрес.
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Добавлиение url в trusted список пользователя mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/client/update" \
      +    -H "Content-Type: application/json" \
      +    -d '{"address":"mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp","date":"2025-10-21","url":["https://testnet-dm2.bitdeals.org"],"sign":"IAGHICUSCxUrcWTMSL9j94vRufb9l5nBckahT+RznlHMPx9LTPpDHsozxVyxkpjtgrhC8eCyJKNaOw8U/v56pL0="}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {"id": "2838be66674f610b06746deb3654a641cf25cc73cb", "action": "Update", "address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp", "result": {"success": true, "message": "Account updated"}, "payload": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ImVuIj4KPGhlYWQ+CiAgICA8bWV0YSBjaGFyc2V0PSJVVEYtOCI+CiAgICA8bWV0YSBuYW1lPSJhdXRob3IiIGNvbnRlbnQ9IkJpdERlYWxzIFBheW1lbnQgU2VydmljZSI+CjwvaGVhZD4KPGJvZHk+CjxwcmU+SGVsbG8sIDxiPm1udW1IczlIUU1ydzJRMWlLTE5ueDlOekV4UzduTUxteXA8L2I+IQoKPGZvbnQgY29sb3I9IiMxNDVBMzIiPjxiPkFjY291bnQgdXBkYXRlZDwvYj48L2ZvbnQ+CgpBY3Rpb246IDxiPlVwZGF0ZTwvYj4KCkluIG1lc3NhZ2UgYm9keSBmb3VuZDoKClRoZSBzaWduYXR1cmUgaXMgPGZvbnQgY29sb3I9IiMxNDVBMzIiPjxiPnZhbGlkLjwvYj48L2ZvbnQ+CgpWZXJpZmljYXRpb24gZGF0ZTogPGI+WWVzPC9iPgpCaXRjb2luIHB1YmxpYyBrZXk6IDxiPk5vPC9iPgpQR1AgcHVibGljIGtleTogPGI+Tm88L2I+ClRydXN0ZWQgVVJMIGNvdW50OiA8Yj4xPC9iPgoKLS0tLS0KVGhhbmsgeW91LApCaXREZWFscy48L3ByZT4KPC9ib2R5Pgo8L2h0bWw+Cg=="}
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli account update:

    +
    +

    +dm-cli account update -d 2025-10-21 -s "IAGH…​pL0=" -u "https://testnet-dm2.bitdeals.org" mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp: +

    +
    +
    +
    +
    success: true
    +message: Account updated
    +
    +
    +
    +

    +
    +
  6. +
  7. +

    Команда должна производить изменение данных пользователя:

    +
    +
      +
    1. +

      PGP ключа

      +
    2. +
    3. +

      Списка Trusted URL

      +
    4. +
    5. +

      Bitmessage адреса

      +
    6. +
    +
    +
  8. +
+
+
+
+

3.4. Создание сделки

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli deal create --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli deal create [options]
    +
    +    Create a new deal
    +
    +    [smhd] means seconds, minutes, hours, days.
    +    For example: --leave-before 2020-01-01, or --leave-before 10d.
    +
    +    -a|--at                   Deal site
    +    -s|--seller               Seller user in deal
    +    -c|--customer             Customer user in deal
    +    -t|--type [prepayment|postpayment]
    +                              Deal type
    +    -s|--sum                  Deal sum in BTC
    +    -l|--leave-before { <yyyy-mm-dd> [hh:mm:ss UTC] | <time>[smhd] }
    +                              Deal end date (deal duration); default: 14d
    +    -p|--pay { <yyyy-mm-dd> [hh:mm:ss UTC] | <time>[smhd] }
    +                              Time for make payment; default: 1d
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli deal create [параметры]
    +
    +    Создать новую сделку
    +
    +    [smhd] означает секунды, минуты, часы, дни.
    +    Например: --leave-before 2020-01-01, or --leave-before 10d.
    +
    +    -a|--at                   Сайт проведения сделки
    +    -s|--seller               Продавец в сделке
    +    -c|--customer             Покупатель в сделке
    +    -t|--type [prepayment|postpayment]
    +                              Тип сделки
    +    -s|--sum                  Сумма сделки в BTC
    +    -l|--leave-before { <гггг-мм-дд> [чч:мм:сс UTC] | <время>[smhd] }
    +                              Время окончания сделки (длительность сделки), по умолчанию: 14d
    +    -p|--pay { <гггг-мм-дд> [чч:мм:сс UTC] | <время>[smhd] }
    +                              Время для оплаты сделки; по умолчанию: 1d
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос создания сделки:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/deal/create" \
      +    -H "Content-Type: application/json" \
      +    -d '{"at":"https://testnet-dm2.bitdeals.org","type":"Prepayment","seller":{"address":                               "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp"},"customer":{"address":"mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC"},"payment":{"sum":"0.01000000"}}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {"id": "f38bfeeb1ddac852", "action": "Created", "address": "mynFyJJkRhsbB6y1Q5kTgDGckVz2m9NKH8", "deal": {"order": "Created", "type": "Prepayment", "code": "ae6d226b2fe5ce009f252e65fcf66fd079729ac8", "at": "https://testnet-dm2.bitdeals.org", "date": "2025-10-21 09:08:12 UTC", "salt": "343c82c2", "seller": {"address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp", "rating": "0+, 32%"}, "customer": {"address": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC", "rating": "0+, 45%"}, "payment": {"address": "2N7gRqGakSZaowyqSHSULaPzp7Fy2KKUQQ7", "until": "2025-10-22 09:08:12 UTC", "sum": "0.01 tBTC"}, "feedback": {"leave_before": "2025-11-04 09:08:12 UTC"}}, "result": {"success": true, "message": "New deal created"}, "payload": "LS0tLS1CRUdJTiBQR1AgU0lHTkVEIE1FU1NBR0UtLS0tLQpIYXNoOiBTSEE1MTIKCmRlYWw6CiAgb3JkZXI6IENyZWF0ZQogIHR5cGU6IFByZXBheW1lbnQKICBhdDogaHR0cHM6Ly90ZXN0bmV0LWRtMi5iaXRkZWFscy5vcmcKICBkYXRlOiAyMDI1LTEwLTIxIDA5OjA4OjEyIFVUQwogIHNhbHQ6IDM0M2M4MmMyCiAgc2VsbGVyOgogICAgYWRkcmVzczogbW51bUhzOUhRTXJ3MlExaUtMTm54OU56RXhTN25NTG15cAogICAgcmF0aW5nOiAwKywgMzIlCiAgY3VzdG9tZXI6CiAgICBhZGRyZXNzOiBtcmFYeDdKcm1BbXVLeXBkSjF2c2VRQlh5U3NkUlpFNUFDCiAgICByYXRpbmc6IDArLCA0NSUKICBwYXltZW50OgogICAgYWRkcmVzczogMk43Z1JxR2FrU1phb3d5cVNIU1VMYVB6cDdGeTJLS1VRUTcKICAgIHVudGlsOiAyMDI1LTEwLTIyIDA5OjA4OjEyIFVUQwogICAgc3VtOiAwLjAxIHRCVEMKICBmZWVkYmFjazoKICAgIGxlYXZlLWJlZm9yZTogMjAyNS0xMS0wNCAwOTowODoxMiBVVEMKLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KVmVyc2lvbjogY2MKCndwd0VBUUVLQUFZRkFtajNUWUFBQ2drUURqa3UwOE9pdDFJR1NnUCtMQWR4aUYrNkpISFpDWHJaNlFHdHhZdTQKeGdGeXJub3FmQ3pxaU0xVlF1MDhsbERtUnZ1aFRMTDBQTUxxUGdXUUYvRTBKckt0T0d1YmRVYlBCaWpKbm04eApiVWJjczRaOEtIcjZOOERhRXdnOU9MQVNYbnpVRGVzMGhCUDJsNEViK1JwWmFRdjhUMUFUeW1aVEt3bjNtbTI5CjZoL0hLQnVHS0hXY1U2MG5nQ2c9Cj1kUXdGCi0tLS0tRU5EIFBHUCBTSUdOQVRVUkUtLS0tLQ=="}
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli deal create:

    +
    +

    +Пример вывода команды 'dm-cli deals create -t prepayment -s mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp -c mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC -s 0.01: +

    +
    +
    +
    +
    -----BEGIN PGP SIGNED MESSAGE-----
    +Hash: SHA512
    +
    +deal:
    +  order: Confirmed
    +  type: Prepayment
    +  at: https://testnet-dm2.bitdeals.org
    +  date: 2025-10-21 09:08:12 UTC
    +  salt: 343c82c2
    +  seller:
    +    address: mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp
    +    rating: 600+, 32%
    +  customer:
    +    address: mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC
    +    rating: 600+, 36%
    +  payment:
    +    address: 2N7gRqGakSZaowyqSHSULaPzp7Fy2KKUQQ7
    +    until: 2025-10-22 09:08:12 UTC
    +    sum: 0.01 tBTC
    +  feedback:
    +    leave-before: 2025-11-04 09:08:12 UTC
    +    status: None
    +-----BEGIN PGP SIGNATURE-----
    +Version: cc
    +
    +wpwEAQEKAAYFAmj3UBgACgkQDjku08Oit1JLogQA0PofMslTfBrNCKFfdlAgj/8A
    +03lXiHPRd36PVzaa8lK6tHmdfs0EFrp28InXLswfksXD/0Hj9SBKrDQz1qxwqXqZ
    +rGC1RiXqRpHxl++3/lx3AguPPX5QydjDEwKSA3lL2pnsnnqe2edqUttJzunz9LYy
    +mhdbFlS1jaFzO0w25Ww=
    +=1TmH
    +-----END PGP SIGNATURE-----
    +
    +
    +
    +

    +
    +
  6. +
  7. +

    Команда должна создавать сделку с учётом указанных параметров:

    +
    +
      +
    • +

      Место (сайт) проведения сделки [deal.at];

      +
    • +
    • +

      Стороны сделки [seller, customer];

      +
    • +
    • +

      Тип сделки [Prepayment, Postpayment];

      +
    • +
    • +

      Сумма сделки в BTC [payment.sum];

      +
    • +
    • +

      Длительность сделки [feedback.leave-before];

      +
    • +
    • +

      Время для оплаты сделки [payment.until];

      +
    • +
    +
    +
  8. +
+
+
+
+

3.5. Статус сделки

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli deal status --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli deal status { <bitcoin_address>|<deal_code> }
    +
    +    Show a deal data details
    +
    +    To show a deal details use a bitcoin payment address or a deal code.
    +
    +    -i|--is-paid              Check a deal is Paid. Returns an exit code 0 if deal is Paid, or non-zero otherwise.
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli deal status { <биткоин адрес>|<код сделки> }
    +
    +    Показать детали сделки
    +
    +    Чтобы показать детали сделки используйте адрес оплаты сделки или код сделки.
    +
    +    -i|--is-paid              Проверить является ли сделка оплаченной. Возвращает exit code 0 если сделка является оплаченной, или не ноль в других случаях.
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос статуса сделки:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/deal/status" \
      +    -H "Content-Type: application/json" \
      +    -d '{"address":"3e251d8fdcfa80adf5a3050064fc4ecb01d304d1"}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {"id": "207022ea5d39ebb2", "action": "Status", "deal": {"order": "Confirmed", "type": "Prepayment", "code": "3e251d8fdcfa80adf5a3050064fc4ecb01d304d1", "at": "https://testnet-dm2.bitdeals.org", "date": "2025-10-21 09:02:11 UTC", "salt": "fd986961", "seller": {"address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp", "rating": "0+, 32%"}, "customer": {"address": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC", "rating": "0+, 36%"}, "payment": {"address": "2NCBgmt37qw97ujZFjgmPEWuoYweR4BWT9g", "until": "2025-10-22 09:02:11 UTC", "sum": "0.01 tBTC"}, "feedback": {"leave_before": "2025-11-04 09:02:11 UTC"}}, "result": {"success": true, "message": "Deal status"}, "payload": "LS0tLS1CRUdJTiBQR1AgU0lHTkVEIE1FU1NBR0UtLS0tLQpIYXNoOiBTSEE1MTIKCmRlYWw6CiAgb3JkZXI6IENvbmZpcm1lZAogIHR5cGU6IFByZXBheW1lbnQKICBhdDogaHR0cHM6Ly90ZXN0bmV0LWRtMi5iaXRkZWFscy5vcmcKICBkYXRlOiAyMDI1LTEwLTIxIDA5OjAyOjExIFVUQwogIHNhbHQ6IGZkOTg2OTYxCiAgc2VsbGVyOgogICAgYWRkcmVzczogbW51bUhzOUhRTXJ3MlExaUtMTm54OU56RXhTN25NTG15cAogICAgcmF0aW5nOiA2MDArLCAzMiUKICBjdXN0b21lcjoKICAgIGFkZHJlc3M6IG1yYVh4N0pybUFtdUt5cGRKMXZzZVFCWHlTc2RSWkU1QUMKICAgIHJhdGluZzogNjAwKywgMzYlCiAgcGF5bWVudDoKICAgIGFkZHJlc3M6IDJOQ0JnbXQzN3F3OTd1alpGamdtUEVXdW9Zd2VSNEJXVDlnCiAgICB1bnRpbDogMjAyNS0xMC0yMiAwOTowMjoxMSBVVEMKICAgIHN1bTogMC4wMSB0QlRDCiAgZmVlZGJhY2s6CiAgICBsZWF2ZS1iZWZvcmU6IDIwMjUtMTEtMDQgMDk6MDI6MTEgVVRDCiAgICBzdGF0dXM6IE5vbmUKLS0tLS1CRUdJTiBQR1AgU0lHTkFUVVJFLS0tLS0KVmVyc2lvbjogY2MKCndwd0VBUUVLQUFZRkFtajNZc0VBQ2drUURqa3UwOE9pdDFLWHpnUC9jd2YrcXI2NGFnSnFrdDBNd2orTzlhb0EKYXE4QndlQXdjc1B0ZEgzMGlhZGZ0c3RidlpmN3Rsc1ppVUxJbHhaTnBRR0VEdUp4czROcVdHTnhwaFlIQ2ZuMAp1T1VRRkZVeTJubmVEUElGSFJhM2I2TFMzQXd3ZGxkWjI1K1ozUmozOU5rQ3BCeGJEMWxWRGJQNWtoOEtwQlVwClNPMnNLRWZIT2hhOXBieHNvWU09Cj1SSUZOCi0tLS0tRU5EIFBHUCBTSUdOQVRVUkUtLS0tLQ=="}
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli deal status:

    +
    +

    +Пример вывода команды dm-cli deal status 2N7gRqGakSZaowyqSHSULaPzp7Fy2KKUQQ7: +

    +
    +
    +
    +
    -----BEGIN PGP SIGNED MESSAGE-----
    +Hash: SHA512
    +
    +deal:
    +  order: Create
    +  type: Prepayment
    +  at: https://testnet-dm2.bitdeals.org
    +  date: 2025-10-21 09:08:12 UTC
    +  salt: 343c82c2
    +  seller:
    +    address: mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp
    +    rating: 0+, 32%
    +  customer:
    +    address: mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC
    +    rating: 0+, 45%
    +  payment:
    +    address: 2N7gRqGakSZaowyqSHSULaPzp7Fy2KKUQQ7
    +    until: 2025-10-22 09:08:12 UTC
    +    sum: 0.01 tBTC
    +  feedback:
    +    leave-before: 2025-11-04 09:08:12 UTC
    +-----BEGIN PGP SIGNATURE-----
    +Version: cc
    +
    +wpwEAQEKAAYFAmj3TYAACgkQDjku08Oit1IGSgP+LAdxiF+6JHHZCXrZ6QGtxYu4
    +xgFyrnoqfCzqiM1VQu08llDmRvuhTLL0PMLqPgWQF/E0JrKtOGubdUbPBijJnm8x
    +bUbcs4Z8KHr6N8DaEwg9OLASXnzUDes0hBP2l4Eb+RpZaQv8T1ATymZTKwn3mm29
    +6h/HKBuGKHWcU60ngCg=
    +=dQwF
    +-----END PGP SIGNATURE-----
    +
    +
    +
    +

    +
    +
  6. +
  7. +

    Проверка --is-paid должна проверять состояние оплаты сделки на основе полученного текста деталей сделки. Для order: Paid, order: Completed, order: Executed - сделка оплачена, соответсвенно, exit code команды должен быть равен 0.

    +
  8. +
+
+
+
+

3.6. Завершение сделки

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli deal complete --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli deal complete [options] { <bitcoin_address>|<deal_code> }
    +
    +    Complete a deal
    +
    +    -p|--positive             Complete deal with positive feedback. (default action)
    +    -r|--refund <num>         Refund % number of a deal sum to the customer. Format: 100.00[%]
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli deal complete [параметры] { <биткоин адес>|<код сделки> }
    +
    +    Завершить сделку
    +
    +    -p|--positive             Завершить сделку с позитивным отзывом. (действие по умолчанию)
    +    -r|--refund <num>         Возврат % от суммы сделки покупателю. Формат: 100.00[%]
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос завершения сделки:

      +
      +
      +
      curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/deal/complete" \
      +    -H "Content-Type: application/json" \
      +    -d '{"order":"Paid","type":"Postpayment","code":"d87cc05dd42bf4fb6cc5d231388a254de94b787a","at":"https://testnet-dm2.bitdeals.org","date":"2025-10-21 11:36:26 UTC","salt":"8f489443","seller":{"address":"mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp","rating":"600+, 32%"},"customer":{"address":"mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC","rating":"600+, 36%"},"payment":{"address":"2Mvh1UozwwUwuFcmeCqQm7UEKAxnV4ANhAS","until":"2025-10-22 11:36:26 UTC","sum":"0.01 tBTC"},"feedback":{"leave_before":"2025-11-04 11:36:26 UTC","status":"Neutral","refund":45}}'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {"id": "f1c94f5a62e005b4", "action": "Complete", "deal": {"order": "Complete", "type": "Postpayment", "code": "d87cc05dd42bf4fb6cc5d231388a254de94b787a", "at": "https://testnet-dm2.bitdeals.org", "date": "2025-10-21 11:36:26 UTC", "salt": "8f489443", "seller": {"address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp", "rating": "0+, 32%"}, "customer": {"address": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC", "rating": "0+, 36%"}, "payment": {"address": "2Mvh1UozwwUwuFcmeCqQm7UEKAxnV4ANhAS", "until": "2025-10-22 11:36:26 UTC", "sum": "0.01 tBTC"}, "feedback": {"leave_before": "2025-11-04 11:36:26 UTC", "status": "Neutral"}}, "result": {"success": true, "message": "Completion command accepted"}, "payload": "CgotLS0tLSBSRVBPUlQgLS0tLS0KClBHUCBzaWduYXR1cmU6IDxmb250IGNvbG9yPSIjMTQ1QTMyIj48Yj52YWxpZC4KPC9iPjwvZm9udD5Nb2R1bGU6IG15bkZ5SkprUmhzYkI2eTFRNWtUZ0RHY2tWejJtOU5LSDgKCkZlZTogMSU="}
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli deal complete:

    +
    +

    +Пример вывода команды dm-cli deal complete -r 45 2Mvh1UozwwUwuFcmeCqQm7UEKAxnV4ANhAS: +

    +
    +
    +
    +
    success: true
    +message: Completion command accepted
    +
    +
    +
    +

    +
    +
  6. +
+
+
+
+

3.7. Отмена сделки

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli deal cancel --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli deal cancel [options] <bitcoin_address>
    +
    +    Cancel a deal
    +
    +    To cancel a deal you should sign the deal payment address and feeback text message
    +    with the seller bitcoin private key. For example, address, feedback, signature:
    +    2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5
    +    seller random cancel reason text
    +    IEOGJ5q/a2cWJPMosQmCHNN6RsXF8Xy/UgaazIoY2i5udbw/v38g1/PdWs451dvFr9Iq/Bq5YL2YdpUFTuijQ60=
    +
    +    -m|--message <text>       Deal cancel reason text message
    +    -s|--signature <sig>      Bitcoin signature.
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli deal cancel [параметры] <биткоин адрес>
    +
    +    Отменить сделку
    +
    +    Для отмены сделки вы должны подписать адрес оплаты сделки и текст отзыва биткоин
    +    ключом продавца. Например, адрес, отзыв, подпись:
    +    2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5
    +    seller random cancel reason text
    +    IEOGJ5q/a2cWJPMosQmCHNN6RsXF8Xy/UgaazIoY2i5udbw/v38g1/PdWs451dvFr9Iq/Bq5YL2YdpUFTuijQ60=
    +
    +    -m|--message <text>       Текст сообщения с причино отмены сделки
    +    -s|--signature <sig>      Биткоин подпись.
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос завершения сделки:

      +
      +
      +
      curl --location 'https://testnet-dm2.bitdeals.org/api/v1/deal/cancel' \
      +--form 'type="Postpayment"' \
      +--form 'at="https://testnet-dm2.bitdeals.org"' \
      +--form 'date="2025-10-21 11:59:41 UTC"' \
      +--form 'salt="98b00a5e"' \
      +--form 'seller_address="mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp"' \
      +--form 'seller_rating="600+, 32%"' \
      +--form 'seller_signature="IERJW29usD99pIkyJktK7z24fxdWncr9GoN/bBvfeHELDNj2aMSOC0JzNqQbnnsT3ETA9mEB9gj5YF+AD4ACuwE="' \
      +--form 'customer_address="mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC"' \
      +--form 'customer_rating="600+, 36%"' \
      +--form 'payment_address="2Mt7UW5RqXUaEN7Y93jo67ZgixcLNPDgvvk"' \
      +--form 'payment_until="2025-10-22 11:59:41 UTC"' \
      +--form 'payment_sum="0.01 tBTC"' \
      +--form 'feedback_leave_before="2025-11-04 11:59:41 UTC"' \
      +--form 'feedback_status="None"' \
      +--form 'feedback_comments="Cancellation comments"'
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      {"id": "3f1b2d6409bfa4bd", "action": "Cancelled", "address": "mynFyJJkRhsbB6y1Q5kTgDGckVz2m9NKH8", "deal": {"order": "Cancelled", "type": "Postpayment", "code": "6e7fa8bdd6f406bf3f5d253b67730523ea62b03f", "at": "https://placard.bitdeals.org", "date": "2024-10-23 10:34:09 UTC", "salt": "6cbf5879", "seller": {"address": "mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp", "rating": "0, 0%"}, "customer": {"address": "mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC", "rating": "0, 0%"}, "payment": {"address": "2NFgvA4f8ibA5jJ6hca1dX9HvBguNTgP6eR", "until": "2024-10-23 15:34:09 UTC", "sum": "0.00519519 tBTC"}, "feedback": {"leave_before": "2025-07-10 10:34:09 UTC", "status": "Positive", "comments": "random deal cancel message"}}, "result": {"success": true, "message": "Deal cancelled"}, "payload": "CgotLS0tLSBSRVBPUlQgLS0tLS0KClBHUCBzaWduYXR1cmU6IDxmb250IGNvbG9yPSIjMTQ1QTMyIj48Yj52YWxpZC4KPC9iPjwvZm9udD5Nb2R1bGU6IG15bkZ5SkprUmhzYkI2eTFRNWtUZ0RHY2tWejJtOU5LSDgKCkZlZTogMSU="}
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli deal cancel:

    +
    +

    +Пример вывода команды dm-cli deal cancel -m "Cancellation comments" -s "CgoL…​MSU=" 2Mt7UW5RqXUaEN7Y93jo67ZgixcLNPDgvvk: +

    +
    +
    +
    +
    success: true
    +message: Deal cancelled
    +
    +
    +
    +

    +
    +
  6. +
+
+
+
+

3.8. Оставление негативного отзыва

+
+
    +
  1. +

    Запрос должен происходить в соответствии с синтаксисом:

    +
    +

    +Пример сообщения 'dm-cli deal negative --help': +

    +
    +
    +

    На английском:

    +
    +
    +
    +
    Usage: dm-cli deal negative [options] <bitcoin_address>
    +
    +    Leave a negative feedback
    +
    +    To leave a negative feedback you should sign the deal payment address and feeback text message
    +    with the customer bitcoin private key. For example, address, feedback, signature:
    +    2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5
    +    customer random feedback text
    +    H1u44C5cyEeKjHqnNnn09B8mIRMdqgR8PD9AeF8mv+cCEqM9HPkcWLrc8a/v2po2YmXJSeya6uy0XaLnmmmO/1o=
    +
    +    -m|--message <text>       Deal feedback text message
    +    -s|--signature <sig>      Bitcoin signature.
    +
    +
    +
    +

    На русском:

    +
    +
    +
    +
    Использование: dm-cli deal negative [options] <биткоин адрес>
    +
    +    Оставить негативный отзыв
    +
    +    Для оставления негативного отзыва ва должны подписать адрес оплаты сделки и текст отзыва биткоин
    +    ключом покупателя. Например, адрес, отзыв, подпись:
    +    2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5
    +    customer random feedback text
    +    H1u44C5cyEeKjHqnNnn09B8mIRMdqgR8PD9AeF8mv+cCEqM9HPkcWLrc8a/v2po2YmXJSeya6uy0XaLnmmmO/1o=
    +
    +    -m|--message <text>       Текст сообщения отзыва
    +    -s|--signature <sig>      Биткоин подпись.
    +
    +
    +
    +

    +
    +
  2. +
  3. +

    Примеры входных и выходных данных.

    +
    +
      +
    1. +

      Запрос завершения сделки:

      +
      +
      +
      +
      +
      +
      +

      +Пример ответа: +

      +
      +
      +
      +
      +
      +
      +
      +

      +
      +
    2. +
    +
    +
  4. +
  5. +

    Пример вывода команды dm-cli deal negative:

    +
    +

    +Пример вывода команды dm-cli deal negative: +

    +
    +
    +
    +
    +
    +
    +
    +

    +
    +
  6. +
  7. +

    В результате исполнения команды, указанная сделка должна получить негативный отзыв (status: Negative).

    +
  8. +
+
+
+
+
+
+ + \ No newline at end of file diff --git a/dm-cli/AccountStatus.cpp b/dm-cli/AccountStatus.cpp new file mode 100644 index 0000000..0a28fae --- /dev/null +++ b/dm-cli/AccountStatus.cpp @@ -0,0 +1,237 @@ +#include "AccountStatus.hpp" +#include +#include +#include +#include "PrintFile.hpp" +#include "common.hpp" +#include "ExecCommand.hpp" +#include "json.hpp" +#include "base64.h" +#include "cleanHtml.h" +#include + +using namespace std; +void AccountHelp(bool isRussian) +{ + if (isRussian) + { + PrintFile(ACCOUNT_STATUS_RU); + } + else + { + PrintFile(ACCOUNT_STATUS_EN); + } +} + +/// @brief Получение информации аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountStatus(const std::string address, const char* bkaddress, bool isDebug) +{ + // curl "https://testnet-dm.bitdeals.org/api/v1/account/status?address=mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp" + string url("curl -s \"https://"); + url += address + "/api/v1/account/status?address=" + bkaddress + "\""; + string result = ExecCommand(url.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + string payload(""); + payload = jsonData["payload"]; + bool success = jsonData["result"]["success"]; + + string decoded = base64_decode(payload); + string cleaned = cleanup_html(decoded); + cout << cleaned << endl; + if (isDebug) ShowDebug(url, result, success, decoded); + if (success) return 0; else return 1; +} + + +/// @brief Получение информации аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountInfo(const std::string address, const char* bkaddress, bool isDebug) { + + // curl -H "Content-Type: application/json" -d "{ \"code\": \"mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp\"}" https://testnet-dm2.bitdeals.org/api/v1/user/profile + string url("curl -s "); + url.append("-H \"Content-Type: application/json\" "); + url.append("-d \"{ \\\"code\\\": \\\""); + url.append(bkaddress); + url.append("\\\"} \" "); + url.append(address); + url.append("/api/v1/user/profile"); + + string result = ExecCommand(url.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + + string bitcoin(""); + string btckey(""); + string bitmessage(""); + string pgpkey(""); + + bitcoin = bkaddress; + btckey = jsonData["btckey"]; + bitmessage = jsonData["bitmessages"][0]; + pgpkey = jsonData["pgpkey"]; + + + + + string decoded(""); + decoded.append("bitcoin: "); + decoded.append(bitcoin); + decoded.append("\n"); + + decoded.append("btckey: "); + decoded.append(btckey); + decoded.append("\n"); + + + decoded.append("bitmessage: "); + decoded.append(bitmessage); + decoded.append("\n"); + + + decoded.append("pgpkey: "); + decoded.append(pgpkey); + decoded.append("\n"); + + cout << decoded << endl; + + if (isDebug) ShowDebug(url, result, 1, decoded); + + + return 0; +} + +/// @brief Получение Рейтинга аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountRaiting(const std::string address, const char* bkaddress, bool isDebug) { + // curl -H "Content-Type: application/json" -d "{ \"code\": \"mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp\"}" https://testnet-dm2.bitdeals.org/api/v1/user/profile + string url("curl -s "); + url.append("-H \"Content-Type: application/json\" "); + url.append("-d \"{ \\\"code\\\": \\\""); + url.append(bkaddress); + url.append("\\\"} \" "); + url.append(address); + url.append("/api/v1/user/profile"); + + string result = ExecCommand(url.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + + + + std::ostringstream stream; + + stream << "created: " << jsonData["created"] << endl; + stream << "seller: " << endl; + stream << " count: " << jsonData["seller"]["count"] << endl; + stream << " positive: " << jsonData["seller"]["positive"] << endl; + + + stream << "customer: " << endl; + stream << " count: " << jsonData["customer"]["count"] << endl; + stream << " positive: " << jsonData["customer"]["positive"] << endl; + + string decoded = stream.str(); + cout << decoded << endl; + + if (isDebug) ShowDebug(url, result, 1, decoded); + + + return 0; +} + + +/// @brief Получение Рейтинга аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +/// @param fb - тип фидбэка 0- все p - 1(positive) n-2 (negative) +int AccountFeedbacks(const std::string address, const char* bkaddress, bool isDebug, int fb) { + + /* + curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/deal/feedback/list" \ + -H "Content-Type: application/json" \ + -d '{"search":[{"field":"sellercode","compare":"EQL","value":"mraXx7JrmAmuKypdJ1vseQBXySsdRZE5AC"}],"orderby":["date DESC"],"reclimit":1000,"recoffset":0}' + + + */ + string url("curl -s "); + url.append("-H \"Content-Type: application/json\" "); + + url.append("-d \"{ \\\"search\\\":[{\\\"field\\\":\\\"sellercode\\\",\\\"compare\\\": \\\"EQL\\\",\\\"value\\\":\\\""); + url.append(bkaddress); + url.append("\\\"}],\\\"orderby\\\":[\\\" date DESC\\\"],\\\"reclimit\\\":100,\\\"recoffset\\\":0} \" "); + + + url.append(address); + url.append("/api/v1/deal/feedback/list"); + + string result = ExecCommand(url.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + std::ostringstream stream; + size_t size = jsonData.size(); + int positivefb = 0; + int negativefb = 0; + + for (size_t i = 0;i < size;++i) { + // "positive" + // "negative" + // 0 - все p - 1(positive)n - 2 (negative) + + auto val = jsonData[i]; + string statustext = val["statustext"]; + + if (statustext.compare("positive") == 0) positivefb++; + if (statustext.compare("negative") == 0) negativefb++; + if (fb == 1 && statustext.compare("positive") == 0) { + stream << "- deal: " << val["deal"] << endl; + stream << " date: " << val["date"] << endl; + stream << " statustext: " << val["statustext"] << endl; + stream << " comments: " << val["comments"] << endl; + } + else if (fb == 2 && statustext.compare("negative") == 0) { + stream << "- deal: " << val["deal"] << endl; + stream << " date: " << val["date"] << endl; + stream << " statustext: " << val["statustext"] << endl; + stream << " comments: " << val["comments"] << endl; + } + else + { + stream << "- deal: " << val["deal"] << endl; + stream << " date: " << val["date"] << endl; + stream << " statustext: " << val["statustext"] << endl; + stream << " comments: " << val["comments"] << endl; + } + + /* + - deal: ff5f337f-e0ab-4515-857f-3a0c8530dcd3 + date: '2025-10-05T15:29:23' + statustext: positive + comments: positive comment about the deal + + */ + } + stream << "------------Summary--------------" << endl; + stream << "total: " << size << endl; + stream << "positive: " << positivefb << endl; + stream << "neegative: " << negativefb << endl; + + string decoded = stream.str(); + cout << decoded << endl; + + if (isDebug) ShowDebug(url, result, 1, decoded); + + + return 0; + + + return 0; +} \ No newline at end of file diff --git a/dm-cli/AccountStatus.hpp b/dm-cli/AccountStatus.hpp new file mode 100644 index 0000000..764acd7 --- /dev/null +++ b/dm-cli/AccountStatus.hpp @@ -0,0 +1,33 @@ +#ifndef _ACCOUNT_STATUS_ +#define _ACCOUNT_STATUS_ +#include +/// @brief ПОлучение справки о параметрах команды +/// @param isRussian - указывает выводить ли русскую справку +void AccountHelp(bool isRussian); +/// @brief Получение статуса аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountStatus(const std::string address, const char *bkaddress, bool isDebug); + +/// @brief Получение информации аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountInfo(const std::string address, const char* bkaddress, bool isDebug); + +/// @brief Получение Рейтинга аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +int AccountRaiting(const std::string address, const char* bkaddress, bool isDebug); + + +/// @brief Получение Рейтинга аккаунта +/// @param address адресс АПИ +/// @param bkaddress номер кошелька +/// @param isDebug флаг отладки +/// @param fb - тип фидбэка 0- все p - 1(positive) n-2 (negative) +int AccountFeedbacks(const std::string address, const char* bkaddress, bool isDebug, int fb); + +#endif \ No newline at end of file diff --git a/dm-cli/AccountUpdate.cpp b/dm-cli/AccountUpdate.cpp new file mode 100644 index 0000000..37c2b71 --- /dev/null +++ b/dm-cli/AccountUpdate.cpp @@ -0,0 +1,299 @@ +#include "AccountUpdate.hpp" +#include +#include +#include "PrintFile.hpp" +#include "common.hpp" +#include "ExecCommand.hpp" +#include "json.hpp" +#include "base64.h" +#include +#include "cleanHtml.h" +#include +#include +using namespace std; + +int AccountUpdate::Help() +{ + if (this->isRussian) + PrintFile(ACCOUNT_UPDATE_RU); + else + PrintFile(ACCOUNT_UPDATE_EN); + return 0; +} + +AccountUpdate::AccountUpdate(const InputParser &parser, const bool isRussian) +{ + this->parser = parser; + this->isRussian = isRussian; + address = (DEFAULTADDRESS); + const string &addressarg = parser.getCmdOption("--address"); + if (!addressarg.empty()) + { + address = addressarg; + } + isDebug = false; + if (parser.cmdOptionExists("--debug")) + { + isDebug = true; + } +} + +int AccountUpdate::Process() +{ + if (this->parser.cmdOptionExists("--help")) + return this->Help(); + return Update(); +} +int AccountUpdate::ProcessUrl(std::string date, std::string signature, std::string urls) +{ + /* + curl -X POST "https://testnet-dm2.bitdeals.org/api/v1/client/update" \ + -H "Content-Type: application/json" \ + -d '{"address":"mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp","date":"2025-10-21","url":["https://testnet-dm2.bitdeals.org"], + "sign":"IAGHICUSCxUrcWTMSL9j94vRufb9l5nBckahT+RznlHMPx9LTPpDHsozxVyxkpjtgrhC8eCyJKNaOw8U/v56pL0="}' + */ + /* + [{{URLS}}], + */ + std::stringstream test(urls); + std::string segment; + std::vector seglist; + string urlout(""); + while (std::getline(test, segment, ',')) + { + urlout.append("\\\""); + urlout.append(segment); + urlout.append("\\\","); + seglist.push_back(segment); + } + urlout = urlout.substr(0, urlout.length() - 1); + string data("curl -s "); + data += ReadFile(ACCOUNT_UPDATE_URL); + string bt(""); + bt = parser.getLast(); + data = Replace(data, string("{{ADDRESS}}"), address); + data = Replace(data, string("{{BT}}"), bt); + data = Replace(data, string("{{DATE}}"), date); + data = Replace(data, string("{{SIGN}}"), signature); + data = Replace(data, string("{{URLS}}"), urlout); + + string result = ExecCommand(data.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + std::ostringstream stream; + stream << "success: " << jsonData["result"]["success"] << endl; + stream << "message: " << jsonData["result"]["message"] << endl; + string decoded = stream.str(); + cout << decoded << endl; + string payload = base64_decode(jsonData["payload"]); + if (isDebug) + ShowDebug(data, decoded, 1, payload); + + return 0; +} + +int AccountUpdate::ProcessPgp(std::string date, std::string signature, std::string pgp) +{ + + string data("curl "); + data += ReadFile(ACCOUNT_UPDATE_PGP); + string bt(""); + bt = parser.getLast(); + data = Replace(data, string("{{ADDRESS}}"), address); + data = Replace(data, string("{{BT}}"), bt); + data = Replace(data, string("{{DATE}}"), date); + data = Replace(data, string("{{SIGN}}"), signature); + data = Replace(data, string("{{PGP}}"), pgp); + + string result = ExecCommand(data.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + std::ostringstream stream; + stream << "success: " << jsonData["result"]["success"] << endl; + stream << "message: " << jsonData["result"]["message"] << endl; + string decoded = stream.str(); + cout << decoded << endl; + string payload = cleanup_html(base64_decode(jsonData["payload"])); + if (isDebug) + ShowDebug(data, decoded, 1, payload); + + return 0; +} + +int AccountUpdate::ProcessBitmessage(std::string date, std::string signature, std::string btmsg) +{ + + string data("curl "); + data += ReadFile(ACCOUNT_UPDATE_BTM); + string bt(""); + bt = parser.getLast(); + data = Replace(data, string("{{ADDRESS}}"), address); + data = Replace(data, string("{{BT}}"), bt); + data = Replace(data, string("{{DATE}}"), date); + data = Replace(data, string("{{SIGN}}"), signature); + data = Replace(data, string("{{BTM}}"), btmsg); + + string result = ExecCommand(data.c_str()); + nlohmann::json jsonData = nlohmann::json::parse(result); + + std::ostringstream stream; + stream << "success: " << jsonData["result"]["success"] << endl; + stream << "message: " << jsonData["result"]["message"] << endl; + string decoded = stream.str(); + cout << decoded << endl; + string payload = cleanup_html(base64_decode(jsonData["payload"])); + if (isDebug) + ShowDebug(data, decoded, 1, payload); + + return 0; +} +int AccountUpdate::Update() +{ + if (!this->parser.cmdOptionExists("-d") && !this->parser.cmdOptionExists("--date")) + { + cout << "option -d | --date required" << endl; + return 1; + } + if (!this->parser.cmdOptionExists("-s") && !this->parser.cmdOptionExists("--signature")) + { + cout << "option -s | --signature required" << endl; + return 1; + } + + if (!this->parser.cmdOptionExists("-p") && !this->parser.cmdOptionExists("--pgp") && !this->parser.cmdOptionExists("-u") && !this->parser.cmdOptionExists("--url") && !this->parser.cmdOptionExists("-b") && !this->parser.cmdOptionExists("--bitmessage")) + { + cout << "one of this parameter required: -p | --pgp, -u| --url, -b| --bitmessage" << endl; + return 1; + } + + string datavalue(""); + if (this->parser.cmdOptionExists("-d")) + { + string vl = this->parser.getCmdOption("-d"); + if (vl.length() > 0) + { + datavalue = vl; + } + } + if (this->parser.cmdOptionExists("--data")) + { + string vl = this->parser.getCmdOption("--data"); + if (vl.length() > 0) + { + datavalue = vl; + } + } + if (datavalue.length() == 0) + { + cout << "data cold't be empty" << endl; + return 1; + } + + string signvalue(""); + if (this->parser.cmdOptionExists("-s")) + { + string vl = this->parser.getCmdOption("-s"); + if (vl.length() > 0) + { + signvalue = vl; + } + } + if (this->parser.cmdOptionExists("--signature")) + { + string vl = this->parser.getCmdOption("--signature"); + if (vl.length() > 0) + { + signvalue = vl; + } + } + if (signvalue.length() == 0) + { + cout << "signature cold't be empty" << endl; + return 1; + } + + // делаем обновление url + if (this->parser.cmdOptionExists("-u") || this->parser.cmdOptionExists("--url")) + { + string urlvalue(""); + if (this->parser.cmdOptionExists("-u")) + { + string vl = this->parser.getCmdOption("-u"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (this->parser.cmdOptionExists("--url")) + { + string vl = this->parser.getCmdOption("--url"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (urlvalue.length() == 0) + { + cout << "url cold't be empty" << endl; + return 1; + } + return ProcessUrl(datavalue, signvalue, urlvalue); + } + if (this->parser.cmdOptionExists("-b") || this->parser.cmdOptionExists("--bitmessage")) + { + string urlvalue(""); + if (this->parser.cmdOptionExists("-b")) + { + string vl = this->parser.getCmdOption("-b"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (this->parser.cmdOptionExists("--bitmessage")) + { + string vl = this->parser.getCmdOption("--bitmessage"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (urlvalue.length() == 0) + { + cout << "bitmessage cold't be empty" << endl; + return 1; + } + return ProcessBitmessage(datavalue, signvalue, urlvalue); + } + + else if (this->parser.cmdOptionExists("-p") || this->parser.cmdOptionExists("--pgp")) + { + string urlvalue(""); + if (this->parser.cmdOptionExists("-p")) + { + string vl = this->parser.getCmdOption("-p"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (this->parser.cmdOptionExists("--pgp")) + { + string vl = this->parser.getCmdOption("--pgp"); + if (vl.length() > 0) + { + urlvalue = vl; + } + } + if (urlvalue.length() == 0) + { + cout << "pgp cold't be empty" << endl; + return 1; + } + return ProcessPgp(datavalue, signvalue, urlvalue); + } + cout << "no argument" << endl; + return 1; + + return 0; +} diff --git a/dm-cli/AccountUpdate.hpp b/dm-cli/AccountUpdate.hpp new file mode 100644 index 0000000..9fa0da2 --- /dev/null +++ b/dm-cli/AccountUpdate.hpp @@ -0,0 +1,27 @@ +#ifndef _ACCOUNT_UPDATE_ +#define _ACCOUNT_UPDATE_ +#include +#include "InputParser.hpp" + +class AccountUpdate { +public: + /// @brief Конструктор + /// @param parser - парсер аргументов + /// @param isRussian - вывод справки на русском + AccountUpdate(const InputParser& parser, const bool isRussian); + int Process(); +private: + int ProcessUrl(std::string date, std::string signature, std::string urls); + int ProcessBitmessage(std::string date, std::string signature, std::string btmsg); + int ProcessPgp(std::string date, std::string signature, std::string pgp); + InputParser parser; + bool isRussian; + /// @brief Получение справки о параметрах команды + int Help(); + + /// @brief Обновление данных, url через запятую + int Update(); + std::string address; + bool isDebug; +}; +#endif \ No newline at end of file diff --git a/dm-cli/Deals.cpp b/dm-cli/Deals.cpp new file mode 100644 index 0000000..25e8eac --- /dev/null +++ b/dm-cli/Deals.cpp @@ -0,0 +1,104 @@ +#include "Deals.hpp" +#include +#include +#include "PrintFile.hpp" +#include "common.hpp" +#include "ExecCommand.hpp" +#include "json.hpp" +#include "base64.h" +#include +#include "cleanHtml.h" +#include +#include + +using namespace std; + +int Deals::HelpCreate() const { + if (isRussian) + PrintFile(DEALS_RU); + else + PrintFile(DEALS_EN); + return 0; +} +int Deals::HelpDealStatus() const +{ + if (isRussian) + PrintFile(DEAL_STATUS_RU); + else + PrintFile(DEAL_STATUS_EN); + return 0; +} +int Deals::HelpDealComplete() const +{ + if (isRussian) + PrintFile(DEAL_COMPLETE_RU); + else + PrintFile(DEAL_COMPLETE_EN); + return 0; +} +int Deals::HelpDealCancel() const +{ + if (isRussian) + PrintFile(DEAL_CANCEL_RU); + else + PrintFile(DEAL_CANCEL_EN); + return 0; + +} +int Deals::HelpDealNegative() const +{ + if (isRussian) + PrintFile(DEAL_NEGATIVE_RU); + else + PrintFile(DEAL_NEGATIVE_EN); + return 0; +} +Deals::Deals(const InputParser& parser, const bool isRussian, const string address, bool isDebug) +{ + this->parser = parser; + this->isRussian = isRussian; + this->address = address; + this->isDebug = isDebug; +} + +int Deals::Process() +{ + + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("create") && this->parser.cmdOptionExists("--help")) + return this->HelpCreate(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("status") && this->parser.cmdOptionExists("--help")) + return this->HelpDealStatus(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("complete") && this->parser.cmdOptionExists("--help")) + return this->HelpDealComplete(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("cancel") && this->parser.cmdOptionExists("--help")) + return this->HelpDealCancel(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("negative") && this->parser.cmdOptionExists("--help")) + return this->HelpDealNegative(); + + + return Update(); + return 0; +} + +int Deals::Update() { + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("create")) + return Create(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("status")) + return Status(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("complete")) + return Complite(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("cancel")) + return Cancel(); + if (parser.cmdOptionExists("deal") && this->parser.cmdOptionExists("negative")) + return Negative(); + return 1; +} +int Deals::Create() { + return 0; +} + + +int Deals::Status() { return 0; } +int Deals::Complite() { return 0; } +int Deals::Cancel() { return 0; } +int Deals::Negative() { return 0; } diff --git a/dm-cli/Deals.hpp b/dm-cli/Deals.hpp new file mode 100644 index 0000000..a51cadb --- /dev/null +++ b/dm-cli/Deals.hpp @@ -0,0 +1,36 @@ +#ifndef _DEALS_ +#define _DEALS_ +#include +#include "InputParser.hpp" + +class Deals { +public: + /// @brief Конструктор + /// @param parser - парсер аргументов + /// @param isRussian - вывод справки на русском + Deals(const InputParser& parser, const bool isRussian, const std::string address, bool isDebug); + int Process(); +private: + InputParser parser; + bool isRussian; + std::string address; + bool isDebug; + + /// @brief Получение справки о параметрах команды + int HelpCreate() const; + int HelpDealStatus() const; + int HelpDealComplete() const; + int HelpDealCancel() const; + int HelpDealNegative() const; + int Update(); + int Create(); + int Status(); + int Complite(); + int Cancel(); + int Negative(); + + + + +}; +#endif \ No newline at end of file diff --git a/dm-cli/ExecCommand.cpp b/dm-cli/ExecCommand.cpp new file mode 100644 index 0000000..f84dbf5 --- /dev/null +++ b/dm-cli/ExecCommand.cpp @@ -0,0 +1,25 @@ +#include "ExecCommand.hpp" +#include +#include +#include +#include +#include +#include + +#ifdef WINDOWS + #define pclose _pclose + #define popen _popen +#endif // WINDOWS + +std::string ExecCommand(const char* cmd) { + std::array buffer; + std::string result; + std::unique_ptr pipe(popen(cmd, "r"), pclose); + if (!pipe) { + throw std::runtime_error("popen() failed!"); + } + while (fgets(buffer.data(), static_cast(buffer.size()), pipe.get()) != nullptr) { + result += buffer.data(); + } + return result; +} \ No newline at end of file diff --git a/dm-cli/ExecCommand.hpp b/dm-cli/ExecCommand.hpp new file mode 100644 index 0000000..cb4b75b --- /dev/null +++ b/dm-cli/ExecCommand.hpp @@ -0,0 +1,5 @@ +#ifndef _EXEC_COMMAND_H_ +#define _EXEC_COMMAND_H_ +#include +std::string ExecCommand(const char* cmd); +#endif \ No newline at end of file diff --git a/dm-cli/InputParser.hpp b/dm-cli/InputParser.hpp new file mode 100644 index 0000000..a7e2c2d --- /dev/null +++ b/dm-cli/InputParser.hpp @@ -0,0 +1,75 @@ +#ifndef _INPUTPARSER_ +#define _INPUTPARSER_ +#include +#include +#include +#include +/// @brief Анализирует входящие параметры +class InputParser +{ +public: + InputParser(){} + InputParser(int &argc, char **argv) + { + for (int i = 1; i < argc; ++i) + this->tokens.push_back(std::string(argv[i])); + } + /// @brief Пакует без параметров --debug и address + /// @param argc + /// @param argv + InputParser(int &argc, char **argv, bool skip) + { + for (int i = 1; i < argc; ++i) + { + std::string cur(argv[i]); + if (cur.compare("--debug") == 0) + { + ++i; + continue; + } + if (cur.compare("--address") == 0) + { + i += 2; + continue; + } + this->tokens.push_back(cur); + } + } + /// @brief получение строки параметров + const std::string &getCmdOption(const std::string &option) const + { + std::vector::const_iterator itr; + itr = std::find(this->tokens.begin(), this->tokens.end(), option); + if (itr != this->tokens.end() && ++itr != this->tokens.end()) + { + return *itr; + } + static const std::string empty_string(""); + return empty_string; + } + /// @brief get last argument + const std::string& getLast() { + return tokens[tokens.size() - 1]; + } + const void getBuffer() const + { + std::string ret; + for (const auto &s : this->tokens) + { + if (!ret.empty()) + ret += ","; + ret += s; + } + std::cout << ret << std::endl; + } + /// @brief существует ли параметр + bool cmdOptionExists(const std::string &option) const + { + return std::find(this->tokens.begin(), this->tokens.end(), option) != this->tokens.end(); + } + +private: + std::vector tokens; +}; + +#endif \ No newline at end of file diff --git a/dm-cli/Makefile b/dm-cli/Makefile new file mode 100644 index 0000000..3287580 --- /dev/null +++ b/dm-cli/Makefile @@ -0,0 +1,18 @@ +CC=g++ +# CFLAGS=-c -Wall +CFLAGS=-c -Wall -g #debug version +# LDFLAGS= +LDFLAGS= -g +SOURCES=AccountStatus.cpp base64.cpp cleanHtml.cpp ExecCommand.cpp help.cpp main.cpp PrintFile.cpp ShowDebug.cpp AccountUpdate.cpp ReadFile.cpp Replace.cpp Deals.cpp +OBJECTS=$(SOURCES:.cpp=.o) +EXECUTABLE=dm-cli + +all: $(SOURCES) $(EXECUTABLE) + +$(EXECUTABLE): $(OBJECTS) + $(CC) $(LDFLAGS) $(OBJECTS) -o $@ + +.cpp.o: + $(CC) $(CFLAGS) $< -o $@ +clean: + rm *.o \ No newline at end of file diff --git a/dm-cli/PrintFile.cpp b/dm-cli/PrintFile.cpp new file mode 100644 index 0000000..2d0dc7f --- /dev/null +++ b/dm-cli/PrintFile.cpp @@ -0,0 +1,23 @@ +#include "PrintFile.hpp" +#include +#include +#include +using namespace std; + +void PrintFile(const char *fileName) +{ + ifstream inputFile(fileName); + if (inputFile.is_open()) + { + string line; + while (getline(inputFile, line)) + { + cout << line << endl; + } + inputFile.close(); + } + else + { + cerr << "Error: Unable to open file " << fileName << endl; + } +} \ No newline at end of file diff --git a/dm-cli/PrintFile.hpp b/dm-cli/PrintFile.hpp new file mode 100644 index 0000000..693eec5 --- /dev/null +++ b/dm-cli/PrintFile.hpp @@ -0,0 +1,4 @@ +#ifndef _PRINT_FILE_ +#define _PRINT_FILE_ +void PrintFile(const char *fileName); +#endif \ No newline at end of file diff --git a/dm-cli/ReadFile.cpp b/dm-cli/ReadFile.cpp new file mode 100644 index 0000000..72c5d17 --- /dev/null +++ b/dm-cli/ReadFile.cpp @@ -0,0 +1,26 @@ + +#include "common.hpp" +#include +#include +#include +using namespace std; + +std::string ReadFile(const char* filename) { + string data(""); + ifstream inputFile(filename); + if (inputFile.is_open()) + { + string line; + while (getline(inputFile, line)) + { + data.append(line); + // data.append("\r\n"); + } + inputFile.close(); + } + else + { + cerr << "Error: Unable to open file " << filename << endl; + } + return data; +} \ No newline at end of file diff --git a/dm-cli/Replace.cpp b/dm-cli/Replace.cpp new file mode 100644 index 0000000..3a8fb84 --- /dev/null +++ b/dm-cli/Replace.cpp @@ -0,0 +1,9 @@ +#include +#include "common.hpp" +std::string Replace(std::string source, std::string from, std::string out) { + size_t start = 0, stop = 0; + start = source.find(from); + stop = from.length(); + if (start > -1 && stop) return source.replace(start, stop, out); + return std::string(""); +} \ No newline at end of file diff --git a/dm-cli/ShowDebug.cpp b/dm-cli/ShowDebug.cpp new file mode 100644 index 0000000..dd4f339 --- /dev/null +++ b/dm-cli/ShowDebug.cpp @@ -0,0 +1,22 @@ +#include "common.hpp" +#include +#include +using namespace std; +extern char** global_argv; +extern int global_argc; +void ShowDebug(std::string url, std::string result, bool success, std::string decoded) { + + std::ostringstream stream; + for (int i = 0; i < global_argc; ++i) { + if (i) stream << ' '; + stream << global_argv[i]; + } + std::string cmdstring = stream.str(); + cout << "---------------DEBUG---------------" << endl; + cout << "command: " << cmdstring << endl; + cout << "success: " << success << endl; + cout << "url: " << url << endl; + cout << "Result: " << endl << result << endl; + cout << "Payload: " << endl << decoded << endl; + cout << "---------------END DEBUG---------------" << endl; +} \ No newline at end of file diff --git a/dm-cli/account_status_en.txt b/dm-cli/account_status_en.txt new file mode 100644 index 0000000..50313a4 --- /dev/null +++ b/dm-cli/account_status_en.txt @@ -0,0 +1,9 @@ +Usage: dm-cli account status [options] + + Show info about a bitdeals user. + + -f|--feedbacks [p|n] Show last 1K received feedbacks. + Use p or n to filter only positive or negative feedbacks. + -i|--info Show user account details. + -r|--rating Show user rating information. + -s|--status Show user account status (default action). \ No newline at end of file diff --git a/dm-cli/account_status_ru.txt b/dm-cli/account_status_ru.txt new file mode 100644 index 0000000..ac6fae9 --- /dev/null +++ b/dm-cli/account_status_ru.txt @@ -0,0 +1,9 @@ +Использование: dm-cli account status [параметры] <биткоин адрес> + + Показать информацию о пользователе bitdeals. + + -f|--feedbacks [p|n] Показать последнюю 1 тыс. полученных отзывов. + Используй p или n для фильтрации только позитивных или негативных отзывов. + -i|--info Показать данные учётной записи. + -r|--rating Показать данные рейтинга. + -s|--status Показать статус пользователя (действие по умолчанию). \ No newline at end of file diff --git a/dm-cli/account_update_en.txt b/dm-cli/account_update_en.txt new file mode 100644 index 0000000..dccb9b7 --- /dev/null +++ b/dm-cli/account_update_en.txt @@ -0,0 +1,15 @@ +Usage: dm-cli account update [options] + + Update user account data. + + To change the account data you should sign the current date and new user data + with your bitcoin private key. For example, current date, new bitmessage, signature: + 2020-01-01 + BM-2cUuxYUFWLCrtpKRMdHCpU1QKEuFtHh7vu + IEF1ysyhu8ps0m5xSJaZZg/5hBylmcWQQggkGO7yNN8iMf/EA2O287kxi58xCDDtxvdsC0TWqylVE5MT5CouamU= + + -d|--date Current date. + -s|--signature Bitcoin signature. + -p|--pgp Set up an armored RSA pgp key. + -u|--url [+/-] Add/remove an url to trusted list. + -b|--bitmessage Change bitmessage address. \ No newline at end of file diff --git a/dm-cli/base64.cpp b/dm-cli/base64.cpp new file mode 100644 index 0000000..8f2d736 --- /dev/null +++ b/dm-cli/base64.cpp @@ -0,0 +1,94 @@ +#include "base64.h" + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + size_t i = 0; + size_t j = 0; + size_t char_array_3[3]; + size_t char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; (i <4) ; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while((i++ < 3)) + ret += '='; + + } + + return ret; + +} +std::string base64_decode(std::string const& encoded_string) { + size_t in_len = encoded_string.size(); + size_t i = 0; + size_t j = 0; + size_t in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && ( encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i ==4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +} \ No newline at end of file diff --git a/dm-cli/base64.h b/dm-cli/base64.h new file mode 100644 index 0000000..3f69a46 --- /dev/null +++ b/dm-cli/base64.h @@ -0,0 +1,12 @@ +#ifndef _BASE64_H_ +#define _BASE64_H_ +#include +/// @brief Кодирование в BASE64 +/// @param bytes_to_encode буфер для декодирования +/// @param in_len длина буфера +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len); +/// @brief Декодирование из BASE64 +/// @param encoded_string Строкадля декодирования +std::string base64_decode(std::string const& encoded_string); + +#endif \ No newline at end of file diff --git a/dm-cli/check.sh b/dm-cli/check.sh new file mode 100644 index 0000000..232cb11 --- /dev/null +++ b/dm-cli/check.sh @@ -0,0 +1 @@ +./dm-cli --address https://testnet-dm2.bitdeals.org --debug account update -d 2020-01-01 -s IEF1ysyhu8ps0m5xSJaZZg/5hBylmcWQQggkGO7yNN8iMf/EA2O287kxi58xCDDtxvdsC0TWqylVE5MT5CouamU= -b btmmessage mnumHs9HQMrw2Q1iKLNnx9NzExS7nMLmyp \ No newline at end of file diff --git a/dm-cli/cleanHtml.cpp b/dm-cli/cleanHtml.cpp new file mode 100644 index 0000000..8014d6a --- /dev/null +++ b/dm-cli/cleanHtml.cpp @@ -0,0 +1,28 @@ +#include "cleanHtml.h" + +std::string cleanup_html(std::string const &encoded_string) +{ + + size_t start = encoded_string.find("
") + 5;
+	size_t last = encoded_string.find("
"); + std::string ret; + ret = encoded_string.substr(start, last - start); + + size_t b = 0; + for (size_t a = b; a < ret.length(); a++) + { + if (ret[a] == '<') + { + for (size_t b = a; b < ret.length(); b++) + { + if (ret[b] == '>') + { + ret.erase(a, (b - a + 1)); + break; + } + } + } + } + + return ret; +} \ No newline at end of file diff --git a/dm-cli/cleanHtml.h b/dm-cli/cleanHtml.h new file mode 100644 index 0000000..968d4bc --- /dev/null +++ b/dm-cli/cleanHtml.h @@ -0,0 +1,9 @@ +#ifndef _CLEANHTML_H_ +#define _CLEANHTML_H_ +#include + +/// @brief Удаление HTML тэгов +/// @param encoded_string срока с HTML +std::string cleanup_html(std::string const& encoded_string); + +#endif \ No newline at end of file diff --git a/dm-cli/common.hpp b/dm-cli/common.hpp new file mode 100644 index 0000000..51ec881 --- /dev/null +++ b/dm-cli/common.hpp @@ -0,0 +1,53 @@ +#ifndef _COMMON_ +#define _COMMON_ +#include + +#define PROGRAM_VERSION "1.0.1" +#define MAIN_HELP_RU "main_help_ru.txt" +#define MAIN_HELP_EN "main_help_en.txt" + +#define ACCOUNT_STATUS_RU "account_status_ru.txt" +#define ACCOUNT_STATUS_EN "account_status_en.txt" + +#define ACCOUNT_UPDATE_RU "account_update_en.txt" +#define ACCOUNT_UPDATE_EN "account_update_ru.txt" + +#define DEALS_EN "deals_en.txt" +#define DEALS_RU "deals_ru.txt" + +#define DEAL_STATUS_RU "deal_status_ru.txt" +#define DEAL_STATUS_EN "deal_status_en.txt" + +#define DEAL_COMPLETE_RU "deal_complete_ru.txt" +#define DEAL_COMPLETE_EN "deal_complete_en.txt" + + +#define DEAL_CANCEL_RU "deal_cancel_ru.txt" +#define DEAL_CANCEL_EN "deal_cancel_en.txt" + +#define DEAL_NEGATIVE_RU "deal_negative_ru.txt" +#define DEAL_NEGATIVE_EN "deal_negative_en.txt" + + + +// LANG=ru_RU.UTF-8 +#define LANG_RU "ru_RU.UTF-8" +#define DEFAULTADDRESS "https://127.0.0.1:4999" + +#define ACCOUNT_UPDATE_URL "tpl/accountupdateurl.txt" +#define ACCOUNT_UPDATE_BTM "tpl/accountupdatebtm.txt" +#define ACCOUNT_UPDATE_PGP "tpl/accountupdatepgp.txt" + +/* +Show help screen. +*/ +void show_help(bool isRulang); +/// @brief Отображает отладочную информацию +void ShowDebug(std::string url, std::string result, bool success, std::string decoded); + +/// @breef read file +std::string ReadFile(const char *filename); +/// @breef Replace in string +std::string Replace(std::string source, std::string from, std::string out); + +#endif diff --git a/dm-cli/createdistr.sh b/dm-cli/createdistr.sh new file mode 100644 index 0000000..3736571 --- /dev/null +++ b/dm-cli/createdistr.sh @@ -0,0 +1 @@ +tar -czvf dm-cli_distr.tar.gz tpl dm-cli *.txt \ No newline at end of file diff --git a/dm-cli/deal_cancel_en.txt b/dm-cli/deal_cancel_en.txt new file mode 100644 index 0000000..5596a99 --- /dev/null +++ b/dm-cli/deal_cancel_en.txt @@ -0,0 +1,12 @@ +Usage: dm-cli deal cancel [options] + + Cancel a deal + + To cancel a deal you should sign the deal payment address and feeback text message + with the seller bitcoin private key. For example, address, feedback, signature: + 2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5 + seller random cancel reason text + IEOGJ5q/a2cWJPMosQmCHNN6RsXF8Xy/UgaazIoY2i5udbw/v38g1/PdWs451dvFr9Iq/Bq5YL2YdpUFTuijQ60= + + -m|--message Deal cancel reason text message + -s|--signature Bitcoin signature. \ No newline at end of file diff --git a/dm-cli/deal_cancel_ru.txt b/dm-cli/deal_cancel_ru.txt new file mode 100644 index 0000000..791ada2 --- /dev/null +++ b/dm-cli/deal_cancel_ru.txt @@ -0,0 +1,12 @@ +Использование: dm-cli deal cancel [параметры] <биткоин адрес> + + Отменить сделку + + Для отмены сделки вы должны подписать адрес оплаты сделки и текст отзыва биткоин + ключом продавца. Например, адрес, отзыв, подпись: + 2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5 + seller random cancel reason text + IEOGJ5q/a2cWJPMosQmCHNN6RsXF8Xy/UgaazIoY2i5udbw/v38g1/PdWs451dvFr9Iq/Bq5YL2YdpUFTuijQ60= + + -m|--message Текст сообщения с причино отмены сделки + -s|--signature Биткоин подпись. \ No newline at end of file diff --git a/dm-cli/deal_complete_en.txt b/dm-cli/deal_complete_en.txt new file mode 100644 index 0000000..bc376d7 --- /dev/null +++ b/dm-cli/deal_complete_en.txt @@ -0,0 +1,6 @@ +Usage: dm-cli deal complete [options] { | } + + Complete a deal + + -p|--positive Complete deal with positive feedback. (default action) + -r|--refund Refund % number of a deal sum to the customer. Format: 100.00[%] \ No newline at end of file diff --git a/dm-cli/deal_complete_ru.txt b/dm-cli/deal_complete_ru.txt new file mode 100644 index 0000000..3d28b73 --- /dev/null +++ b/dm-cli/deal_complete_ru.txt @@ -0,0 +1,6 @@ +Использование: dm-cli deal complete [параметры] { <биткоин адес>|<код сделки> } + + Завершить сделку + + -p|--positive Завершить сделку с позитивным отзывом. (действие по умолчанию) + -r|--refund Возврат % от суммы сделки покупателю. Формат: 100.00[%] \ No newline at end of file diff --git a/dm-cli/deal_negative_en.txt b/dm-cli/deal_negative_en.txt new file mode 100644 index 0000000..18bf374 --- /dev/null +++ b/dm-cli/deal_negative_en.txt @@ -0,0 +1,12 @@ +Usage: dm-cli deal negative [options] + + Leave a negative feedback + + To leave a negative feedback you should sign the deal payment address and feeback text message + with the customer bitcoin private key. For example, address, feedback, signature: + 2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5 + customer random feedback text + H1u44C5cyEeKjHqnNnn09B8mIRMdqgR8PD9AeF8mv+cCEqM9HPkcWLrc8a/v2po2YmXJSeya6uy0XaLnmmmO/1o= + + -m|--message Deal feedback text message + -s|--signature Bitcoin signature. \ No newline at end of file diff --git a/dm-cli/deal_negative_ru.txt b/dm-cli/deal_negative_ru.txt new file mode 100644 index 0000000..715d4e3 --- /dev/null +++ b/dm-cli/deal_negative_ru.txt @@ -0,0 +1,12 @@ +Использование: dm-cli deal negative [options] <биткоин адрес> + + Оставить негативный отзыв + + Для оставления негативного отзыва ва должны подписать адрес оплаты сделки и текст отзыва биткоин + ключом покупателя. Например, адрес, отзыв, подпись: + 2NEVoXnRgUeb3j17s7pP6DoFHBVHMb94gF5 + customer random feedback text + H1u44C5cyEeKjHqnNnn09B8mIRMdqgR8PD9AeF8mv+cCEqM9HPkcWLrc8a/v2po2YmXJSeya6uy0XaLnmmmO/1o= + + -m|--message Текст сообщения отзыва + -s|--signature Биткоин подпись. \ No newline at end of file diff --git a/dm-cli/deal_status_en.txt b/dm-cli/deal_status_en.txt new file mode 100644 index 0000000..81b3515 --- /dev/null +++ b/dm-cli/deal_status_en.txt @@ -0,0 +1,7 @@ +Usage: dm-cli deal status { | } + + Show a deal data details + + To show a deal details use a bitcoin payment address or a deal code. + + -i|--is-paid Check a deal is Paid. Returns an exit code 0 if deal is Paid, or non-zero otherwise. \ No newline at end of file diff --git a/dm-cli/deal_status_ru.txt b/dm-cli/deal_status_ru.txt new file mode 100644 index 0000000..d97d215 --- /dev/null +++ b/dm-cli/deal_status_ru.txt @@ -0,0 +1,7 @@ +Использование: dm-cli deal status { <биткоин адрес>|<код сделки> } + + Показать детали сделки + + Чтобы показать детали сделки используйте адрес оплаты сделки или код сделки. + + -i|--is-paid Проверить является ли сделка оплаченной. Возвращает exit code 0 если сделка является оплаченной, или не ноль в других случаях. \ No newline at end of file diff --git a/dm-cli/deals_en.txt b/dm-cli/deals_en.txt new file mode 100644 index 0000000..b2b7ecf --- /dev/null +++ b/dm-cli/deals_en.txt @@ -0,0 +1,17 @@ +Usage: dm-cli deal create [options] + + Create a new deal + + [smhd] means seconds, minutes, hours, days. + For example: --leave-before 2020-01-01, or --leave-before 10d. + + -a|--at Deal site + -s|--seller Seller user in deal + -c|--customer Customer user in deal + -t|--type [prepayment|postpayment] + Deal type + -s|--sum Deal sum in BTC + -l|--leave-before { [hh:mm:ss UTC] |