service: llama-apy

package:
  individually: true

frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs16.x
  stage: dev
  region: eu-central-1
  tracing:
    apiGateway: true
    lambda: true
  memorySize: 512
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - xray:PutTraceSegments
            - xray:PutTelemetryRecords
          Resource: '*'
        - Effect: Allow
          Action:
            - s3:ListBucket
            - s3:*Object*
            - sqs:SendMessage
          Resource: '*'

  environment:
    # for api handlers
    APIG_URL:
      {
        'Fn::Join':
          [
            '',
            [
              'https://',
              { Ref: 'HttpApi' },
              '.execute-api.',
              { Ref: 'AWS::Region' },
              '.',
              { Ref: 'AWS::URLSuffix' },
            ],
          ],
      }
    BUCKET_DATA: { Ref: BucketData }
    DATABASE_URL: ${file(./env.js):DATABASE_URL}

  httpApi:
    metrics: true

functions:
  # ---------- TRIGGER HANDLERS
  # --- top-lvl-entrypoint
  triggerEntrypoint:
    handler: src/handlers/triggerEntrypoint.handler
    description: Lambda to launch the adaptor pipeline
    timeout: 30
    events:
      # every new hour
      - schedule: cron(0 * * * ? *)
    environment:
      ADAPTER_QUEUE_URL: { Ref: AdapterQueue }

  # --- adaptors
  triggerAdaptor:
    handler: src/handlers/triggerAdaptor.handler
    description: Lambda which runs adaptors
    timeout: 600
    events:
      - sqs:
          arn:
            Fn::GetAtt:
              - AdapterQueue
              - Arn
          batchSize: 2
          functionResponseType: ReportBatchItemFailures
    environment:
      ALCHEMY_CONNECTION_ARBITRUM: ${file(./env.js):ALCHEMY_CONNECTION_ARBITRUM}
      ALCHEMY_CONNECTION_ETHEREUM: ${file(./env.js):ALCHEMY_CONNECTION_ETHEREUM}
      ETHEREUM_RPC: ${file(./env.js):ETHEREUM_RPC}
      XDAI_RPC: ${file(./env.js):XDAI_RPC}
      CRONOS_RPC: ${file(./env.js):CRONOS_RPC}
      FANTOM_RPC: ${file(./env.js):FANTOM_RPC}
      OPTIMISM_RPC: ${file(./env.js):OPTIMISM_RPC}
      AVAX_RPC: ${file(./env.js):AVAX_RPC}
      TVL_SPIKE_WEBHOOK: ${file(./env.js):TVL_SPIKE_WEBHOOK}
      NEW_YIELDS_WEBHOOK: ${file(./env.js):NEW_YIELDS_WEBHOOK}

  # --- data enrichment
  triggerEnrichment:
    handler: src/handlers/triggerEnrichment.handler
    description: Lambda which runs enrichment process
    timeout: 300
    events:
      # every hour at 20 past
      - schedule: cron(20 * * * ? *)

  # --- stats update
  triggerStat:
    handler: src/handlers/triggerStat.handler
    description: Lambda which updates the stat table
    timeout: 300
    events:
      # 30min prior midnight
      - schedule: cron(30 23 * * ? *)

  # --- median insert
  triggerMedian:
    handler: src/handlers/triggerMedian.handler
    description: Lambda which inserts latest value into the median table
    timeout: 300
    events:
      # 30min prior midnight
      - schedule: cron(30 23 * * ? *)

  # --- save poolsEnriched as CSV
  triggerCsv:
    handler: src/handlers/triggerCsv.handler
    description: Lambda which saves poolsEnriched as csv to s3 bucket
    timeout: 300
    events:
      # every hour at 25 past
      - schedule: cron(25 * * * ? *)

  # --- trigger monitor
  triggerMonitor:
    handler: src/handlers/triggerMonitor.handler
    description: Lambda which triggers the monitor query for logging stale adapters
    timeout: 300
    events:
      # every hour at 30 past
      - schedule: cron(30 * * * ? *)
    environment:
      STALE_PROJECTS_WEBHOOK: ${file(./env.js):STALE_PROJECTS_WEBHOOK}

  # --- trigger perpetuals
  triggerPerpertuals:
    handler: src/handlers/triggerPerpetuals.handler
    description: Lambda which triggers perp files
    timeout: 300
    events:
      # every new hour
      - schedule: cron(0 * * * ? *)

  # ---------- GET HANDLERS
  getPoolsEnriched:
    handler: src/handlers/getPoolsEnriched.handler
    description: Lambda for retrieving the latest enriched data for each unique pool
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /poolsEnriched
      - httpApi:
          method: get
          path: /pools

  # includes old pool values
  getPoolsEnrichedOld:
    handler: src/handlers/getPoolsEnrichedOld.handler
    description: Lambda for retrieving the latest enriched data for each unique pool (includes old pool values)
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /poolsOld

  getChart:
    handler: src/handlers/getChart.handler
    description: Lambda for retrieving chart data for a particular pool
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /chart/{configID}

  getMedian:
    handler: src/handlers/getMedian.handler
    description: Lambda for retrieving daily median apy's
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /median

  getUrl:
    handler: src/handlers/getUrl.handler
    description: Lambda for retrieving project url's
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /url

  getDistinctID:
    handler: src/handlers/getDistinctID.handler
    description: Lambda for retrieving unique pool id's
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /distinctID

  getLendBorrow:
    handler: src/handlers/getLendBorrow.handler
    description: Lambda for retrieving lending + borrow data
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /lendBorrow

  getHistoryLendBorrow:
    handler: src/handlers/getHistoryLendBorrow.handler
    description: Lambda for retrieving chart data for a particular pool
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /chartLendBorrow/{configID}

  getConfigPool:
    handler: src/handlers/getConfigPool.handler
    description: Lambda for retrieving config data of configIDs
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /configPool/{configID}

  getPerp:
    handler: src/handlers/getPerp.handler
    description: Lambda for retrieving latest perp data
    timeout: 20
    events:
      - httpApi:
          method: get
          path: /perps

  getLSDRates:
    handler: src/handlers/getLSDRates.handler
    description: Lambda for retrieving ETH LSD Rates
    timeout: 30
    events:
      - httpApi:
          method: get
          path: /lsdRates

resources:
  Resources:
    # QUEUES
    # --- queue for adaptor handler
    AdapterQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:service}-${self:custom.stage}-AdapterQueue
        VisibilityTimeout: 660
        # setting this to 9hours
        MessageRetentionPeriod: 32400
        RedrivePolicy:
          deadLetterTargetArn:
            Fn::GetAtt:
              - DeadLetterQueue
              - Arn
          # this params is requried, otherwise cloudformation error
          # means that after 3 failed runs, the message will be moved from the adaptor queue
          # to the DLQ
          maxReceiveCount: 3

    # --- DLQ
    DeadLetterQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:service}-${self:custom.stage}-DeadLetterQueue
        # leaving this at max, 14days, after that msg in there will be deleted
        MessageRetentionPeriod: 1209600

    # --- create bucket
    BucketData:
      Type: AWS::S3::Bucket
      Properties:
        BucketName: ${self:service}-${self:custom.stage}-data

    # --- alarm stuff for DLQ
    DlqAlarm:
      Type: AWS::CloudWatch::Alarm
      Properties:
        AlarmName: ${self:service}-${self:custom.stage}-AdapterDLQ
        AlarmDescription: There are failed messages in the dead letter queue.
        Namespace: AWS/SQS
        MetricName: ApproximateNumberOfMessagesVisible
        Dimensions:
          - Name: QueueName
            Value: !GetAtt DeadLetterQueue.QueueName
        Statistic: Sum
        Period: 60
        EvaluationPeriods: 1
        Threshold: 0
        ComparisonOperator: GreaterThanThreshold
        AlarmActions:
          - !Ref DlqAlarmEmail

    DlqAlarmEmail:
      Type: AWS::SNS::Topic
      Properties:
        Subscription:
          - Endpoint: slasher125@protonmail.com
            Protocol: email

custom:
  stage: ${opt:stage, self:provider.stage}
  webpack:
    webpackConfig: 'webpack.config.js'
    includeModules: true
    packager: 'npm'
    excludeFiles: src/**/*.test.js
  prune:
    automatic: true
    number: 5

plugins:
  - serverless-webpack
  - serverless-prune-plugin
