golang

Fitter —  сшиватель API/Website's.  Большое обновление

  • среда, 31 января 2024 г. в 00:00:16
https://habr.com/ru/articles/789952/

Добрый вечер всем!

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

Итак, что появилось:

  1. Написано, какое-никакое README.md , которое регулярно пополняется фишками.

  2. Добавлена возможность использования как библиотека для go.

  3.  Добавлена поддержка плагинов на go.

  4. Добавлена поддержка прокси для коннекторов (server/playwright).

  5. Добавлена возможность отправки обновлений в console(stdout)/telegram/http/redis.

  6. Убрано огромное дуплицирование кода с помощью generic.

  7. Добавлена возможность скачивать файлы.

  8. Добавлена возможность делать вычисляемые поля и благодаря этому можно делать супер связки конфигураций(об этом ниже).

  9. Добавлено возможность создавать reference(можно кэшировать данные и переиспользовать их) и инжектить переменные среды.

  10. Добавлена возможность делать fallback на любые поля если оно пустое.

Напоследок хотелось бы показать пример конфигурации которую делал для друга. И так его задача с сохранением орфографии:

  1. ну сначала нужно получить все позиции юзера https://docs.saucerswap.finance/v/developer/saucerswap-v2/liquidity-operations/get-user-positions

  2. потом все пулы https://docs.saucerswap.finance/v/developer/saucerswap-v2/liquidity-operations/fetch-all-pools

  3. и потом заметчить позиции юзера с пулами что бы определить какие позици вне диапазона пула

И так что получилось:

{
  "references": {
    "AllPoolRef": {
      "expire": "60",
      "connector_config": {
        "response_type": "json",
        "url": "https://api.saucerswap.finance/v2/pools/",
        "server_config": {
          "method": "GET"
        }
      },
      "model": {
        "array_config": {
          "item_config": {
            "fields": {
              "tokenA": {
                "base_field": {
                  "type": "string",
                  "path": "tokenA.symbol"
                }
              },
              "tokenB": {
                "base_field": {
                  "type": "string",
                  "path": "tokenB.symbol"
                }
              }
            }
          }
        }
      }
    },
    "AccountIdRef": {
      "connector_config": {
        "response_type": "json",
        "static_config": {
          "value": "{{{FromEnv=USER_ID}}}"
        }
      },
      "model": {
        "base_field": {
          "type": "string"
        }
      }
    }
  },
  "items": [
    {
      "name": "user-position",
      "connector_config": {
        "response_type": "json",
        "url": "https://api.saucerswap.finance/V2/nfts/{{{RefName=AccountIdRef}}}/positions",
        "server_config": {
          "method": "GET"
        }
      },
      "model": {
        "array_config": {
          "item_config": {
            "fields": {
              "position": {
                "base_field": {
                  "type": "object",
                  "generated": {
                    "formatted": {
                      "template": "tokenA={{{tokenA.symbol}}} tokenB={{{tokenB.symbol}}}"
                    }
                  }
                }
              },
              "value": {
                "base_field": {
                  "type": "object",
                  "path": "",
                  "generated": {
                    "calculated": {
                      "type": "boolean",
                      "expression": "any(fromJSON('{{{RefName=AllPoolRef}}}'), {.tokenA == '{{{tokenA.symbol}}}' && .tokenB == '{{{tokenB.symbol}}}'})"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "trigger_config": {
        "scheduler_trigger": {
          "interval": 10
        }
      },
      "notifier_config": {
        "expression": "any(fRes, {.value == true})",
        "telegram_bot": {
          "token": "{{{FromEnv=TELEGRAM_TOKEN}}}",
          "users_id": [],
          "pretty": true
        }
      }
    }
  ]
}

Тут есть два параметра из среды:

  1. TELEGRAM_TOKEN - строка 95

  2. USER_ID - строка 37

Все что надо было сделать другу это запустить Fitter и добавить в конфиг ID юзеров для нотификации(строка 95):

TELEGRAM_TOKEN=xxx USER_ID=xxx ./fitter --path=./config.json

Расскажу что тут происходит:

  1. Создаем Reference(строка 3) на все пулы и кэшируем на 60 секунд(строка 4). Мы берем и создаем массив объектов с двумя полями(символы двух токенов из пулов).

  2. Создаем Reference(строка 33) на AccountId, это будет просто строка.

  3. Мы создаем item для мониторинга каждые 10 секунд(строка 88) который берет данные с сервера с inject account Id(строка 52), который представляет из себя массив обьектов с двумя полями. Первое позиция(строка 66) - это шаблонная строка с inject результата. Второе это результат проверки содержится ли токены юзера в пуле из Reference(пункт первый) типа boolean.

  4. Дальше мы уведомляем если какое нибудь из полей имеет значение true(строка 93).

  5. Получаем в телегу уведомление:

Result for: user-position

[
 {
  "position": "tokenA=USDC tokenB=USDC[hts]",
  "value": true
 },
 {
  "value": false,
  "position": "tokenA=USDC tokenB=USDT"
 }
]

PS: false значения можно было игнорировать, но не стал.

Спасибо за внимание, продолжаю работать на проектом!