├── .github
├── checkov.yml
├── cspell.json
├── eslintrc.js
├── exemptions.md
├── gitleaks.toml
├── markdown-link-check.json
├── markdownlint.json
├── proselintrc.json
├── secretlintrc.json
└── workflows
│ ├── mega-linter.yml
│ ├── npm-audit.yml
│ └── npm-test.yml
├── .gitignore
├── 47998e45-a502-4849-8fc2-b70af9681423-megalinter_file_names_cspell.txt
├── 84eef9f1-ed93-4209-9929-cf8d606120eb-megalinter_file_names_cspell.txt
├── README.md
├── asset-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ ├── Comptroller.json
│ └── cErc20.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── test-utils.js
│ └── utils.js
├── comp-delegations-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── Dockerfile
├── README.md
├── abi
│ ├── CompERC20.json
│ └── GovernorBravo.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ └── agent.spec.js
├── ctoken-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ ├── Comptroller.json
│ └── cErc20.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── test-utils.js
│ └── utils.js
├── defender
├── .eslintrc.js
├── .gitignore
├── README.md
├── ctoken_monitor
│ ├── abis
│ │ └── sentinel-1.json.abi
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── datadog_alerts_heat_map
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── datadog_forta_bot_alerts
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── datadog_forta_detection_bot_health
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_ctoken
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_distribution
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_explorer_monitor
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_governance
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_large_borrows_governance
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_large_delegations
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_low_liquidity
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_multi_sig
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_oracle_price
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_underlying_asset
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_v2_liquidation_monitor_dev
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── forta_v3_liquidation_monitor_dev
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── gasless_voting_dev
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── governance_automation
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── governance_discord_alert
│ ├── abis
│ │ └── sentinel-1.json.abi
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── governance_discord_summary
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── governance_twitter_summary
│ ├── autotask-1
│ │ ├── index.js
│ │ └── twitter-api-v2
│ │ │ ├── LICENSE
│ │ │ ├── README.md
│ │ │ ├── changelog.md
│ │ │ ├── lib
│ │ │ ├── client-mixins
│ │ │ │ ├── form-data.helper.d.ts
│ │ │ │ ├── form-data.helper.js
│ │ │ │ ├── oauth1.helper.d.ts
│ │ │ │ ├── oauth1.helper.js
│ │ │ │ ├── oauth2.helper.d.ts
│ │ │ │ ├── oauth2.helper.js
│ │ │ │ ├── request-handler.helper.d.ts
│ │ │ │ ├── request-handler.helper.js
│ │ │ │ ├── request-maker.mixin.d.ts
│ │ │ │ ├── request-maker.mixin.js
│ │ │ │ ├── request-param.helper.d.ts
│ │ │ │ └── request-param.helper.js
│ │ │ ├── client.base.d.ts
│ │ │ ├── client.base.js
│ │ │ ├── client.subclient.d.ts
│ │ │ ├── client.subclient.js
│ │ │ ├── client
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── readonly.d.ts
│ │ │ │ ├── readonly.js
│ │ │ │ ├── readwrite.d.ts
│ │ │ │ └── readwrite.js
│ │ │ ├── globals.d.ts
│ │ │ ├── globals.js
│ │ │ ├── helpers.d.ts
│ │ │ ├── helpers.js
│ │ │ ├── index.d.ts
│ │ │ ├── index.js
│ │ │ ├── paginators
│ │ │ │ ├── TwitterPaginator.d.ts
│ │ │ │ ├── TwitterPaginator.js
│ │ │ │ ├── dm.paginator.v1.d.ts
│ │ │ │ ├── dm.paginator.v1.js
│ │ │ │ ├── followers.paginator.v1.d.ts
│ │ │ │ ├── followers.paginator.v1.js
│ │ │ │ ├── friends.paginator.v1.d.ts
│ │ │ │ ├── friends.paginator.v1.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── list.paginator.v1.d.ts
│ │ │ │ ├── list.paginator.v1.js
│ │ │ │ ├── list.paginator.v2.d.ts
│ │ │ │ ├── list.paginator.v2.js
│ │ │ │ ├── mutes.paginator.v1.d.ts
│ │ │ │ ├── mutes.paginator.v1.js
│ │ │ │ ├── paginator.v1.d.ts
│ │ │ │ ├── paginator.v1.js
│ │ │ │ ├── tweet.paginator.v1.d.ts
│ │ │ │ ├── tweet.paginator.v1.js
│ │ │ │ ├── tweet.paginator.v2.d.ts
│ │ │ │ ├── tweet.paginator.v2.js
│ │ │ │ ├── user.paginator.v1.d.ts
│ │ │ │ ├── user.paginator.v1.js
│ │ │ │ ├── user.paginator.v2.d.ts
│ │ │ │ ├── user.paginator.v2.js
│ │ │ │ ├── v2.paginator.d.ts
│ │ │ │ └── v2.paginator.js
│ │ │ ├── plugins
│ │ │ │ ├── helpers.d.ts
│ │ │ │ └── helpers.js
│ │ │ ├── settings.d.ts
│ │ │ ├── settings.js
│ │ │ ├── stream
│ │ │ │ ├── TweetStream.d.ts
│ │ │ │ ├── TweetStream.js
│ │ │ │ ├── TweetStreamEventCombiner.d.ts
│ │ │ │ ├── TweetStreamEventCombiner.js
│ │ │ │ ├── TweetStreamParser.d.ts
│ │ │ │ └── TweetStreamParser.js
│ │ │ ├── test
│ │ │ │ ├── utils.d.ts
│ │ │ │ └── utils.js
│ │ │ ├── types
│ │ │ │ ├── auth.types.d.ts
│ │ │ │ ├── auth.types.js
│ │ │ │ ├── client.types.d.ts
│ │ │ │ ├── client.types.js
│ │ │ │ ├── entities.types.d.ts
│ │ │ │ ├── entities.types.js
│ │ │ │ ├── errors.types.d.ts
│ │ │ │ ├── errors.types.js
│ │ │ │ ├── index.d.ts
│ │ │ │ ├── index.js
│ │ │ │ ├── plugins
│ │ │ │ │ ├── client.plugins.types.d.ts
│ │ │ │ │ ├── client.plugins.types.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ └── index.js
│ │ │ │ ├── request-maker.mixin.types.d.ts
│ │ │ │ ├── request-maker.mixin.types.js
│ │ │ │ ├── responses.types.d.ts
│ │ │ │ ├── responses.types.js
│ │ │ │ ├── shared.types.d.ts
│ │ │ │ ├── shared.types.js
│ │ │ │ ├── v1
│ │ │ │ │ ├── dev-utilities.v1.types.d.ts
│ │ │ │ │ ├── dev-utilities.v1.types.js
│ │ │ │ │ ├── dm.v1.types.d.ts
│ │ │ │ │ ├── dm.v1.types.js
│ │ │ │ │ ├── entities.v1.types.d.ts
│ │ │ │ │ ├── entities.v1.types.js
│ │ │ │ │ ├── geo.v1.types.d.ts
│ │ │ │ │ ├── geo.v1.types.js
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── list.v1.types.d.ts
│ │ │ │ │ ├── list.v1.types.js
│ │ │ │ │ ├── streaming.v1.types.d.ts
│ │ │ │ │ ├── streaming.v1.types.js
│ │ │ │ │ ├── trends.v1.types.d.ts
│ │ │ │ │ ├── trends.v1.types.js
│ │ │ │ │ ├── tweet.v1.types.d.ts
│ │ │ │ │ ├── tweet.v1.types.js
│ │ │ │ │ ├── user.v1.types.d.ts
│ │ │ │ │ └── user.v1.types.js
│ │ │ │ └── v2
│ │ │ │ │ ├── index.d.ts
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── list.v2.types.d.ts
│ │ │ │ │ ├── list.v2.types.js
│ │ │ │ │ ├── shared.v2.types.d.ts
│ │ │ │ │ ├── shared.v2.types.js
│ │ │ │ │ ├── spaces.v2.types.d.ts
│ │ │ │ │ ├── spaces.v2.types.js
│ │ │ │ │ ├── streaming.v2.types.d.ts
│ │ │ │ │ ├── streaming.v2.types.js
│ │ │ │ │ ├── tweet.definition.v2.d.ts
│ │ │ │ │ ├── tweet.definition.v2.js
│ │ │ │ │ ├── tweet.v2.types.d.ts
│ │ │ │ │ ├── tweet.v2.types.js
│ │ │ │ │ ├── user.v2.types.d.ts
│ │ │ │ │ └── user.v2.types.js
│ │ │ ├── v1
│ │ │ │ ├── client.v1.d.ts
│ │ │ │ ├── client.v1.js
│ │ │ │ ├── client.v1.read.d.ts
│ │ │ │ ├── client.v1.read.js
│ │ │ │ ├── client.v1.write.d.ts
│ │ │ │ ├── client.v1.write.js
│ │ │ │ ├── media-helpers.v1.d.ts
│ │ │ │ └── media-helpers.v1.js
│ │ │ ├── v2-labs
│ │ │ │ ├── client.v2.labs.d.ts
│ │ │ │ ├── client.v2.labs.js
│ │ │ │ ├── client.v2.labs.read.d.ts
│ │ │ │ ├── client.v2.labs.read.js
│ │ │ │ ├── client.v2.labs.write.d.ts
│ │ │ │ └── client.v2.labs.write.js
│ │ │ └── v2
│ │ │ │ ├── client.v2.d.ts
│ │ │ │ ├── client.v2.js
│ │ │ │ ├── client.v2.read.d.ts
│ │ │ │ ├── client.v2.read.js
│ │ │ │ ├── client.v2.write.d.ts
│ │ │ │ ├── client.v2.write.js
│ │ │ │ ├── includes.v2.helper.d.ts
│ │ │ │ └── includes.v2.helper.js
│ │ │ ├── package-lock.json
│ │ │ └── package.json
│ └── serverless.yml
├── package-lock.json
├── package.json
├── proposal_110_automatoooor
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── proposal_117_monitor_market_entered
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── proposal_117_monitor_mint
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── secret-example.yml
├── template_autotask_relay
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── template_autotask_relay_forta
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── template_autotask_relay_sentinel
│ ├── abis
│ │ └── sentinel-1.json.abi
│ ├── autotask-1
│ │ └── index.js
│ └── serverless.yml
├── tests
│ ├── datadog_alerts_heat_map.spec.js
│ ├── datadog_forta_bot_alerts.spec.js
│ ├── datadog_forta_detection_bot_health.spec.js
│ ├── forta_ctoken.spec.js
│ ├── forta_distribution.spec.js
│ ├── forta_explorer_monitor.spec.js
│ ├── forta_governance.spec.js
│ ├── forta_large_borrows_governance.spec.js
│ ├── forta_large_delegations.spec.js
│ ├── forta_low_liquidity.spec.js
│ ├── forta_multi_sig.spec.js
│ ├── forta_oracle_price.spec.js
│ ├── forta_underlying_asset.spec.js
│ ├── forta_v2_liquidation_monitor_dev.spec.js
│ ├── forta_v3_liquidation_monitor_dev.spec.js
│ ├── gasless_voting_dev.spec.js
│ ├── governance_automation.spec.js
│ ├── governance_discord_alert.spec.js
│ ├── governance_discord_summary.spec.js
│ ├── governance_twitter_summary.spec.js
│ └── onChainResources
│ │ └── DummyGovernor.sol
└── yarn.lock
├── distribution
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ └── Comptroller.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── test-utils.js
│ └── utils.js
├── gnosis-safe-deploy
├── .eslintrc.js
├── .gitignore
├── Dockerfile
├── README.md
├── abi
│ ├── .gitkeep
│ ├── AgentRegistry.json
│ └── AgentRegistryProxy.json
├── bot-config.json
├── config.json.example
├── package-lock.json
├── package.json
├── scripts
│ ├── approveTransaction.js
│ ├── deploySafe.js
│ ├── executeTransaction.js
│ ├── proposeFortaBot.js
│ └── rejectTransaction.js
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── test-utils.js
│ ├── utils.js
│ └── utils.spec.js
├── governance
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ ├── .gitkeep
│ └── GovernorBravo.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── delegatesList.json
│ ├── governance.js
│ └── test-utils.js
├── large-borrows-governance
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ ├── CErc20.json
│ ├── CompERC20.json
│ └── GovernorBravo.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ └── agent.spec.js
├── liquidation-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── Dockerfile
├── README.md
├── abi
│ ├── Comptroller.json
│ ├── OneInch.json
│ └── cErc20.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ └── utils.js
├── low-liquidity-market-attack-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ ├── Comptroller.json
│ └── cErc20.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ ├── test-utils.js
│ └── utils.js
├── multisig-transactions-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── Dockerfile
├── README.md
├── abi
│ ├── Comet.json
│ ├── Comptroller.json
│ ├── GnosisSafe.json
│ └── GovernorBravo.json
├── bot-config.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ ├── agent.spec.js
│ └── utils.js
├── oracle-price-monitor
├── .dockerignore
├── .eslintrc.js
├── .gitignore
├── COPYING
├── Dockerfile
├── LICENSE
├── README.md
├── abi
│ └── UniswapAnchoredView.json
├── package-lock.json
├── package.json
└── src
│ ├── agent.js
│ └── agent.spec.js
├── package-lock.json
└── package.json
/.github/checkov.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # You can see all available properties here: https://github.com/bridgecrewio/checkov#configuration-using-a-config-file
3 | quiet: true
4 | skip-check:
5 | - CKV_DOCKER_2
6 | # Default forta bot triggers Docker3 error
7 | # ref: https://docs.bridgecrew.io/docs/ensure-that-a-user-for-the-container-has-been-created
8 | - CKV_DOCKER_3
9 | # GHA7 errors on custom Action triggers that we have in our repo.
10 | - CKV_GHA_7
11 |
--------------------------------------------------------------------------------
/.github/cspell.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignorePaths": [
3 | "**/node_modules/**",
4 | "**/.git/**",
5 | "**/.github/**",
6 | "package-lock.json",
7 | "megalinter-reports/**",
8 | "cspell.json",
9 | "megalinter_file_names_spell.txt",
10 | "**/delegatesList.json"
11 |
12 | ],
13 | "language": "en",
14 | "noConfigSearch": true,
15 | "words": [
16 | "aave",
17 | "addressofdeployedgnosissafe",
18 | "automatoooor",
19 | "autotask",
20 | "autotasks",
21 | "bignumber",
22 | "bulker",
23 | "calldatas",
24 | "cbtc",
25 | "ceth",
26 | "codespell",
27 | "collateralized",
28 | "configurator",
29 | "creds",
30 | "ctoken",
31 | "ctokenaddress",
32 | "datas",
33 | "firstaddress",
34 | "forta",
35 | "ierc",
36 | "jszip",
37 | "keyfile",
38 | "kvstore",
39 | "lastaddress",
40 | "liquidatable",
41 | "mult",
42 | "multicall",
43 | "newstake",
44 | "newtest",
45 | "nodebuffer",
46 | "offchain",
47 | "plusplus",
48 | "privatekeyforgnosissafeowner",
49 | "privatekeyforpolygonaccounttodeploysafe",
50 | "proposedtransactionhash",
51 | "proxiable",
52 | "pyspelling",
53 | "reporteraddress",
54 | "secondaddress",
55 | "ssot",
56 | "stablecoins",
57 | "stefanzweifel",
58 | "timelock",
59 | "twap",
60 | "typehash",
61 | "typoci",
62 | "underlyingtokenaddress",
63 | "unitroller",
64 | "unobfuscated",
65 | "usdp",
66 | "volatilities",
67 | "zipfile"
68 | ],
69 | "version": "0.2"
70 | }
71 |
--------------------------------------------------------------------------------
/.github/eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 'latest',
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-plusplus': 'off',
21 | 'no-console': 'off',
22 | // When linting from the root directory, eslint doesn't check sub-directory modules
23 | // so this gives many false positives.
24 | 'import/no-unresolved': 'off',
25 | },
26 | },
27 | ],
28 | };
29 |
--------------------------------------------------------------------------------
/.github/exemptions.md:
--------------------------------------------------------------------------------
1 | # Reasons for ignoring certain checks
2 |
3 | ## Megalinter Disabled Linters
4 |
5 | - jscpy - CopyPaste scanning is disabled
6 | - JAVASCRIPT_STANDARD - We use eslint instead
7 | - REPOSITORY_TRIVY - Deufault Forta bot causes docker warnings. Trivy is unable to disable checks:
8 |
9 | ## Specific linter exemptions
10 |
11 | - cspell - "ignoreRegExpList": "/[0-9a-f]{8}.js/gi" - scripts/download.js will save files with this name
12 | - cspell - "ignoreRegExpList": "/[0-9a-f]{8}\\\_ABI.json/gi" - scripts/download.js will save files with this name
13 | - cspell - "ignoreRegExpList": "/0x[0-9a-f]{40}/gi" - ignore ETH addresses
14 | - cspell - "ignoreRegExpList": "/Qm[0-9a-zA-Z]{44}/g" - ignore IPFS CIDv0 addresses
15 | - cspell - "ignoreRegExpList": "/bafy[0-9a-zA-Z]{40}[0-9a-zA-Z]+/g" - ignore a subset of IPFS CIDv1 addresses
16 |
17 | - cspell - "words" - various industry words
18 |
19 | - markdownlint - "MD041" - Ignoring first-line-h1 First line in a file should be a top-level heading
20 |
21 | - markdown-link-check - "^" - False positives in autotasks/nft-minter-user-signed/README.md
22 |
23 | - proselint - typography.symbols
24 |
25 | - '...' is an approximation, use the ellipsis symbol '…'.
26 | - Use the multiplication symbol ×, not the letter x. (false positives on ETH addresses)
27 | - Use curly quotes “”, not straight quotes "".
28 |
29 | - gitleaks - '(.\*?)spec\.js$' - ignore our tests, which may have mocked keys and addresses
30 | - gitleaks - '(.\*?)defender-config\.json$' - ignore our defender-config, which may have UIDs
31 |
32 | - secretlint --secretlintignores "**/megalinter-reports/**" - ignore output folder
33 |
34 | - checkov - CKV_DOCKER_3 - Default forta bot triggers Docker3 error
35 |
--------------------------------------------------------------------------------
/.github/gitleaks.toml:
--------------------------------------------------------------------------------
1 |
2 | title = "gitleaks config"
3 |
4 | [extend]
5 | # useDefault will extend the base configuration with the default gitleaks config:
6 | # https://github.com/zricethezav/gitleaks/blob/master/config/gitleaks.toml
7 | useDefault = true
8 |
9 | [allowlist]
10 | description = "Allowlisted files"
11 | paths = [
12 | '''.automation/test''',
13 | '''megalinter-reports''',
14 | '''.github/linters''',
15 | '''node_modules''',
16 | '''.mypy_cache''',
17 | '''(.*?)gitleaks\.toml$''',
18 | '''(.*?)\.(png|jpg|gif|doc|docx|pdf|bin|xls|pyc|zip)$''',
19 | '''(go.mod|go.sum)$''',
20 | '''(.*?)\.spec\.js$''',
21 | ]
22 | regexes = [
23 | '''0x[0-9a-fA-F]{40}''',
24 | ]
25 |
--------------------------------------------------------------------------------
/.github/markdown-link-check.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignorePatterns": [
3 | {
4 | "pattern": "^https://reqbin.com/req/"
5 | },
6 | {
7 | "pattern": "^https://explorer-api.forta.network/graphql"
8 | }
9 | ],
10 | "retryOn429": true,
11 | "retryCount": 5,
12 | "aliveStatusCodes": [200, 203]
13 | }
14 |
--------------------------------------------------------------------------------
/.github/markdownlint.json:
--------------------------------------------------------------------------------
1 | {
2 | "MD004": false,
3 | "MD007": {
4 | "indent": 2
5 | },
6 | "MD013": {
7 | "line_length": 400
8 | },
9 | "MD026": {
10 | "punctuation": ".,;:!。,;:"
11 | },
12 | "MD029": false,
13 | "MD033": false,
14 | "MD036": false,
15 | "MD041": false,
16 | "blank_lines": false
17 | }
18 |
--------------------------------------------------------------------------------
/.github/proselintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "checks": {
3 | "typography.symbols": false
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/.github/secretlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "rules": [
3 | {
4 | "id": "@secretlint/secretlint-rule-preset-recommend"
5 | }
6 | ]
7 | }
8 |
--------------------------------------------------------------------------------
/.github/workflows/npm-audit.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Custom workflow for running NPM audit
3 | name: NPM Vulnerability Checker
4 | # yamllint disable-line rule:truthy
5 | on:
6 | # Enabling manual test
7 | # REF: https://stackoverflow.com/questions/58933155/manual-workflow-triggers-in-github-actions
8 | workflow_dispatch:
9 | pull_request:
10 | branches: [master, main]
11 | types: [opened, reopened]
12 | schedule:
13 | - cron: "0 0 * * 0" # Hours, minutes, day of month, month, day of week. Set for weekly
14 | permissions: read-all
15 |
16 | jobs:
17 | npm-audit:
18 | runs-on: ubuntu-latest
19 | timeout-minutes: 5
20 |
21 | steps:
22 | - name: Checkout the repo
23 | uses: actions/checkout@v3
24 |
25 | - name: Use Node.js
26 | uses: actions/setup-node@v3
27 | with:
28 | node-version: lts/*
29 |
30 | # Looks for package.json in all sub-folders lists all outdated packages for refernce. Ignores error codes.
31 | - name: List outdated packages
32 | continue-on-error: true
33 | # Single command, all newlines are interpreted as a space
34 | run: >
35 | find .
36 | ! -path "*/node_modules/*"
37 | ! -path "*/additional_path/*"
38 | -name "package.json"
39 | -execdir pwd \;
40 | -execdir npm ci \;
41 | -execdir npm outdated \;
42 |
43 | # Looks for package.json in all sub-folders and looks for vulnerable packages. Fails on vulnerable packages.
44 | - name: Check for vulnerabilities
45 | if: always()
46 | # Single command, all newlines are interpreted as a space
47 | run: >
48 | find . !
49 | -path "*/node_modules/*"
50 | ! -path "*/additional_path/*"
51 | -name "package.json"
52 | -execdir pwd \;
53 | -execdir npm audit {} +
54 |
--------------------------------------------------------------------------------
/.github/workflows/npm-test.yml:
--------------------------------------------------------------------------------
1 | ---
2 | # Custom workflow for running NPM test
3 | name: NPM Test
4 | # yamllint disable-line rule:truthy
5 | on:
6 | workflow_dispatch:
7 | pull_request:
8 | branches: [master, main]
9 | types: [opened, reopened, labeled]
10 | push:
11 | branches:
12 | - main
13 | permissions: read-all
14 |
15 | jobs:
16 | npm-test:
17 | runs-on: ubuntu-latest
18 | timeout-minutes: 5
19 |
20 | steps:
21 | - name: Checkout the repo
22 | uses: actions/checkout@v3
23 | - name: Use Node.js
24 | uses: actions/setup-node@v3
25 | with:
26 | node-version: lts/*
27 | # Looks for package.json in all sub-folders and runs all tests.
28 | - name: Run NPM test
29 | continue-on-error: true
30 | # Single command, all newlines are interpreted as a space
31 | run: >
32 | find .
33 | ! -path "*/node_modules/*"
34 | ! -path "*/additional_path/*"
35 | -name "package.json"
36 | -execdir echo "::group::Click to expand test results" \;
37 | -execdir npm ci \;
38 | -execdir npm test \;
39 | -execdir echo "::endgroup::" \;
40 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .vscode
3 | .env
4 | forta.config.json
5 | node_modules
6 | dist
7 | publish.log
8 | megalinter-reports/
9 |
--------------------------------------------------------------------------------
/asset-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/asset-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/asset-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/asset-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
--------------------------------------------------------------------------------
/asset-monitor/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Protocol Monitoring
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
--------------------------------------------------------------------------------
/asset-monitor/README.md:
--------------------------------------------------------------------------------
1 | # Compound cToken Underlying Asset Monitor
2 |
3 | ## Description
4 |
5 | This bot monitors the underlying asset of Compound Finance cToken contracts. First
6 | it determines which assets are deployed using upgradable proxy contracts and then it
7 | monitors those contracts for any upgrade events to detect when the implementation for
8 | a cToken's underlying asset may have changed.
9 |
10 | ## Alerts
11 |
12 |
13 | - AE-COMP-CTOKEN-ASSET-UPGRADED
14 | - Emitted for any proxy pattern specified in `bot-config.json`
15 | - Type is set to the pattern specific value in `bot-config.json`
16 | - Severity is set to the pattern specific value in `bot-config.json`
17 | - Metadata field contains:
18 | - cToken symbol
19 | - cToken address
20 | - underlyingAssetAddress
21 | - Arguments passed with event (e.g. for new implementation address)
22 |
23 | ## Testing
24 |
25 | - AAVE - 0xb505725d0d622207af8ad6bfbd2f9a5031795fe62de9163d54173fbfbbe655e4
26 | - TUSD - 0x125823f2914e4f14e06b9b1b30fe9dd9512b36354cc1f6c063118c4fe03d8287
27 | - USDP - 0xeea8b8f0f0b7125bda2f78ee2f62eb031418be78e09a2fae892eb58f13837ceb
28 | - USDC - 0xe2e40640ffd5f76538cd23660cf56f00bfebd5fe925ebad6b8067c4cee18a2c3
--------------------------------------------------------------------------------
/asset-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "contracts": {
6 | "Comptroller": {
7 | "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
8 | "abiFile": "Comptroller.json"
9 | },
10 | "cTokens": {
11 | "abiFile": "cErc20.json"
12 | }
13 | },
14 | "excludeAddresses": ["0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5"],
15 | "proxyPatterns": [
16 | {
17 | "name": "OwnedUpgradeabilityProxy",
18 | "findingType": "Suspicious",
19 | "findingSeverity": "High",
20 | "functionSignatures": [
21 | "implementation()",
22 | "upgradeTo(address)",
23 | "transferProxyOwnership(address)"
24 | ],
25 | "eventSignatures": ["event Upgraded(address indexed implementation)"]
26 | },
27 | {
28 | "name": "OZ_TransparentUpgradableProxy",
29 | "findingType": "Suspicious",
30 | "findingSeverity": "High",
31 | "functionSignatures": [
32 | "implementation()",
33 | "upgradeTo(address)",
34 | "upgradeToAndCall(address,bytes)"
35 | ],
36 | "eventSignatures": [
37 | "event Upgraded(address indexed implementation)",
38 | "event Upgraded(address implementation)"
39 | ]
40 | },
41 | {
42 | "name": "OZ_UpgradeableUsingUnstructuredStorageProxy",
43 | "findingType": "Suspicious",
44 | "findingSeverity": "High",
45 | "functionSignatures": [
46 | "implementation()",
47 | "upgradeTo(address)",
48 | "proxiableUUID()"
49 | ],
50 | "eventSignatures": ["event Upgraded(address indexed implementation)"]
51 | },
52 | {
53 | "name": "OZ_UpgradeableUsingInternalStorageProxy",
54 | "findingType": "Suspicious",
55 | "findingSeverity": "High",
56 | "functionSignatures": [
57 | "implementation()",
58 | "UpgradeabilityProxy(string)",
59 | "upgradeTo(string)"
60 | ],
61 | "eventSignatures": ["event Upgraded(address indexed implementation)"]
62 | }
63 | ]
64 | }
65 |
--------------------------------------------------------------------------------
/asset-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-asset-monitor",
3 | "version": "0.0.4",
4 | "description": "This bot monitors the underlying asset of a Compound Finance cToken.",
5 | "scripts": {
6 | "start": "npm run start:dev",
7 | "start:prod": "forta-agent run --prod",
8 | "tx": "forta-agent run --tx",
9 | "block": "forta-agent run --block",
10 | "range": "forta-agent run --range",
11 | "file": "forta-agent run --file",
12 | "publish": "forta-agent publish",
13 | "push": "forta-agent push",
14 | "disable": "forta-agent disable",
15 | "enable": "forta-agent enable",
16 | "keyfile": "forta-agent keyfile",
17 | "test": "jest"
18 | },
19 | "dependencies": {
20 | "forta-agent": "0.0.39",
21 | "web3-eth": "1.7.1"
22 | },
23 | "devDependencies": {
24 | "eslint": "8.16.0",
25 | "eslint-config-airbnb-base": "15.0.0",
26 | "eslint-plugin-import": "2.26.0",
27 | "jest": "28.1.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/asset-monitor/src/utils.js:
--------------------------------------------------------------------------------
1 | function getAbi(abiName) {
2 | // eslint-disable-next-line global-require,import/no-dynamic-require
3 | const { abi } = require(`../abi/${abiName}`);
4 | return abi;
5 | }
6 |
7 | module.exports = {
8 | getAbi,
9 | };
10 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./abi ./abi
17 | COPY ./src ./src
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/README.md:
--------------------------------------------------------------------------------
1 | # Compound Delegate Votes Governance Bot
2 |
3 | ## Description
4 |
5 | This bot monitors all DelegateVotesChanged events emitted by the COMP token contract to see if an address has been delegated enough COMP to pass significant governance thresholds.
6 |
7 | ## Alerts
8 |
9 | - AE-COMP-GOVERNANCE-DELEGATE-THRESHOLD
10 | - Fired when a delegate's balance is the minimum governance threshold level for `proposal` or `votingQuorum`
11 | - Type is always set to `Suspicious`
12 | - Severity is set to `Medium` for the proposal threshold alert and `High` for the voting quorum threshold alert
13 | - Metadata field contains:
14 | - Delegate Address
15 | - Governance threshold level that has been surpassed, which can be either `proposal` or `votingQuorum`
16 | - The minimum amount of COMP needed to pass the respective governance threshold
17 | - The amount of COMP owned by the delegate address
--------------------------------------------------------------------------------
/comp-delegations-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "compERC20": {
6 | "address": "0xc00e94Cb662C3520282E6f5717214004A7f26888",
7 | "abi": "CompERC20.json"
8 | },
9 | "governorBravo": {
10 | "address": "0xc0Da02939E1441F497fd74F78cE7Decb17B66529",
11 | "abi": "GovernorBravo.json"
12 | },
13 | "delegateLevels": {
14 | "proposal": {
15 | "type": "Suspicious",
16 | "severity": "Medium"
17 | },
18 | "votingQuorum": {
19 | "type": "Suspicious",
20 | "severity": "High"
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/comp-delegations-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-delegations-monitor",
3 | "version": "0.0.2",
4 | "description": "Forta Bot to monitor delegate voting power",
5 | "chainIds": [
6 | 1
7 | ],
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "publish": "forta-agent publish",
16 | "push": "forta-agent push",
17 | "disable": "forta-agent disable",
18 | "enable": "forta-agent enable",
19 | "keyfile": "forta-agent keyfile",
20 | "test": "jest"
21 | },
22 | "dependencies": {
23 | "bignumber.js": "9.0.2",
24 | "forta-agent": "0.1.3"
25 | },
26 | "devDependencies": {
27 | "eslint": "8.16.0",
28 | "eslint-config-airbnb-base": "15.0.0",
29 | "eslint-plugin-import": "2.26.0",
30 | "jest": "28.1.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/ctoken-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/ctoken-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/ctoken-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/ctoken-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/ctoken-monitor/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Protocol Monitoring
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/ctoken-monitor/README.md:
--------------------------------------------------------------------------------
1 | # Compound cToken Event Monitor
2 |
3 | ## Description
4 |
5 | This bot monitors Compound Finance cToken contracts for common market events like Mint, Borrow,
6 | etc. Monitored events are specified in the bot-config.json file, with associated Finding types
7 | and severities for each one.
8 |
9 | This bot also checks the Compound Finance Comptroller contract on every block to compare the most
10 | recent Array of cToken addresses against the previously stored Array. If any new cTokens were
11 | added, the new cToken address(es) are placed into the Array for monitoring in that block and all
12 | subsequent blocks.
13 |
14 | ## Alerts
15 |
16 |
17 | - AE-COMP-CTOKEN-EVENT
18 | - Emitted for any event specified in `bot-config.json`
19 | - Type is set to event specific value in `bot-config.json`
20 | - Severity is set to event specific value in `bot-config.json`
21 | - Metadata field contains:
22 | - cToken symbol
23 | - cToken address
24 | - Event name
25 | - Arguments passed with event (e.g. for Borrow event, includes borrower address, borrowAmount, accountBorrows, and totalBorrows)
26 |
27 | ## Testing
28 |
29 | Borrow (ETH) - 0xcf8a30b55567c988259b08fb219d10bedc3376f612f12d536a045186a566c99c
30 | Liquidate (DAI) - 0x4316c6cb73296b6b5b603a80a267b203d394e049216d71d8e3ff4822e8d7658f
31 | Mint (USDC) - 0xfd200d6d3136ce4f4b91270f8ed7579bf9932e1ce2388b324ee4a281f58047b1
32 | Redeem (ETH) - 0x4b11cee2963cbb2c01cf2c9858a684117ef24ce62a4ffac5738557e14f0276b6
33 | Repay (USDC) - 0x3c59e9ba77e3864f2efdc49df1c9aba83fb202c59ffbbe116c133dbeb327b010
--------------------------------------------------------------------------------
/ctoken-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "contracts": {
6 | "Comptroller": {
7 | "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
8 | "abiFile": "Comptroller.json",
9 | "events": {}
10 | },
11 | "cTokens": {
12 | "abiFile": "cErc20.json",
13 | "events": {
14 | "Borrow": {
15 | "type": "Info",
16 | "severity": "Info",
17 | "amountKey": "borrowAmount"
18 | },
19 | "LiquidateBorrow": {
20 | "type": "Info",
21 | "severity": "Info",
22 | "amountKey": "repayAmount"
23 | },
24 | "Mint": {
25 | "type": "Info",
26 | "severity": "Info",
27 | "amountKey": "mintAmount"
28 | },
29 | "Redeem": {
30 | "type": "Info",
31 | "severity": "Info",
32 | "amountKey": "redeemAmount"
33 | },
34 | "RepayBorrow": {
35 | "type": "Info",
36 | "severity": "Info",
37 | "amountKey": "repayAmount"
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/ctoken-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-ctoken-events",
3 | "version": "0.0.5",
4 | "description": "This Bot monitors Compound Finance cToken contract for common market events.",
5 | "scripts": {
6 | "start": "npm run start:dev",
7 | "start:prod": "forta-agent run --prod",
8 | "tx": "forta-agent run --tx",
9 | "block": "forta-agent run --block",
10 | "range": "forta-agent run --range",
11 | "file": "forta-agent run --file",
12 | "publish": "forta-agent publish",
13 | "push": "forta-agent push",
14 | "disable": "forta-agent disable",
15 | "enable": "forta-agent enable",
16 | "keyfile": "forta-agent keyfile",
17 | "test": "jest"
18 | },
19 | "dependencies": {
20 | "axios": "0.27.2",
21 | "bignumber.js": "9.0.2",
22 | "forta-agent": "0.0.39"
23 | },
24 | "devDependencies": {
25 | "eslint": "8.16.0",
26 | "eslint-config-airbnb-base": "15.0.0",
27 | "eslint-plugin-import": "2.26.0",
28 | "jest": "28.1.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/ctoken-monitor/src/utils.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('forta-agent');
2 |
3 | function getAbi(abiName) {
4 | // eslint-disable-next-line global-require,import/no-dynamic-require
5 | const { abi } = require(`../abi/${abiName}`);
6 | return abi;
7 | }
8 |
9 | // helper function that identifies key strings in the args array obtained from log parsing
10 | // these key-value pairs will be added to the metadata as event args
11 | // all values are converted to strings so that BigNumbers are readable
12 | function extractEventArgs(args) {
13 | const eventArgs = {};
14 | Object.keys(args).forEach((key) => {
15 | if (Number.isNaN(Number(key))) {
16 | eventArgs[key] = args[key].toString();
17 | }
18 | });
19 | return eventArgs;
20 | }
21 |
22 | function isAddress(valueString) {
23 | return ethers.utils.isHexString(valueString, 20);
24 | }
25 |
26 | module.exports = {
27 | getAbi,
28 | extractEventArgs,
29 | isAddress,
30 | };
31 |
--------------------------------------------------------------------------------
/defender/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 'latest',
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-plusplus': 'off',
21 | 'no-console': 'off',
22 | },
23 | },
24 | ],
25 | };
26 |
--------------------------------------------------------------------------------
/defender/.gitignore:
--------------------------------------------------------------------------------
1 | .env
2 | node_modules
3 |
4 | # Temp
5 | demo*.js
6 | config.js
7 |
8 | # Serverless directories
9 | .serverless
10 |
11 | # Defender
12 | secrets*.yml
13 | .defender
14 |
--------------------------------------------------------------------------------
/defender/datadog_alerts_heat_map/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: datadog_alerts_heat_map
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Datadog Alerts Heat Map
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Private variables pulled from external secrets.yml file
20 | datadogApiKey: ${self:custom.stackSecrets.datadogApiKey}
21 |
22 | defender:
23 | key: ${self:custom.config.keys.api}
24 | secret: ${self:custom.config.keys.secret}
25 |
26 | functions:
27 | autotask-1:
28 | name: ${self:custom.name} Serverless Autotask
29 | path: autotask-1
30 | trigger:
31 | type: schedule
32 | frequency: 60
33 | paused: false
34 |
35 | resources:
36 | Resources:
37 | policies:
38 | policy-1:
39 | gas-price-cap: 1000
40 | whitelist-receivers:
41 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
42 | eip1559-pricing: true
43 |
44 | secrets:
45 | stack: ${self:custom.defenderSecrets}
46 |
47 | relayers:
48 |
49 | plugins:
50 | - defender-serverless
51 |
--------------------------------------------------------------------------------
/defender/datadog_forta_bot_alerts/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: datadog_forta_bot_alerts
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Datadog Forta Bot Alerts
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Private variables pulled from external secrets.yml file
20 | datadogApiKey: ${self:custom.stackSecrets.datadogApiKey}
21 |
22 | defender:
23 | key: ${self:custom.config.keys.api}
24 | secret: ${self:custom.config.keys.secret}
25 |
26 | functions:
27 | autotask-1:
28 | name: ${self:custom.name} Serverless Autotask
29 | path: autotask-1
30 | trigger:
31 | type: schedule
32 | frequency: 60
33 | paused: false
34 |
35 | resources:
36 | Resources:
37 | policies:
38 | policy-1:
39 | gas-price-cap: 1000
40 | whitelist-receivers:
41 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
42 | eip1559-pricing: true
43 |
44 | secrets:
45 | stack: ${self:custom.defenderSecrets}
46 |
47 | relayers:
48 |
49 | plugins:
50 | - defender-serverless
51 |
--------------------------------------------------------------------------------
/defender/datadog_forta_detection_bot_health/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: datadog_forta_detection_bot_health
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Datadog Forta Detection Bot Health
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Private variables pulled from external secrets.yml file
20 | datadogApiKey: ${self:custom.stackSecrets.datadogApiKey}
21 |
22 | defender:
23 | key: ${self:custom.config.keys.api}
24 | secret: ${self:custom.config.keys.secret}
25 |
26 | functions:
27 | autotask-1:
28 | name: ${self:custom.name} Serverless Autotask
29 | path: autotask-1
30 | trigger:
31 | type: schedule
32 | frequency: 60
33 | paused: false
34 |
35 | resources:
36 | Resources:
37 | policies:
38 | policy-1:
39 | gas-price-cap: 1000
40 | whitelist-receivers:
41 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
42 | eip1559-pricing: true
43 |
44 | secrets:
45 | stack: ${self:custom.defenderSecrets}
46 |
47 | relayers:
48 |
49 | plugins:
50 | - defender-serverless
51 |
--------------------------------------------------------------------------------
/defender/forta_ctoken/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_ctoken
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Forta cToken
17 |
18 | # Forta Sentinel Settings
19 | alert-ids:
20 | - AE-COMP-CTOKEN-EVENT
21 | agent-ids:
22 | - "0xab39733ddf86340b8e7940ebb933bb48506a341485c7f8c77da17bc1400fe028"
23 |
24 | # Comment out any secret that you do not want to be overwritten in Defender
25 | defenderSecrets:
26 | # Private variables pulled from external secrets.yml file
27 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
28 |
29 | defender:
30 | key: ${self:custom.config.keys.api}
31 | secret: ${self:custom.config.keys.secret}
32 |
33 | functions:
34 | autotask-1:
35 | name: ${self:custom.name} Serverless Autotask
36 | path: autotask-1
37 | trigger:
38 | type: schedule
39 | frequency: 525600000
40 | paused: false
41 | relayer: ${self:resources.Resources.relayers.relayer-1}
42 |
43 | resources:
44 | Resources:
45 | policies:
46 | policy-1:
47 | gas-price-cap: 1000
48 | whitelist-receivers:
49 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
50 | eip1559-pricing: true
51 |
52 | secrets:
53 | stack: ${self:custom.defenderSecrets}
54 |
55 | relayers:
56 | relayer-1:
57 | name: ${self:custom.name} Serverless Relay
58 | network: mainnet
59 | min-balance: 100000000000000000
60 |
61 | sentinels:
62 | sentinel-1:
63 | name: ${self:custom.name} Serverless Sentinel
64 | type: FORTA
65 | addresses: []
66 | network: mainnet
67 | paused: true
68 | autotask-trigger: ${self:functions.autotask-1}
69 | notify-config:
70 | timeout: 0
71 | channels: []
72 | conditions:
73 | min-scanner-count: 1
74 | severity: 1
75 | alert-ids: ${self:custom.alert-ids}
76 | agent-ids: ${self:custom.agent-ids}
77 |
78 | plugins:
79 | - defender-serverless
80 |
--------------------------------------------------------------------------------
/defender/forta_distribution/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_distribution
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Forta Distribution
17 |
18 | # Forta Sentinel Settings
19 | alert-ids:
20 | - AE-COMP-DISTRIBUTION-EVENT
21 | agent-ids:
22 | - "0x34c27c43e0a45bced8f8a941b3d552f5e6feae62afd7e2e88b5024f7de5a8ba0"
23 |
24 | # Comment out any secret that you do not want to be overwritten in Defender
25 | defenderSecrets:
26 | # Private variables pulled from external secrets.yml file
27 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
28 |
29 | defender:
30 | key: ${self:custom.config.keys.api}
31 | secret: ${self:custom.config.keys.secret}
32 |
33 | functions:
34 | autotask-1:
35 | name: ${self:custom.name} Serverless Autotask
36 | path: autotask-1
37 | trigger:
38 | type: schedule
39 | frequency: 525600000
40 | paused: false
41 |
42 | resources:
43 | Resources:
44 | policies:
45 | policy-1:
46 | gas-price-cap: 1000
47 | whitelist-receivers:
48 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
49 | eip1559-pricing: true
50 |
51 | secrets:
52 | stack: ${self:custom.defenderSecrets}
53 |
54 | relayers:
55 |
56 | sentinels:
57 | sentinel-1:
58 | name: ${self:custom.name} Serverless Sentinel
59 | type: FORTA
60 | addresses: []
61 | network: mainnet
62 | paused: true
63 | autotask-trigger: ${self:functions.autotask-1}
64 | notify-config:
65 | timeout: 0
66 | channels: []
67 | conditions:
68 | min-scanner-count: 1
69 | severity: 1
70 | alert-ids: ${self:custom.alert-ids}
71 | agent-ids: ${self:custom.agent-ids}
72 |
73 | plugins:
74 | - defender-serverless
75 |
--------------------------------------------------------------------------------
/defender/forta_explorer_monitor/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_explorer_monitor
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 |
14 | # Configure this section and rename secret-example.yml to secrets.yml
15 | name: Forta Explorer Monitor
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | autotask-1:
23 | name: ${self:custom.name} Serverless Autotask
24 | path: autotask-1
25 | trigger:
26 | type: schedule
27 | cron: "0 * * * *" # Every hour on the hour
28 | paused: false
29 |
30 | resources:
31 | Resources:
32 | policies:
33 | policy-1:
34 | gas-price-cap: 1000
35 | whitelist-receivers:
36 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
37 | eip1559-pricing: true
38 |
39 | secrets:
40 |
41 | relayers:
42 |
43 | plugins:
44 | - defender-serverless
45 |
--------------------------------------------------------------------------------
/defender/forta_large_borrows_governance/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_large_borrows_governance
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
15 | name: Forta Large Borrows Governance
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | autotask-1:
23 | name: ${self:custom.name} Action
24 | path: autotask-1
25 | trigger:
26 | type: schedule
27 | frequency: 0
28 | paused: true
29 |
30 | resources:
31 | Resources:
32 | notifications:
33 | discord:
34 | type: discord
35 | name: ${self:custom.name} Discord
36 | config:
37 | url: ${self:custom.discordWebhook}
38 | paused: false
39 | sentinels:
40 | monitor:
41 | name: ${self:custom.name} Monitor
42 | type: FORTA
43 | network: mainnet
44 | paused: false
45 | autotask-trigger: ${self:functions.autotask-1}
46 | notify-config:
47 | timeout: 0
48 | message: [TX]({{ metadata.transactionLink }}) {{ metadata.message }}
49 | message-subject: Defender Alert: ${self:custom.name}
50 | channels:
51 | - ${self:resources.Resources.notifications.discord}
52 | conditions:
53 | min-scanner-count: 1
54 | severity: 1
55 | alert-ids:
56 | - AE-COMP-GOVERNANCE-THRESHOLD
57 | agent-ids:
58 | - 0xb6bdedbae67cc82e60aad02a8ffab3ccbefeaa876ca7e4f291c07c798a95e339
59 |
60 | plugins:
61 | - defender-serverless
--------------------------------------------------------------------------------
/defender/forta_large_delegations/autotask-1/index.js:
--------------------------------------------------------------------------------
1 | function getUrl(scopedSecrets, source) {
2 | if (!scopedSecrets || !source) return;
3 | const { block, transactionHash } = source;
4 | if (!block || !transactionHash) return;
5 | const { chainId } = block;
6 | if (!chainId) return;
7 | // eslint-disable-next-line dot-notation
8 | let mapping = scopedSecrets['NetworkBlockexplorerMapping'];
9 | if (!mapping) return;
10 | try {
11 | mapping = JSON.parse(mapping);
12 | } catch (e) { return; }
13 | const path = mapping?.[chainId];
14 | if (!path) return;
15 | // eslint-disable-next-line consistent-return
16 | return `${path}${transactionHash}`;
17 | }
18 |
19 | // eslint-disable-next-line func-names
20 | exports.handler = async function (payload) {
21 | const matches = [];
22 | payload.request.body.events?.forEach((event) => {
23 | const { source, metadata, hash } = event.alert;
24 | const transactionLink = getUrl(payload.secrets, source) ?? `https://explorer.forta.network/alert/${hash}`;
25 | if (metadata === undefined) {
26 | throw new Error('metadata undefined');
27 | }
28 |
29 | // Start of usual modifications to the autotask script
30 | // extract the metadata
31 | const {
32 | delegateAddress,
33 | levelName,
34 | } = metadata;
35 | if (delegateAddress === undefined) {
36 | throw new Error('delegateAddress undefined');
37 | }
38 | const delegateFormatted = delegateAddress.slice(0, 6);
39 |
40 | const message = `${transactionLink} 💸 **${delegateFormatted}** has been delegated enough **COMP** tokens to pass min threshold for the governance event: **${levelName}**`;
41 | matches.push({
42 | hash: event.hash,
43 | metadata: { message, transactionLink },
44 | });
45 | });
46 | return { matches };
47 | };
--------------------------------------------------------------------------------
/defender/forta_large_delegations/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: 3
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_large_delegations
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
15 | name: Forta Large Delegations
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | filter:
23 | name: ${self:custom.name} Filter
24 | trigger:
25 | type: schedule
26 | frequency: 0
27 | paused: true
28 | path: autotask-1
29 |
30 | resources:
31 | Resources:
32 | notifications:
33 | discord:
34 | type: discord
35 | name: ${self:custom.name} Discord
36 | config:
37 | url: ${self:custom.discordWebhook}
38 | paused: false
39 | sentinels:
40 | monitor:
41 | name: ${self:custom.name} Monitor
42 | type: FORTA
43 | network: mainnet
44 | paused: false
45 | notify-config:
46 | timeout: 0
47 | message: [TX]({{ metadata.transactionLink }}) {{ metadata.message }}
48 | message-subject: Defender Alert: ${self:custom.name}
49 | channels:
50 | - ${self:resources.Resources.notifications.discord}
51 | autotask-condition: ${self:functions.filter}
52 | conditions:
53 | min-scanner-count: 1
54 | severity: 1
55 | alert-ids:
56 | - AE-COMP-GOVERNANCE-DELEGATE-THRESHOLD
57 | agent-ids:
58 | - 0x0d3cdcc2757cd7837e3b302a9889c854044a80835562dc8060d7c163fbb69d53
59 | plugins:
60 | - defender-serverless
61 |
--------------------------------------------------------------------------------
/defender/forta_low_liquidity/autotask-1/index.js:
--------------------------------------------------------------------------------
1 | function getUrl(scopedSecrets, source) {
2 | if (!scopedSecrets || !source) return;
3 | const { block, transactionHash } = source;
4 | if (!block || !transactionHash) return;
5 | const { chainId } = block;
6 | if (!chainId) return;
7 | let mapping = scopedSecrets['NetworkBlockexplorerMapping'];
8 | if (!mapping) return;
9 | try {
10 | mapping = JSON.parse(mapping);
11 | } catch (e) { return; }
12 | const path = mapping?.[chainId];
13 | if (!path) return;
14 | return `${path}${transactionHash}`;
15 | }
16 | exports.handler = async function (payload) {
17 | const matches = [];
18 | payload.request.body.events?.forEach(event => {
19 | const { alertId, source, metadata, hash } = event.alert;
20 | const transactionLink = getUrl(payload.secrets, source) ?? `https://explorer.forta.network/alert/${hash}`;
21 | if (metadata === undefined) {
22 | throw new Error('metadata undefined');
23 | }
24 | // Start of usual modifications to the autotask script
25 | // extract the metadata
26 | const {
27 | compTokenSymbol,
28 | maliciousAddress,
29 | protocolVersion,
30 | } = metadata;
31 | if (maliciousAddress === undefined) {
32 | throw new Error('maliciousAddress undefined');
33 | }
34 | // Handle older alerts which don't specify the protocol version
35 | let versionString = '';
36 | if (protocolVersion !== undefined) {
37 | versionString = ` (Compound v${protocolVersion})`;
38 | }
39 | const maliciousAddressFormatted = maliciousAddress.slice(0, 6);
40 | const message = `The address ${maliciousAddressFormatted} is potentially manipulating the cToken ${compTokenSymbol} market${versionString}`;
41 | matches.push({
42 | hash: event.hash,
43 | metadata: { message, transactionLink }
44 | });
45 | });
46 | return { matches };
47 | };
--------------------------------------------------------------------------------
/defender/forta_low_liquidity/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_low_liquidity
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
15 | name: Forta Low Liquidity
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | filter:
23 | name: ${self:custom.name} Filter
24 | path: autotask-1
25 | trigger:
26 | type: schedule
27 | frequency: 525600000
28 | paused: false
29 |
30 | resources:
31 | Resources:
32 | notifications:
33 | discord:
34 | type: discord
35 | name: "${self:custom.name} Discord Channel"
36 | config:
37 | url: ${self:custom.discordWebhook}
38 | paused: false
39 | sentinels:
40 | monitor:
41 | name: ${self:custom.name} Monitor
42 | type: FORTA
43 | network: mainnet
44 | paused: false
45 | notify-config:
46 | timeout: 0
47 | message: "[TX]({{ metadata.transactionLink }}) {{ metadata.message }}"
48 | message-subject: Defender Alert: ${self:custom.name}
49 | channels:
50 | - ${self:resources.Resources.notifications.discord}
51 | autotask-condition: ${self:functions.filter}
52 | conditions:
53 | min-scanner-count: 1
54 | severity: 1
55 | alert-ids:
56 | - AE-COMP-MARKET-ATTACK-EVENT
57 | agent-ids:
58 | - 0xe49ab07879658c258d5007ac6b88428a2b88cc5cfef206222ad94690840be87a
59 | plugins:
60 | - defender-serverless
--------------------------------------------------------------------------------
/defender/forta_oracle_price/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_oracle_price
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | name: Forta Oracle Price
14 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
15 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
16 |
17 | agent-ids: "0x32facccd163300ad76c7fe88b559b812dca9050a569417b42fced95594dda08e"
18 |
19 | defender:
20 | key: ${self:custom.config.keys.api}
21 | secret: ${self:custom.config.keys.secret}
22 |
23 | functions:
24 | autotask-1:
25 | name: ${self:custom.name} Filter
26 | path: autotask-1
27 | trigger:
28 | type: schedule
29 | frequency: 0
30 | paused: true
31 |
32 | resources:
33 | Resources:
34 | notifications:
35 | discord:
36 | type: discord
37 | name: "${self:custom.name} Discord Channel"
38 | config:
39 | url: ${self:custom.discordWebhook}
40 | paused: false
41 | sentinels:
42 | forta-oracle-price-sentinel:
43 | name: "${self:custom.name} Sentinel"
44 | type: "FORTA"
45 | network: "mainnet"
46 | addresses: []
47 | paused: false
48 | notify-config:
49 | timeout: 0
50 | message: "[TX]({{ metadata.transactionLink }}) {{ metadata.message }}"
51 | message-subject: "Compound Monitoring: Forta Oracle Price Sentinel triggered"
52 | channels:
53 | - ${self:resources.Resources.notifications.discord}
54 | conditions:
55 | min-scanner-count: 1
56 | severity: 1
57 | autotask-condition: ${self:functions.autotask-1}
58 | agent-ids: ${self:custom.agent-ids}
59 | plugins:
60 | - '@openzeppelin/defender-serverless'
--------------------------------------------------------------------------------
/defender/forta_underlying_asset/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_underlying_asset
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Forta Underlying Asset
17 |
18 | # Forta Sentinel Settings
19 | alert-ids:
20 | - AE-COMP-CTOKEN-ASSET-UPGRADED
21 | agent-ids:
22 | - "0xfa3044aa08927163ff8578fb5c108978dfde3a12e0b21834e53111e2859f3a59"
23 |
24 | # Comment out any secret that you do not want to be overwritten in Defender
25 | defenderSecrets:
26 | # Private variables pulled from external secrets.yml file
27 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
28 |
29 | defender:
30 | key: ${self:custom.config.keys.api}
31 | secret: ${self:custom.config.keys.secret}
32 |
33 | functions:
34 | autotask-1:
35 | name: ${self:custom.name} Serverless Autotask
36 | path: autotask-1
37 | trigger:
38 | type: schedule
39 | frequency: 0
40 | paused: true
41 |
42 | resources:
43 | Resources:
44 | notifications:
45 | discord:
46 | type: discord
47 | name: "${self:custom.name} Security Alerts"
48 | config:
49 | url: ${self:custom.defenderSecrets.discordWebhook}
50 | paused: false
51 | sentinels:
52 | forta-multisig-sentinel:
53 | name: "${self:custom.name} Sentinel"
54 | type: "FORTA"
55 | network: "mainnet"
56 | addresses: []
57 | paused: false
58 | notify-config:
59 | timeout: 0
60 | message: "[TX]({{ metadata.transactionLink }}) {{ metadata.message }}"
61 | message-subject: "Defender Sentinel: ${self:custom.name} triggered"
62 | channels:
63 | - ${self:resources.Resources.notifications.discord}
64 | conditions:
65 | min-scanner-count: 1
66 | severity: 1
67 | autotask-condition: ${self:functions.autotask-1}
68 | agent-ids: ${self:custom.agent-ids}
69 |
70 | plugins:
71 | - defender-serverless
--------------------------------------------------------------------------------
/defender/forta_v2_liquidation_monitor_dev/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_v2_liquidation_monitor_dev
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Forta v2 Liquidation Monitor DEV
17 |
18 | # Forta Sentinel Settings
19 | alert-ids: [] # Accept all alerts
20 | agent-ids:
21 | - "0x3c61101f1d349661298a58ba59a58fbce5a3626c5c7af10b091796969e0d6c59"
22 |
23 | # Comment out any secret that you do not want to be overwritten in Defender
24 | defenderSecrets:
25 | # Private variables pulled from external secrets.yml file
26 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
27 |
28 | defender:
29 | key: ${self:custom.config.keys.api}
30 | secret: ${self:custom.config.keys.secret}
31 |
32 | functions:
33 | autotask-1:
34 | name: ${self:custom.name} Serverless Autotask
35 | path: autotask-1
36 | trigger:
37 | type: schedule
38 | frequency: 525600000
39 | paused: false
40 |
41 | resources:
42 | Resources:
43 | policies:
44 | policy-1:
45 | gas-price-cap: 1000
46 | whitelist-receivers:
47 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
48 | eip1559-pricing: true
49 |
50 | secrets:
51 | stack: ${self:custom.defenderSecrets}
52 |
53 | relayers:
54 |
55 | sentinels:
56 | sentinel-1:
57 | name: ${self:custom.name} Serverless Sentinel
58 | type: FORTA
59 | addresses: []
60 | network: mainnet
61 | paused: false
62 | autotask-trigger: ${self:functions.autotask-1}
63 | notify-config:
64 | timeout: 0
65 | channels: []
66 | conditions:
67 | min-scanner-count: 1
68 | severity: 1
69 | alert-ids: ${self:custom.alert-ids}
70 | agent-ids: ${self:custom.agent-ids}
71 |
72 | plugins:
73 | - defender-serverless
74 |
--------------------------------------------------------------------------------
/defender/forta_v3_liquidation_monitor_dev/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: forta_v3_liquidation_monitor_dev
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Forta v3 Liquidation Monitor DEV
17 |
18 | # Forta Sentinel Settings
19 | alert-ids: [] # Accept all alerts
20 | agent-ids:
21 | - "0x52b24dd829bf3aa7b18a74f23947377af6203f09b6553ef054df7c633f961210"
22 |
23 | # Comment out any secret that you do not want to be overwritten in Defender
24 | defenderSecrets:
25 | # Private variables pulled from external secrets.yml file
26 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
27 |
28 | defender:
29 | key: ${self:custom.config.keys.api}
30 | secret: ${self:custom.config.keys.secret}
31 |
32 | functions:
33 | autotask-1:
34 | name: ${self:custom.name} Serverless Autotask
35 | path: autotask-1
36 | trigger:
37 | type: schedule
38 | frequency: 525600000
39 | paused: false
40 |
41 | resources:
42 | Resources:
43 | policies:
44 | policy-1:
45 | gas-price-cap: 1000
46 | whitelist-receivers:
47 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
48 | eip1559-pricing: true
49 |
50 | secrets:
51 | stack: ${self:custom.defenderSecrets}
52 |
53 | relayers:
54 |
55 | sentinels:
56 | sentinel-1:
57 | name: ${self:custom.name} Serverless Sentinel
58 | type: FORTA
59 | addresses: []
60 | network: mainnet
61 | paused: false
62 | autotask-trigger: ${self:functions.autotask-1}
63 | notify-config:
64 | timeout: 0
65 | channels: []
66 | conditions:
67 | min-scanner-count: 1
68 | severity: 1
69 | alert-ids: ${self:custom.alert-ids}
70 | agent-ids: ${self:custom.agent-ids}
71 |
72 | plugins:
73 | - defender-serverless
74 |
--------------------------------------------------------------------------------
/defender/gasless_voting_dev/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: gasless_voting_dev
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 |
14 | # Configure this section and rename secret-example.yml to secrets.yml
15 | name: Gasless Voting DEV
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | autotask-1:
23 | name: ${self:custom.name} Serverless Autotask
24 | path: autotask-1
25 | trigger:
26 | type: webhook
27 | paused: false
28 | relayer: ${self:resources.Resources.relayers.relayer-1}
29 |
30 | resources:
31 | Resources:
32 | policies:
33 | policy-1:
34 | gas-price-cap: 1000
35 | whitelist-receivers:
36 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
37 | eip1559-pricing: true
38 |
39 | secrets:
40 |
41 | relayers:
42 | relayer-1:
43 | name: ${self:custom.name} Serverless Relay
44 | network: mainnet
45 | min-balance: 100000000000000000
46 |
47 | plugins:
48 | - defender-serverless
49 |
--------------------------------------------------------------------------------
/defender/governance_automation/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: governance_automation
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 |
14 | # Configure this section and rename secret-example.yml to secrets.yml
15 | name: Governance Automation
16 | # Comment out any secret that you do not want to be overwritten in Defender
17 | defenderSecrets:
18 | # Public Variables
19 | # Compound Governance Address
20 | governanceAddress: "0xc0Da02939E1441F497fd74F78cE7Decb17B66529"
21 |
22 | defender:
23 | key: ${self:custom.config.keys.api}
24 | secret: ${self:custom.config.keys.secret}
25 |
26 | functions:
27 | autotask-1:
28 | name: ${self:custom.name} Serverless Autotask
29 | path: autotask-1
30 | trigger:
31 | type: schedule
32 | frequency: 1
33 | paused: false
34 | relayer: ${self:resources.Resources.relayers.relayer-1}
35 |
36 | resources:
37 | Resources:
38 | policies:
39 | policy-1:
40 | gas-price-cap: 1000
41 | whitelist-receivers:
42 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
43 | eip1559-pricing: true
44 |
45 | secrets:
46 | stack: ${self:custom.defenderSecrets}
47 |
48 | relayers:
49 | relayer-1:
50 | name: ${self:custom.name} Serverless Relay
51 | network: mainnet
52 | min-balance: 100000000000000000
53 |
54 | plugins:
55 | - defender-serverless
56 |
--------------------------------------------------------------------------------
/defender/governance_discord_summary/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: governance_discord_summary
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Governance Discord Summary
17 | defenderSecrets:
18 | # Public Variables
19 | # Compound Governance Address
20 | governanceAddress: "0xc0Da02939E1441F497fd74F78cE7Decb17B66529"
21 | # Private variables pulled from external secrets.yml file
22 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
23 |
24 | defender:
25 | key: ${self:custom.config.keys.api}
26 | secret: ${self:custom.config.keys.secret}
27 |
28 | functions:
29 | autotask-1:
30 | name: ${self:custom.name} Serverless Autotask
31 | path: autotask-1
32 | trigger:
33 | type: schedule
34 | frequency: 1440
35 | paused: false
36 | relayer: ${self:resources.Resources.relayers.relayer-1}
37 |
38 | resources:
39 | Resources:
40 | policies:
41 | policy-1:
42 | gas-price-cap: 1000
43 | whitelist-receivers:
44 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
45 | eip1559-pricing: true
46 |
47 | secrets:
48 | stack: ${self:custom.defenderSecrets}
49 |
50 | relayers:
51 | relayer-1:
52 | name: ${self:custom.name} Serverless Relay
53 | network: mainnet
54 | min-balance: 100000000000000000
55 |
56 | plugins:
57 | - defender-serverless
58 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client-mixins/form-data.helper.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | declare type TStringable = {
3 | toString(): string;
4 | };
5 | export declare class FormDataHelper {
6 | protected _boundary: string;
7 | protected _chunks: Buffer[];
8 | protected _footerChunk?: Buffer;
9 | protected static readonly LINE_BREAK = "\r\n";
10 | protected static readonly DEFAULT_CONTENT_TYPE = "application/octet-stream";
11 | protected bodyAppend(...values: (Buffer | string)[]): void;
12 | append(field: string, value: Buffer | string | TStringable, contentType?: string): void;
13 | getHeaders(): {
14 | 'content-type': string;
15 | };
16 | /** Length of form-data (including footer length). */
17 | protected getLength(): number;
18 | getBuffer(): Buffer;
19 | protected getBoundary(): string;
20 | protected generateBoundary(): void;
21 | protected getMultipartHeader(field: string, value: string | Buffer, contentType?: string): string;
22 | protected getMultipartFooter(): Buffer;
23 | }
24 | export {};
25 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client-mixins/oauth1.helper.d.ts:
--------------------------------------------------------------------------------
1 | export interface OAuth1Tokens {
2 | key: string;
3 | secret: string;
4 | }
5 | export interface OAuth1MakerArgs {
6 | consumerKeys: OAuth1Tokens;
7 | }
8 | export interface OAuth1RequestOptions {
9 | url: string;
10 | method: string;
11 | data?: any;
12 | }
13 | export interface OAuth1AuthInfo {
14 | oauth_consumer_key: string;
15 | oauth_nonce: string;
16 | oauth_signature_method: string;
17 | oauth_timestamp: number;
18 | oauth_version: string;
19 | oauth_token: string;
20 | oauth_signature: string;
21 | }
22 | export declare class OAuth1Helper {
23 | nonceLength: number;
24 | protected consumerKeys: OAuth1Tokens;
25 | constructor(options: OAuth1MakerArgs);
26 | static percentEncode(str: string): string;
27 | protected hash(base: string, key: string): string;
28 | authorize(request: OAuth1RequestOptions, accessTokens?: Partial): OAuth1AuthInfo;
29 | toHeader(oauthInfo: OAuth1AuthInfo): {
30 | Authorization: string;
31 | };
32 | protected getNonce(): string;
33 | protected getTimestamp(): number;
34 | protected getSignature(request: OAuth1RequestOptions, tokenSecret: string | undefined, oauthInfo: OAuth1AuthInfo): string;
35 | protected getSigningKey(tokenSecret: string | undefined): string;
36 | protected getBaseString(request: OAuth1RequestOptions, oauthInfo: OAuth1AuthInfo): string;
37 | protected getParameterString(request: OAuth1RequestOptions, oauthInfo: OAuth1AuthInfo): string;
38 | protected getBaseUrl(url: string): string;
39 | }
40 | export default OAuth1Helper;
41 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client-mixins/oauth2.helper.d.ts:
--------------------------------------------------------------------------------
1 | export declare class OAuth2Helper {
2 | static getCodeVerifier(): string;
3 | static getCodeChallengeFromVerifier(verifier: string): string;
4 | static getAuthHeader(clientId: string, clientSecret: string): string;
5 | static generateRandomString(length: number): string;
6 | private static escapeBase64Url;
7 | }
8 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client-mixins/request-param.helper.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { RequestOptions } from 'https';
3 | import type { TBodyMode, TRequestBody, TRequestQuery, TRequestStringQuery } from '../types/request-maker.mixin.types';
4 | export declare class RequestParamHelpers {
5 | static readonly JSON_1_1_ENDPOINTS: Set;
6 | static formatQueryToString(query: TRequestQuery): TRequestStringQuery;
7 | static autoDetectBodyType(url: URL): TBodyMode;
8 | static addQueryParamsToUrl(url: URL, query: TRequestQuery): void;
9 | static constructBodyParams(body: TRequestBody, headers: Record, mode: TBodyMode): string | Buffer;
10 | static setBodyLengthHeader(options: RequestOptions, body: string | Buffer): void;
11 | static isOAuthSerializable(item: any): boolean;
12 | static mergeQueryAndBodyForOAuth(query: TRequestQuery, body: TRequestBody): any;
13 | static moveUrlQueryParamsIntoObject(url: URL, query: TRequestQuery): URL;
14 | /**
15 | * Replace URL parameters available in pathname, like `:id`, with data given in `parameters`:
16 | * `https://twitter.com/:id.json` + `{ id: '20' }` => `https://twitter.com/20.json`
17 | */
18 | static applyRequestParametersToUrl(url: URL, parameters: TRequestQuery): URL;
19 | }
20 | export default RequestParamHelpers;
21 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client.subclient.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiBase from './client.base';
2 | /**
3 | * Base subclient for every v1 and v2 client.
4 | */
5 | export default abstract class TwitterApiSubClient extends TwitterApiBase {
6 | constructor(instance: TwitterApiBase);
7 | }
8 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client.subclient.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const client_base_1 = __importDefault(require("./client.base"));
7 | /**
8 | * Base subclient for every v1 and v2 client.
9 | */
10 | class TwitterApiSubClient extends client_base_1.default {
11 | constructor(instance) {
12 | if (!(instance instanceof client_base_1.default)) {
13 | throw new Error('You must instance SubTwitterApi instance from existing TwitterApi instance.');
14 | }
15 | super(instance);
16 | }
17 | }
18 | exports.default = TwitterApiSubClient;
19 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client/index.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiv1 from '../v1/client.v1';
2 | import TwitterApiv2 from '../v2/client.v2';
3 | import TwitterApiReadWrite from './readwrite';
4 | /**
5 | * Twitter v1.1 and v2 API client.
6 | */
7 | export declare class TwitterApi extends TwitterApiReadWrite {
8 | protected _v1?: TwitterApiv1;
9 | protected _v2?: TwitterApiv2;
10 | get v1(): TwitterApiv1;
11 | get v2(): TwitterApiv2;
12 | /**
13 | * Get a client with read/write rights.
14 | */
15 | get readWrite(): TwitterApiReadWrite;
16 | static getErrors(error: any): (import("../types").ErrorV1 | import("../types").ErrorV2)[];
17 | /** Extract another image size than obtained in a `profile_image_url` or `profile_image_url_https` field of a user object. */
18 | static getProfileImageInSize(profileImageUrl: string, size: 'normal' | 'bigger' | 'mini' | 'original'): string;
19 | }
20 | export { default as TwitterApiReadWrite } from './readwrite';
21 | export { default as TwitterApiReadOnly } from './readonly';
22 | export default TwitterApi;
23 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client/readwrite.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiv1ReadWrite from '../v1/client.v1.write';
2 | import TwitterApiv2ReadWrite from '../v2/client.v2.write';
3 | import TwitterApiReadOnly from './readonly';
4 | /**
5 | * Twitter v1.1 and v2 API client.
6 | */
7 | export default class TwitterApiReadWrite extends TwitterApiReadOnly {
8 | protected _v1?: TwitterApiv1ReadWrite;
9 | protected _v2?: TwitterApiv2ReadWrite;
10 | get v1(): TwitterApiv1ReadWrite;
11 | get v2(): TwitterApiv2ReadWrite;
12 | /**
13 | * Get a client with read only rights.
14 | */
15 | get readOnly(): TwitterApiReadOnly;
16 | }
17 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/client/readwrite.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const client_v1_write_1 = __importDefault(require("../v1/client.v1.write"));
7 | const client_v2_write_1 = __importDefault(require("../v2/client.v2.write"));
8 | const readonly_1 = __importDefault(require("./readonly"));
9 | /**
10 | * Twitter v1.1 and v2 API client.
11 | */
12 | class TwitterApiReadWrite extends readonly_1.default {
13 | /* Direct access to subclients */
14 | get v1() {
15 | if (this._v1)
16 | return this._v1;
17 | return this._v1 = new client_v1_write_1.default(this);
18 | }
19 | get v2() {
20 | if (this._v2)
21 | return this._v2;
22 | return this._v2 = new client_v2_write_1.default(this);
23 | }
24 | /**
25 | * Get a client with read only rights.
26 | */
27 | get readOnly() {
28 | return this;
29 | }
30 | }
31 | exports.default = TwitterApiReadWrite;
32 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/globals.d.ts:
--------------------------------------------------------------------------------
1 | export declare const API_V2_PREFIX = "https://api.twitter.com/2/";
2 | export declare const API_V2_LABS_PREFIX = "https://api.twitter.com/labs/2/";
3 | export declare const API_V1_1_PREFIX = "https://api.twitter.com/1.1/";
4 | export declare const API_V1_1_UPLOAD_PREFIX = "https://upload.twitter.com/1.1/";
5 | export declare const API_V1_1_STREAM_PREFIX = "https://stream.twitter.com/1.1/";
6 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/globals.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.API_V1_1_STREAM_PREFIX = exports.API_V1_1_UPLOAD_PREFIX = exports.API_V1_1_PREFIX = exports.API_V2_LABS_PREFIX = exports.API_V2_PREFIX = void 0;
4 | exports.API_V2_PREFIX = 'https://api.twitter.com/2/';
5 | exports.API_V2_LABS_PREFIX = 'https://api.twitter.com/labs/2/';
6 | exports.API_V1_1_PREFIX = 'https://api.twitter.com/1.1/';
7 | exports.API_V1_1_UPLOAD_PREFIX = 'https://upload.twitter.com/1.1/';
8 | exports.API_V1_1_STREAM_PREFIX = 'https://stream.twitter.com/1.1/';
9 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/helpers.d.ts:
--------------------------------------------------------------------------------
1 | export interface SharedPromise {
2 | value: T | undefined;
3 | promise: Promise;
4 | }
5 | export declare function sharedPromise(getter: () => Promise): SharedPromise;
6 | export declare function arrayWrap(value: T | T[]): T[];
7 | export declare function trimUndefinedProperties(object: any): void;
8 | export declare function isTweetStreamV2ErrorPayload(payload: any): boolean;
9 | export declare function hasMultipleItems(item: string | string[]): boolean;
10 | export interface IDeprecationWarning {
11 | instance: string;
12 | method: string;
13 | problem: string;
14 | resolution: string;
15 | }
16 | export declare function safeDeprecationWarning(message: IDeprecationWarning): void;
17 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/index.d.ts:
--------------------------------------------------------------------------------
1 | export { default as default } from './client';
2 | export * from './client';
3 | export * from './v1/client.v1';
4 | export * from './v2/client.v2';
5 | export * from './v2/includes.v2.helper';
6 | export * from './v2-labs/client.v2.labs';
7 | export * from './types';
8 | export * from './paginators';
9 | export * from './stream/TweetStream';
10 | export * from './settings';
11 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | var __importDefault = (this && this.__importDefault) || function (mod) {
17 | return (mod && mod.__esModule) ? mod : { "default": mod };
18 | };
19 | Object.defineProperty(exports, "__esModule", { value: true });
20 | exports.default = void 0;
21 | var client_1 = require("./client");
22 | Object.defineProperty(exports, "default", { enumerable: true, get: function () { return __importDefault(client_1).default; } });
23 | __exportStar(require("./client"), exports);
24 | __exportStar(require("./v1/client.v1"), exports);
25 | __exportStar(require("./v2/client.v2"), exports);
26 | __exportStar(require("./v2/includes.v2.helper"), exports);
27 | __exportStar(require("./v2-labs/client.v2.labs"), exports);
28 | __exportStar(require("./types"), exports);
29 | __exportStar(require("./paginators"), exports);
30 | __exportStar(require("./stream/TweetStream"), exports);
31 | __exportStar(require("./settings"), exports);
32 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/dm.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import type { GetDmListV1Args, ReceivedDMEventsV1, TReceivedDMEvent, TwitterResponse, ReceivedWelcomeDMCreateEventV1, WelcomeDirectMessageListV1Result } from '../types';
2 | import { CursoredV1Paginator } from './paginator.v1';
3 | export declare class DmEventsV1Paginator extends CursoredV1Paginator {
4 | protected _endpoint: string;
5 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
6 | protected getPageLengthFromRequest(result: TwitterResponse): number;
7 | protected getItemArray(): import("../types").DirectMessageCreateV1[];
8 | /**
9 | * Events returned by paginator.
10 | */
11 | get events(): import("../types").DirectMessageCreateV1[];
12 | }
13 | export declare class WelcomeDmV1Paginator extends CursoredV1Paginator {
14 | protected _endpoint: string;
15 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
16 | protected getPageLengthFromRequest(result: TwitterResponse): number;
17 | protected getItemArray(): ReceivedWelcomeDMCreateEventV1[];
18 | get welcomeMessages(): ReceivedWelcomeDMCreateEventV1[];
19 | }
20 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/dm.paginator.v1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.WelcomeDmV1Paginator = exports.DmEventsV1Paginator = void 0;
4 | const paginator_v1_1 = require("./paginator.v1");
5 | class DmEventsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
6 | constructor() {
7 | super(...arguments);
8 | this._endpoint = 'direct_messages/events/list.json';
9 | }
10 | refreshInstanceFromResult(response, isNextPage) {
11 | const result = response.data;
12 | this._rateLimit = response.rateLimit;
13 | if (isNextPage) {
14 | this._realData.events.push(...result.events);
15 | this._realData.next_cursor = result.next_cursor;
16 | }
17 | }
18 | getPageLengthFromRequest(result) {
19 | return result.data.events.length;
20 | }
21 | getItemArray() {
22 | return this.events;
23 | }
24 | /**
25 | * Events returned by paginator.
26 | */
27 | get events() {
28 | return this._realData.events;
29 | }
30 | }
31 | exports.DmEventsV1Paginator = DmEventsV1Paginator;
32 | class WelcomeDmV1Paginator extends paginator_v1_1.CursoredV1Paginator {
33 | constructor() {
34 | super(...arguments);
35 | this._endpoint = 'direct_messages/welcome_messages/list.json';
36 | }
37 | refreshInstanceFromResult(response, isNextPage) {
38 | const result = response.data;
39 | this._rateLimit = response.rateLimit;
40 | if (isNextPage) {
41 | this._realData.welcome_messages.push(...result.welcome_messages);
42 | this._realData.next_cursor = result.next_cursor;
43 | }
44 | }
45 | getPageLengthFromRequest(result) {
46 | return result.data.welcome_messages.length;
47 | }
48 | getItemArray() {
49 | return this.welcomeMessages;
50 | }
51 | get welcomeMessages() {
52 | return this._realData.welcome_messages;
53 | }
54 | }
55 | exports.WelcomeDmV1Paginator = WelcomeDmV1Paginator;
56 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/followers.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import { CursoredV1Paginator } from './paginator.v1';
2 | import type { UserFollowerIdsV1Params, UserFollowerIdsV1Result, UserFollowerListV1Params, UserFollowerListV1Result, TwitterResponse, UserV1 } from '../types';
3 | export declare class UserFollowerListV1Paginator extends CursoredV1Paginator {
4 | protected _endpoint: string;
5 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
6 | protected getPageLengthFromRequest(result: TwitterResponse): number;
7 | protected getItemArray(): UserV1[];
8 | /**
9 | * Users returned by paginator.
10 | */
11 | get users(): UserV1[];
12 | }
13 | export declare class UserFollowerIdsV1Paginator extends CursoredV1Paginator {
14 | protected _endpoint: string;
15 | protected _maxResultsWhenFetchLast: number;
16 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
17 | protected getPageLengthFromRequest(result: TwitterResponse): number;
18 | protected getItemArray(): string[];
19 | /**
20 | * Users IDs returned by paginator.
21 | */
22 | get ids(): string[];
23 | }
24 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/followers.paginator.v1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.UserFollowerIdsV1Paginator = exports.UserFollowerListV1Paginator = void 0;
4 | const paginator_v1_1 = require("./paginator.v1");
5 | class UserFollowerListV1Paginator extends paginator_v1_1.CursoredV1Paginator {
6 | constructor() {
7 | super(...arguments);
8 | this._endpoint = 'followers/list.json';
9 | }
10 | refreshInstanceFromResult(response, isNextPage) {
11 | const result = response.data;
12 | this._rateLimit = response.rateLimit;
13 | if (isNextPage) {
14 | this._realData.users.push(...result.users);
15 | this._realData.next_cursor = result.next_cursor;
16 | }
17 | }
18 | getPageLengthFromRequest(result) {
19 | return result.data.users.length;
20 | }
21 | getItemArray() {
22 | return this.users;
23 | }
24 | /**
25 | * Users returned by paginator.
26 | */
27 | get users() {
28 | return this._realData.users;
29 | }
30 | }
31 | exports.UserFollowerListV1Paginator = UserFollowerListV1Paginator;
32 | class UserFollowerIdsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
33 | constructor() {
34 | super(...arguments);
35 | this._endpoint = 'followers/ids.json';
36 | this._maxResultsWhenFetchLast = 5000;
37 | }
38 | refreshInstanceFromResult(response, isNextPage) {
39 | const result = response.data;
40 | this._rateLimit = response.rateLimit;
41 | if (isNextPage) {
42 | this._realData.ids.push(...result.ids);
43 | this._realData.next_cursor = result.next_cursor;
44 | }
45 | }
46 | getPageLengthFromRequest(result) {
47 | return result.data.ids.length;
48 | }
49 | getItemArray() {
50 | return this.ids;
51 | }
52 | /**
53 | * Users IDs returned by paginator.
54 | */
55 | get ids() {
56 | return this._realData.ids;
57 | }
58 | }
59 | exports.UserFollowerIdsV1Paginator = UserFollowerIdsV1Paginator;
60 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/friends.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import { CursoredV1Paginator } from './paginator.v1';
2 | import type { UserFollowerIdsV1Params, UserFollowerIdsV1Result, UserFriendListV1Params, UserFriendListV1Result, UserV1, TwitterResponse } from '../types';
3 | export declare class UserFriendListV1Paginator extends CursoredV1Paginator {
4 | protected _endpoint: string;
5 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
6 | protected getPageLengthFromRequest(result: TwitterResponse): number;
7 | protected getItemArray(): UserV1[];
8 | /**
9 | * Users returned by paginator.
10 | */
11 | get users(): UserV1[];
12 | }
13 | export declare class UserFollowersIdsV1Paginator extends CursoredV1Paginator {
14 | protected _endpoint: string;
15 | protected _maxResultsWhenFetchLast: number;
16 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
17 | protected getPageLengthFromRequest(result: TwitterResponse): number;
18 | protected getItemArray(): string[];
19 | /**
20 | * Users IDs returned by paginator.
21 | */
22 | get ids(): string[];
23 | }
24 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/friends.paginator.v1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.UserFollowersIdsV1Paginator = exports.UserFriendListV1Paginator = void 0;
4 | const paginator_v1_1 = require("./paginator.v1");
5 | class UserFriendListV1Paginator extends paginator_v1_1.CursoredV1Paginator {
6 | constructor() {
7 | super(...arguments);
8 | this._endpoint = 'friends/list.json';
9 | }
10 | refreshInstanceFromResult(response, isNextPage) {
11 | const result = response.data;
12 | this._rateLimit = response.rateLimit;
13 | if (isNextPage) {
14 | this._realData.users.push(...result.users);
15 | this._realData.next_cursor = result.next_cursor;
16 | }
17 | }
18 | getPageLengthFromRequest(result) {
19 | return result.data.users.length;
20 | }
21 | getItemArray() {
22 | return this.users;
23 | }
24 | /**
25 | * Users returned by paginator.
26 | */
27 | get users() {
28 | return this._realData.users;
29 | }
30 | }
31 | exports.UserFriendListV1Paginator = UserFriendListV1Paginator;
32 | class UserFollowersIdsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
33 | constructor() {
34 | super(...arguments);
35 | this._endpoint = 'friends/ids.json';
36 | this._maxResultsWhenFetchLast = 5000;
37 | }
38 | refreshInstanceFromResult(response, isNextPage) {
39 | const result = response.data;
40 | this._rateLimit = response.rateLimit;
41 | if (isNextPage) {
42 | this._realData.ids.push(...result.ids);
43 | this._realData.next_cursor = result.next_cursor;
44 | }
45 | }
46 | getPageLengthFromRequest(result) {
47 | return result.data.ids.length;
48 | }
49 | getItemArray() {
50 | return this.ids;
51 | }
52 | /**
53 | * Users IDs returned by paginator.
54 | */
55 | get ids() {
56 | return this._realData.ids;
57 | }
58 | }
59 | exports.UserFollowersIdsV1Paginator = UserFollowersIdsV1Paginator;
60 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './tweet.paginator.v2';
2 | export * from './TwitterPaginator';
3 | export * from './dm.paginator.v1';
4 | export * from './mutes.paginator.v1';
5 | export * from './tweet.paginator.v1';
6 | export * from './user.paginator.v1';
7 | export * from './user.paginator.v2';
8 | export * from './list.paginator.v1';
9 | export * from './list.paginator.v2';
10 | export * from './friends.paginator.v1';
11 | export * from './followers.paginator.v1';
12 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./tweet.paginator.v2"), exports);
18 | __exportStar(require("./TwitterPaginator"), exports);
19 | __exportStar(require("./dm.paginator.v1"), exports);
20 | __exportStar(require("./mutes.paginator.v1"), exports);
21 | __exportStar(require("./tweet.paginator.v1"), exports);
22 | __exportStar(require("./user.paginator.v1"), exports);
23 | __exportStar(require("./user.paginator.v2"), exports);
24 | __exportStar(require("./list.paginator.v1"), exports);
25 | __exportStar(require("./list.paginator.v2"), exports);
26 | __exportStar(require("./friends.paginator.v1"), exports);
27 | __exportStar(require("./followers.paginator.v1"), exports);
28 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/list.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import { DoubleEndedListsCursorV1Result, DoubleEndedUsersCursorV1Result, ListMembersV1Params, ListOwnershipsV1Params, ListV1, TwitterResponse, UserV1 } from '../types';
2 | import { CursoredV1Paginator } from './paginator.v1';
3 | declare abstract class ListListsV1Paginator extends CursoredV1Paginator {
4 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
5 | protected getPageLengthFromRequest(result: TwitterResponse): number;
6 | protected getItemArray(): ListV1[];
7 | /**
8 | * Lists returned by paginator.
9 | */
10 | get lists(): ListV1[];
11 | }
12 | export declare class ListMembershipsV1Paginator extends ListListsV1Paginator {
13 | protected _endpoint: string;
14 | }
15 | export declare class ListOwnershipsV1Paginator extends ListListsV1Paginator {
16 | protected _endpoint: string;
17 | }
18 | export declare class ListSubscriptionsV1Paginator extends ListListsV1Paginator {
19 | protected _endpoint: string;
20 | }
21 | declare abstract class ListUsersV1Paginator extends CursoredV1Paginator {
22 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
23 | protected getPageLengthFromRequest(result: TwitterResponse): number;
24 | protected getItemArray(): UserV1[];
25 | /**
26 | * Users returned by paginator.
27 | */
28 | get users(): UserV1[];
29 | }
30 | export declare class ListMembersV1Paginator extends ListUsersV1Paginator {
31 | protected _endpoint: string;
32 | }
33 | export declare class ListSubscribersV1Paginator extends ListUsersV1Paginator {
34 | protected _endpoint: string;
35 | }
36 | export {};
37 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/list.paginator.v2.d.ts:
--------------------------------------------------------------------------------
1 | import type { GetListTimelineV2Params, ListTimelineV2Result, ListV2 } from '../types';
2 | import { TimelineV2Paginator } from './v2.paginator';
3 | declare abstract class ListTimelineV2Paginator extends TimelineV2Paginator {
4 | protected getItemArray(): ListV2[];
5 | /**
6 | * Lists returned by paginator.
7 | */
8 | get lists(): ListV2[];
9 | get meta(): TResult["meta"];
10 | }
11 | export declare class UserOwnedListsV2Paginator extends ListTimelineV2Paginator {
14 | protected _endpoint: string;
15 | }
16 | export declare class UserListMembershipsV2Paginator extends ListTimelineV2Paginator {
19 | protected _endpoint: string;
20 | }
21 | export declare class UserListFollowedV2Paginator extends ListTimelineV2Paginator {
24 | protected _endpoint: string;
25 | }
26 | export {};
27 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/list.paginator.v2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.UserListFollowedV2Paginator = exports.UserListMembershipsV2Paginator = exports.UserOwnedListsV2Paginator = void 0;
4 | const v2_paginator_1 = require("./v2.paginator");
5 | class ListTimelineV2Paginator extends v2_paginator_1.TimelineV2Paginator {
6 | getItemArray() {
7 | return this.lists;
8 | }
9 | /**
10 | * Lists returned by paginator.
11 | */
12 | get lists() {
13 | var _a;
14 | return (_a = this._realData.data) !== null && _a !== void 0 ? _a : [];
15 | }
16 | get meta() {
17 | return super.meta;
18 | }
19 | }
20 | class UserOwnedListsV2Paginator extends ListTimelineV2Paginator {
21 | constructor() {
22 | super(...arguments);
23 | this._endpoint = 'users/:id/owned_lists';
24 | }
25 | }
26 | exports.UserOwnedListsV2Paginator = UserOwnedListsV2Paginator;
27 | class UserListMembershipsV2Paginator extends ListTimelineV2Paginator {
28 | constructor() {
29 | super(...arguments);
30 | this._endpoint = 'users/:id/list_memberships';
31 | }
32 | }
33 | exports.UserListMembershipsV2Paginator = UserListMembershipsV2Paginator;
34 | class UserListFollowedV2Paginator extends ListTimelineV2Paginator {
35 | constructor() {
36 | super(...arguments);
37 | this._endpoint = 'users/:id/followed_lists';
38 | }
39 | }
40 | exports.UserListFollowedV2Paginator = UserListFollowedV2Paginator;
41 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/mutes.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import { CursoredV1Paginator } from './paginator.v1';
2 | import type { MuteUserIdsV1Params, MuteUserIdsV1Result, MuteUserListV1Params, MuteUserListV1Result, TwitterResponse, UserV1 } from '../types';
3 | export declare class MuteUserListV1Paginator extends CursoredV1Paginator {
4 | protected _endpoint: string;
5 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
6 | protected getPageLengthFromRequest(result: TwitterResponse): number;
7 | protected getItemArray(): UserV1[];
8 | /**
9 | * Users returned by paginator.
10 | */
11 | get users(): UserV1[];
12 | }
13 | export declare class MuteUserIdsV1Paginator extends CursoredV1Paginator {
14 | protected _endpoint: string;
15 | protected _maxResultsWhenFetchLast: number;
16 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
17 | protected getPageLengthFromRequest(result: TwitterResponse): number;
18 | protected getItemArray(): string[];
19 | /**
20 | * Users IDs returned by paginator.
21 | */
22 | get ids(): string[];
23 | }
24 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/mutes.paginator.v1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.MuteUserIdsV1Paginator = exports.MuteUserListV1Paginator = void 0;
4 | const paginator_v1_1 = require("./paginator.v1");
5 | class MuteUserListV1Paginator extends paginator_v1_1.CursoredV1Paginator {
6 | constructor() {
7 | super(...arguments);
8 | this._endpoint = 'mutes/users/list.json';
9 | }
10 | refreshInstanceFromResult(response, isNextPage) {
11 | const result = response.data;
12 | this._rateLimit = response.rateLimit;
13 | if (isNextPage) {
14 | this._realData.users.push(...result.users);
15 | this._realData.next_cursor = result.next_cursor;
16 | }
17 | }
18 | getPageLengthFromRequest(result) {
19 | return result.data.users.length;
20 | }
21 | getItemArray() {
22 | return this.users;
23 | }
24 | /**
25 | * Users returned by paginator.
26 | */
27 | get users() {
28 | return this._realData.users;
29 | }
30 | }
31 | exports.MuteUserListV1Paginator = MuteUserListV1Paginator;
32 | class MuteUserIdsV1Paginator extends paginator_v1_1.CursoredV1Paginator {
33 | constructor() {
34 | super(...arguments);
35 | this._endpoint = 'mutes/users/ids.json';
36 | this._maxResultsWhenFetchLast = 5000;
37 | }
38 | refreshInstanceFromResult(response, isNextPage) {
39 | const result = response.data;
40 | this._rateLimit = response.rateLimit;
41 | if (isNextPage) {
42 | this._realData.ids.push(...result.ids);
43 | this._realData.next_cursor = result.next_cursor;
44 | }
45 | }
46 | getPageLengthFromRequest(result) {
47 | return result.data.ids.length;
48 | }
49 | getItemArray() {
50 | return this.ids;
51 | }
52 | /**
53 | * Users IDs returned by paginator.
54 | */
55 | get ids() {
56 | return this._realData.ids;
57 | }
58 | }
59 | exports.MuteUserIdsV1Paginator = MuteUserIdsV1Paginator;
60 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import { TwitterResponse } from '../types';
2 | import TwitterPaginator from './TwitterPaginator';
3 | export declare abstract class CursoredV1Paginator extends TwitterPaginator {
9 | protected getNextQueryParams(maxResults?: number): Partial;
10 | protected isFetchLastOver(result: TwitterResponse): boolean;
11 | protected canFetchNextPage(result: TApiResult): boolean;
12 | private isNextCursorInvalid;
13 | }
14 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/paginator.v1.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.CursoredV1Paginator = void 0;
7 | const TwitterPaginator_1 = __importDefault(require("./TwitterPaginator"));
8 | class CursoredV1Paginator extends TwitterPaginator_1.default {
9 | getNextQueryParams(maxResults) {
10 | var _a;
11 | return {
12 | ...this._queryParams,
13 | cursor: (_a = this._realData.next_cursor_str) !== null && _a !== void 0 ? _a : this._realData.next_cursor,
14 | ...(maxResults ? { count: maxResults } : {}),
15 | };
16 | }
17 | isFetchLastOver(result) {
18 | // If we cant fetch next page
19 | return !this.canFetchNextPage(result.data);
20 | }
21 | canFetchNextPage(result) {
22 | // If one of cursor is valid
23 | return !this.isNextCursorInvalid(result.next_cursor) || !this.isNextCursorInvalid(result.next_cursor_str);
24 | }
25 | isNextCursorInvalid(value) {
26 | return value === undefined
27 | || value === 0
28 | || value === -1
29 | || value === '0'
30 | || value === '-1';
31 | }
32 | }
33 | exports.CursoredV1Paginator = CursoredV1Paginator;
34 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/tweet.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterPaginator from './TwitterPaginator';
2 | import { TwitterResponse, TweetV1, TweetV1TimelineResult, TweetV1TimelineParams, TweetV1UserTimelineParams, ListStatusesV1Params } from '../types';
3 | /** A generic TwitterPaginator able to consume TweetV1 timelines. */
4 | declare abstract class TweetTimelineV1Paginator extends TwitterPaginator {
5 | protected hasFinishedFetch: boolean;
6 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
7 | protected getNextQueryParams(maxResults?: number): {
8 | max_results?: number | undefined;
9 | } & Partial & {
10 | max_id: string;
11 | };
12 | protected getPageLengthFromRequest(result: TwitterResponse): number;
13 | protected isFetchLastOver(result: TwitterResponse): boolean;
14 | protected canFetchNextPage(result: TResult): boolean;
15 | protected getItemArray(): TResult;
16 | /**
17 | * Tweets returned by paginator.
18 | */
19 | get tweets(): TResult;
20 | get done(): boolean;
21 | }
22 | export declare class HomeTimelineV1Paginator extends TweetTimelineV1Paginator {
23 | protected _endpoint: string;
24 | }
25 | export declare class MentionTimelineV1Paginator extends TweetTimelineV1Paginator {
26 | protected _endpoint: string;
27 | }
28 | export declare class UserTimelineV1Paginator extends TweetTimelineV1Paginator {
29 | protected _endpoint: string;
30 | }
31 | export declare class ListTimelineV1Paginator extends TweetTimelineV1Paginator {
32 | protected _endpoint: string;
33 | }
34 | export declare class UserFavoritesV1Paginator extends TweetTimelineV1Paginator {
35 | protected _endpoint: string;
36 | }
37 | export {};
38 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/user.paginator.v1.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterPaginator from './TwitterPaginator';
2 | import { FriendshipsIncomingV1Params, FriendshipsIncomingV1Result, TwitterResponse, UserSearchV1Params, UserV1 } from '../types';
3 | import { CursoredV1Paginator } from './paginator.v1';
4 | /** A generic TwitterPaginator able to consume TweetV1 timelines. */
5 | export declare class UserSearchV1Paginator extends TwitterPaginator {
6 | _endpoint: string;
7 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
8 | protected getNextQueryParams(maxResults?: number): {
9 | count?: number | undefined;
10 | page: number;
11 | q?: string | undefined;
12 | include_entities?: boolean | undefined;
13 | tweet_mode?: "extended" | undefined;
14 | };
15 | protected getPageLengthFromRequest(result: TwitterResponse): number;
16 | protected isFetchLastOver(result: TwitterResponse): boolean;
17 | protected canFetchNextPage(result: UserV1[]): boolean;
18 | protected getItemArray(): UserV1[];
19 | /**
20 | * Users returned by paginator.
21 | */
22 | get users(): UserV1[];
23 | }
24 | export declare class FriendshipsIncomingV1Paginator extends CursoredV1Paginator {
25 | protected _endpoint: string;
26 | protected _maxResultsWhenFetchLast: number;
27 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: true): void;
28 | protected getPageLengthFromRequest(result: TwitterResponse): number;
29 | protected getItemArray(): string[];
30 | /**
31 | * Users IDs returned by paginator.
32 | */
33 | get ids(): string[];
34 | }
35 | export declare class FriendshipsOutgoingV1Paginator extends FriendshipsIncomingV1Paginator {
36 | protected _endpoint: string;
37 | }
38 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/user.paginator.v2.d.ts:
--------------------------------------------------------------------------------
1 | import { UserV2, UserV2TimelineParams, UserV2TimelineResult } from '../types';
2 | import { TimelineV2Paginator } from './v2.paginator';
3 | /** A generic PreviousableTwitterPaginator able to consume UserV2 timelines. */
4 | declare abstract class UserTimelineV2Paginator extends TimelineV2Paginator {
5 | protected getItemArray(): UserV2[];
6 | /**
7 | * Users returned by paginator.
8 | */
9 | get users(): UserV2[];
10 | get meta(): TResult["meta"];
11 | }
12 | export declare class UserBlockingUsersV2Paginator extends UserTimelineV2Paginator {
15 | protected _endpoint: string;
16 | }
17 | export declare class UserMutingUsersV2Paginator extends UserTimelineV2Paginator {
20 | protected _endpoint: string;
21 | }
22 | export declare class UserFollowersV2Paginator extends UserTimelineV2Paginator {
25 | protected _endpoint: string;
26 | }
27 | export declare class UserFollowingV2Paginator extends UserTimelineV2Paginator {
30 | protected _endpoint: string;
31 | }
32 | export declare class UserListMembersV2Paginator extends UserTimelineV2Paginator {
35 | protected _endpoint: string;
36 | }
37 | export declare class UserListFollowersV2Paginator extends UserTimelineV2Paginator {
40 | protected _endpoint: string;
41 | }
42 | export declare class TweetLikingUsersV2Paginator extends UserTimelineV2Paginator {
45 | protected _endpoint: string;
46 | }
47 | export declare class TweetRetweetersUsersV2Paginator extends UserTimelineV2Paginator {
50 | protected _endpoint: string;
51 | }
52 | export {};
53 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/paginators/v2.paginator.d.ts:
--------------------------------------------------------------------------------
1 | import type { TwitterResponse } from '../types';
2 | import type { DataMetaAndIncludeV2 } from '../types/v2/shared.v2.types';
3 | import { TwitterV2IncludesHelper } from '../v2/includes.v2.helper';
4 | import { PreviousableTwitterPaginator } from './TwitterPaginator';
5 | /** A generic PreviousableTwitterPaginator with common v2 helper methods. */
6 | export declare abstract class TwitterV2Paginator, TParams extends object, TItem, TShared = any> extends PreviousableTwitterPaginator {
7 | protected _includesInstance?: TwitterV2IncludesHelper;
8 | protected updateIncludes(data: TResult): void;
9 | /** Throw if the current paginator is not usable. */
10 | protected assertUsable(): void;
11 | get meta(): any;
12 | get includes(): TwitterV2IncludesHelper;
13 | get errors(): import("../types").InlineErrorV2[];
14 | /** `true` if this paginator only contains error payload and no metadata found to consume data. */
15 | get unusable(): boolean;
16 | }
17 | /** A generic TwitterV2Paginator able to consume v2 timelines that use max_results and pagination tokens. */
18 | export declare abstract class TimelineV2Paginator, TParams extends {
19 | max_results?: number;
20 | pagination_token?: string;
21 | }, TItem, TShared = any> extends TwitterV2Paginator {
22 | protected refreshInstanceFromResult(response: TwitterResponse, isNextPage: boolean): void;
23 | protected getNextQueryParams(maxResults?: number): {
24 | max_results?: number | undefined;
25 | } & Partial & {
26 | pagination_token: any;
27 | };
28 | protected getPreviousQueryParams(maxResults?: number): {
29 | max_results?: number | undefined;
30 | } & Partial & {
31 | pagination_token: any;
32 | };
33 | protected getPageLengthFromRequest(result: TwitterResponse): any;
34 | protected isFetchLastOver(result: TwitterResponse): boolean;
35 | protected canFetchNextPage(result: TResult): boolean;
36 | }
37 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/plugins/helpers.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { ClientRequestArgs } from 'http';
3 | import type { ClientRequestMaker } from '../client-mixins/request-maker.mixin';
4 | import { IGetHttpRequestArgs } from '../types';
5 | import type { IComputedHttpRequestArgs } from '../types/request-maker.mixin.types';
6 | export declare function hasRequestErrorPlugins(client: ClientRequestMaker): boolean;
7 | export declare function applyResponseHooks(this: ClientRequestMaker, requestParams: IGetHttpRequestArgs, computedParams: IComputedHttpRequestArgs, requestOptions: Partial, error: any): Promise;
8 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/plugins/helpers.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.applyResponseHooks = exports.hasRequestErrorPlugins = void 0;
4 | const types_1 = require("../types");
5 | /* Plugin helpers */
6 | function hasRequestErrorPlugins(client) {
7 | var _a;
8 | if (!((_a = client.clientSettings.plugins) === null || _a === void 0 ? void 0 : _a.length)) {
9 | return false;
10 | }
11 | for (const plugin of client.clientSettings.plugins) {
12 | if (plugin.onRequestError || plugin.onResponseError) {
13 | return true;
14 | }
15 | }
16 | return false;
17 | }
18 | exports.hasRequestErrorPlugins = hasRequestErrorPlugins;
19 | async function applyResponseHooks(requestParams, computedParams, requestOptions, error) {
20 | let override;
21 | if (error instanceof types_1.ApiRequestError || error instanceof types_1.ApiPartialResponseError) {
22 | override = await this.applyPluginMethod('onRequestError', {
23 | client: this,
24 | url: this.getUrlObjectFromUrlString(requestParams.url),
25 | params: requestParams,
26 | computedParams,
27 | requestOptions,
28 | error,
29 | });
30 | }
31 | else if (error instanceof types_1.ApiResponseError) {
32 | override = await this.applyPluginMethod('onResponseError', {
33 | client: this,
34 | url: this.getUrlObjectFromUrlString(requestParams.url),
35 | params: requestParams,
36 | computedParams,
37 | requestOptions,
38 | error,
39 | });
40 | }
41 | if (override && override instanceof types_1.TwitterApiPluginResponseOverride) {
42 | return override.value;
43 | }
44 | return Promise.reject(error);
45 | }
46 | exports.applyResponseHooks = applyResponseHooks;
47 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/settings.d.ts:
--------------------------------------------------------------------------------
1 | export interface ITwitterApiV2Settings {
2 | debug: boolean;
3 | deprecationWarnings: boolean;
4 | logger: ITwitterApiV2SettingsLogger;
5 | }
6 | export interface ITwitterApiV2SettingsLogger {
7 | log(message: string, payload?: any): void;
8 | }
9 | export declare const TwitterApiV2Settings: ITwitterApiV2Settings;
10 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/settings.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.TwitterApiV2Settings = void 0;
4 | exports.TwitterApiV2Settings = {
5 | debug: false,
6 | deprecationWarnings: true,
7 | logger: { log: console.log.bind(console) },
8 | };
9 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/stream/TweetStreamEventCombiner.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { EventEmitter } from 'events';
3 | import type TweetStream from './TweetStream';
4 | export declare class TweetStreamEventCombiner extends EventEmitter {
5 | private stream;
6 | private stack;
7 | private onceNewEvent;
8 | constructor(stream: TweetStream);
9 | /** Returns a new `Promise` that will `resolve` on next event (`data` or any sort of error). */
10 | nextEvent(): Promise<{
11 | type: "error";
12 | payload?: any;
13 | } | {
14 | type: "data";
15 | payload: T;
16 | }>;
17 | /** Returns `true` if there's something in the stack. */
18 | hasStack(): boolean;
19 | /** Returns stacked data events, and clean the stack. */
20 | popStack(): T[];
21 | /** Cleanup all the listeners attached on stream. */
22 | destroy(): void;
23 | private emitEvent;
24 | private onStreamError;
25 | private onStreamData;
26 | }
27 | export default TweetStreamEventCombiner;
28 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/stream/TweetStreamParser.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import { EventEmitter } from 'events';
3 | export default class TweetStreamParser extends EventEmitter {
4 | protected currentMessage: string;
5 | push(chunk: string): void;
6 | /** Reset the currently stored message (f.e. on connection reset) */
7 | reset(): void;
8 | }
9 | export declare enum EStreamParserEvent {
10 | ParsedData = "parsed data",
11 | ParseError = "parse error"
12 | }
13 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/stream/TweetStreamParser.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.EStreamParserEvent = void 0;
4 | const events_1 = require("events");
5 | class TweetStreamParser extends events_1.EventEmitter {
6 | constructor() {
7 | super(...arguments);
8 | this.currentMessage = '';
9 | }
10 | // Code partially belongs to twitter-stream-api for this
11 | // https://github.com/trygve-lie/twitter-stream-api/blob/master/lib/parser.js
12 | push(chunk) {
13 | this.currentMessage += chunk;
14 | chunk = this.currentMessage;
15 | const size = chunk.length;
16 | let start = 0;
17 | let offset = 0;
18 | while (offset < size) {
19 | // Take [offset, offset+1] inside a new string
20 | if (chunk.slice(offset, offset + 2) === '\r\n') {
21 | // If chunk contains \r\n after current offset,
22 | // parse [start, ..., offset] as a tweet
23 | const piece = chunk.slice(start, offset);
24 | start = offset += 2;
25 | // If empty object
26 | if (!piece.length) {
27 | continue;
28 | }
29 | try {
30 | const payload = JSON.parse(piece);
31 | if (payload) {
32 | this.emit(EStreamParserEvent.ParsedData, payload);
33 | continue;
34 | }
35 | }
36 | catch (error) {
37 | this.emit(EStreamParserEvent.ParseError, error);
38 | }
39 | }
40 | offset++;
41 | }
42 | this.currentMessage = chunk.slice(start, size);
43 | }
44 | /** Reset the currently stored message (f.e. on connection reset) */
45 | reset() {
46 | this.currentMessage = '';
47 | }
48 | }
49 | exports.default = TweetStreamParser;
50 | var EStreamParserEvent;
51 | (function (EStreamParserEvent) {
52 | EStreamParserEvent["ParsedData"] = "parsed data";
53 | EStreamParserEvent["ParseError"] = "parse error";
54 | })(EStreamParserEvent = exports.EStreamParserEvent || (exports.EStreamParserEvent = {}));
55 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/test/utils.d.ts:
--------------------------------------------------------------------------------
1 | import { TwitterApi } from '..';
2 | /** User OAuth 1.0a client */
3 | export declare function getUserClient(this: any): TwitterApi;
4 | export declare function getUserKeys(): {
5 | appKey: string;
6 | appSecret: string;
7 | accessToken: string;
8 | accessSecret: string;
9 | };
10 | export declare function sleepTest(ms: number): Promise;
11 | /** User-unlogged OAuth 1.0a client */
12 | export declare function getRequestClient(): TwitterApi;
13 | export declare function getRequestKeys(): {
14 | appKey: string;
15 | appSecret: string;
16 | };
17 | export declare function getAuthLink(callback: string): Promise<{
18 | oauth_token: string;
19 | oauth_token_secret: string;
20 | oauth_callback_confirmed: "true";
21 | url: string;
22 | }>;
23 | export declare function getAccessClient(verifier: string): Promise;
24 | /** App OAuth 2.0 client */
25 | export declare function getAppClient(): Promise;
26 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/auth.types.d.ts:
--------------------------------------------------------------------------------
1 | import type TwitterApi from '../client';
2 | import { TypeOrArrayOf } from './shared.types';
3 | export declare type TOAuth2Scope = 'tweet.read' | 'tweet.write' | 'tweet.moderate.write' | 'users.read' | 'follows.read' | 'follows.write' | 'offline.access' | 'space.read' | 'mute.read' | 'mute.write' | 'like.read' | 'like.write' | 'list.read' | 'list.write' | 'block.read' | 'block.write' | 'bookmark.read' | 'bookmark.write';
4 | export interface BuildOAuth2RequestLinkArgs {
5 | scope?: TypeOrArrayOf | TypeOrArrayOf;
6 | state?: string;
7 | }
8 | export interface AccessOAuth2TokenArgs {
9 | /** The same URI given to generate link at previous step. */
10 | redirectUri: string;
11 | /** The code obtained in link generation step. */
12 | codeVerifier: string;
13 | /** The code given by Twitter in query string, after redirection to your callback URL. */
14 | code: string;
15 | }
16 | export interface AccessOAuth2TokenResult {
17 | token_type: 'bearer';
18 | expires_in: number;
19 | access_token: string;
20 | scope: string;
21 | refresh_token?: string;
22 | }
23 | export interface RequestTokenArgs {
24 | authAccessType: 'read' | 'write';
25 | linkMode: 'authenticate' | 'authorize';
26 | forceLogin: boolean;
27 | screenName: string;
28 | }
29 | export interface RequestTokenResult {
30 | oauth_token: string;
31 | oauth_token_secret: string;
32 | oauth_callback_confirmed: 'true';
33 | }
34 | export interface IOAuth2RequestTokenResult {
35 | url: string;
36 | state: string;
37 | codeVerifier: string;
38 | codeChallenge: string;
39 | }
40 | export interface AccessTokenResult {
41 | oauth_token: string;
42 | oauth_token_secret: string;
43 | user_id: string;
44 | screen_name: string;
45 | }
46 | export interface BearerTokenResult {
47 | token_type: 'bearer';
48 | access_token: string;
49 | }
50 | export interface LoginResult {
51 | userId: string;
52 | screenName: string;
53 | accessToken: string;
54 | accessSecret: string;
55 | client: TwitterApi;
56 | }
57 | export interface IParsedOAuth2TokenResult {
58 | client: TwitterApi;
59 | expiresIn: number;
60 | accessToken: string;
61 | scope: TOAuth2Scope[];
62 | refreshToken?: string;
63 | }
64 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/auth.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/client.types.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { Agent } from 'http';
3 | import type { ITwitterApiClientPlugin } from './plugins';
4 | import type { TRequestCompressionLevel } from './request-maker.mixin.types';
5 | export declare enum ETwitterStreamEvent {
6 | Connected = "connected",
7 | ConnectError = "connect error",
8 | ConnectionError = "connection error",
9 | ConnectionClosed = "connection closed",
10 | ConnectionLost = "connection lost",
11 | ReconnectAttempt = "reconnect attempt",
12 | Reconnected = "reconnected",
13 | ReconnectError = "reconnect error",
14 | ReconnectLimitExceeded = "reconnect limit exceeded",
15 | DataKeepAlive = "data keep-alive",
16 | Data = "data event content",
17 | DataError = "data twitter error",
18 | TweetParseError = "data tweet parse error",
19 | Error = "stream error"
20 | }
21 | export interface TwitterApiTokens {
22 | appKey: string;
23 | appSecret: string;
24 | accessToken?: string;
25 | accessSecret?: string;
26 | }
27 | export interface TwitterApiOAuth2Init {
28 | clientId: string;
29 | clientSecret?: string;
30 | }
31 | export interface TwitterApiBasicAuth {
32 | username: string;
33 | password: string;
34 | }
35 | export interface IClientTokenBearer {
36 | bearerToken: string;
37 | type: 'oauth2';
38 | }
39 | export interface IClientOAuth2UserClient {
40 | clientId: string;
41 | type: 'oauth2-user';
42 | }
43 | export interface IClientTokenBasic {
44 | token: string;
45 | type: 'basic';
46 | }
47 | export interface IClientTokenOauth {
48 | appKey: string;
49 | appSecret: string;
50 | accessToken?: string;
51 | accessSecret?: string;
52 | type: 'oauth-1.0a';
53 | }
54 | export interface IClientTokenNone {
55 | type: 'none';
56 | }
57 | export declare type TClientTokens = IClientTokenNone | IClientTokenBearer | IClientTokenOauth | IClientTokenBasic | IClientOAuth2UserClient;
58 | export interface IClientSettings {
59 | /** Used to send HTTPS requests. This is mostly used to make requests work behind a proxy. */
60 | httpAgent: Agent;
61 | plugins: ITwitterApiClientPlugin[];
62 | compression: TRequestCompressionLevel;
63 | }
64 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/client.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.ETwitterStreamEvent = void 0;
4 | var ETwitterStreamEvent;
5 | (function (ETwitterStreamEvent) {
6 | ETwitterStreamEvent["Connected"] = "connected";
7 | ETwitterStreamEvent["ConnectError"] = "connect error";
8 | ETwitterStreamEvent["ConnectionError"] = "connection error";
9 | ETwitterStreamEvent["ConnectionClosed"] = "connection closed";
10 | ETwitterStreamEvent["ConnectionLost"] = "connection lost";
11 | ETwitterStreamEvent["ReconnectAttempt"] = "reconnect attempt";
12 | ETwitterStreamEvent["Reconnected"] = "reconnected";
13 | ETwitterStreamEvent["ReconnectError"] = "reconnect error";
14 | ETwitterStreamEvent["ReconnectLimitExceeded"] = "reconnect limit exceeded";
15 | ETwitterStreamEvent["DataKeepAlive"] = "data keep-alive";
16 | ETwitterStreamEvent["Data"] = "data event content";
17 | ETwitterStreamEvent["DataError"] = "data twitter error";
18 | ETwitterStreamEvent["TweetParseError"] = "data tweet parse error";
19 | ETwitterStreamEvent["Error"] = "stream error";
20 | })(ETwitterStreamEvent = exports.ETwitterStreamEvent || (exports.ETwitterStreamEvent = {}));
21 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/entities.types.d.ts:
--------------------------------------------------------------------------------
1 | export interface Entity {
2 | start: number;
3 | end: number;
4 | }
5 | export interface UrlEntity extends Entity {
6 | url: string;
7 | expanded_url: string;
8 | display_url: string;
9 | }
10 | export interface HashtagEntity extends Entity {
11 | hashtag: string;
12 | }
13 | export interface CashtagEntity extends Entity {
14 | cashtag: string;
15 | }
16 | export interface MentionEntity extends Entity {
17 | username: string;
18 | }
19 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/entities.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './v1';
2 | export * from './v2';
3 | export * from './errors.types';
4 | export * from './responses.types';
5 | export * from './client.types';
6 | export * from './auth.types';
7 | export * from './plugins';
8 | export { IGetHttpRequestArgs } from './request-maker.mixin.types';
9 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./v1"), exports);
18 | __exportStar(require("./v2"), exports);
19 | __exportStar(require("./errors.types"), exports);
20 | __exportStar(require("./responses.types"), exports);
21 | __exportStar(require("./client.types"), exports);
22 | __exportStar(require("./auth.types"), exports);
23 | __exportStar(require("./plugins"), exports);
24 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/plugins/client.plugins.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.TwitterApiPluginResponseOverride = void 0;
4 | class TwitterApiPluginResponseOverride {
5 | constructor(value) {
6 | this.value = value;
7 | }
8 | }
9 | exports.TwitterApiPluginResponseOverride = TwitterApiPluginResponseOverride;
10 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/plugins/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './client.plugins.types';
2 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/plugins/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./client.plugins.types"), exports);
18 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/request-maker.mixin.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/responses.types.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import type { IncomingHttpHeaders } from 'http';
3 | export interface TwitterResponse {
4 | headers: IncomingHttpHeaders;
5 | data: T;
6 | rateLimit?: TwitterRateLimit;
7 | }
8 | export interface TwitterRateLimit {
9 | limit: number;
10 | reset: number;
11 | remaining: number;
12 | }
13 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/responses.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/shared.types.d.ts:
--------------------------------------------------------------------------------
1 | export declare type NumberString = number | string;
2 | export declare type BooleanString = boolean | string;
3 | export declare type TypeOrArrayOf = T | T[];
4 | export declare type PromiseOrType = T | Promise;
5 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/shared.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/dev-utilities.v1.types.d.ts:
--------------------------------------------------------------------------------
1 | export declare type TAppRateLimitResourceV1 = 'help' | 'statuses' | 'friends' | 'followers' | 'users' | 'search' | 'trends' | 'favorites' | 'friendships' | 'direct_messages' | 'lists' | 'geo' | 'account' | 'application' | 'account_activity';
2 | export interface AppRateLimitV1Result {
3 | rate_limit_context: {
4 | access_token: string;
5 | };
6 | resources: {
7 | [TResourceName in TAppRateLimitResourceV1]?: {
8 | [resourceEndpoint: string]: AppRateLimitEndpointV1;
9 | };
10 | };
11 | }
12 | export interface AppRateLimitEndpointV1 {
13 | limit: number;
14 | remaining: number;
15 | reset: number;
16 | }
17 | export interface HelpLanguageV1Result {
18 | code: string;
19 | status: string;
20 | name: string;
21 | }
22 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/dev-utilities.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/dm.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.EDirectMessageEventTypeV1 = void 0;
4 | // Creation of DMs
5 | var EDirectMessageEventTypeV1;
6 | (function (EDirectMessageEventTypeV1) {
7 | EDirectMessageEventTypeV1["Create"] = "message_create";
8 | EDirectMessageEventTypeV1["WelcomeCreate"] = "welcome_message";
9 | })(EDirectMessageEventTypeV1 = exports.EDirectMessageEventTypeV1 || (exports.EDirectMessageEventTypeV1 = {}));
10 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/entities.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/geo.v1.types.d.ts:
--------------------------------------------------------------------------------
1 | import { PlaceV1 } from './entities.v1.types';
2 | export interface ReverseGeoCodeV1Params {
3 | lat: number;
4 | long: number;
5 | accuracy?: string;
6 | granularity?: 'city' | 'neighborhood' | 'country' | 'admin';
7 | max_results?: number;
8 | }
9 | export interface ReverseGeoCodeV1Result {
10 | query: {
11 | params: Partial;
12 | type: string;
13 | url: string;
14 | };
15 | result: {
16 | places: PlaceV1[];
17 | };
18 | }
19 | export interface SearchGeoV1Params extends Partial {
20 | ip?: string;
21 | query?: string;
22 | }
23 | export interface SearchGeoV1Result {
24 | query: {
25 | params: SearchGeoV1Params;
26 | type: string;
27 | url: string;
28 | };
29 | result: {
30 | places: PlaceV1[];
31 | };
32 | }
33 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/geo.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './streaming.v1.types';
2 | export * from './tweet.v1.types';
3 | export * from './entities.v1.types';
4 | export * from './user.v1.types';
5 | export * from './dev-utilities.v1.types';
6 | export * from './geo.v1.types';
7 | export * from './trends.v1.types';
8 | export * from './dm.v1.types';
9 | export * from './list.v1.types';
10 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./streaming.v1.types"), exports);
18 | __exportStar(require("./tweet.v1.types"), exports);
19 | __exportStar(require("./entities.v1.types"), exports);
20 | __exportStar(require("./user.v1.types"), exports);
21 | __exportStar(require("./dev-utilities.v1.types"), exports);
22 | __exportStar(require("./geo.v1.types"), exports);
23 | __exportStar(require("./trends.v1.types"), exports);
24 | __exportStar(require("./dm.v1.types"), exports);
25 | __exportStar(require("./list.v1.types"), exports);
26 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/list.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/streaming.v1.types.d.ts:
--------------------------------------------------------------------------------
1 | import type { TypeOrArrayOf } from '../shared.types';
2 | export interface AskTweetStreamV1Params {
3 | tweet_mode?: 'extended' | 'compat';
4 | /** Specifies whether stall warnings should be delivered. */
5 | stall_warnings: boolean;
6 | }
7 | /**
8 | * See https://developer.twitter.com/en/docs/twitter-api/v1/tweets/filter-realtime/guides/basic-stream-parameters
9 | * for detailed documentation.
10 | */
11 | export interface FilterStreamV1Params extends AskTweetStreamV1Params {
12 | /** A list of user IDs, indicating the users to return statuses for in the stream. */
13 | follow: TypeOrArrayOf<(string | BigInt)>;
14 | /** Keywords to track. */
15 | track: TypeOrArrayOf;
16 | /** Specifies a set of bounding boxes to track. */
17 | locations: TypeOrArrayOf<{
18 | lng: string;
19 | lat: string;
20 | }>;
21 | /** Specifies whether stall warnings should be delivered. */
22 | stall_warnings: boolean;
23 | [otherParameter: string]: any;
24 | }
25 | export interface SampleStreamV1Params extends AskTweetStreamV1Params {
26 | [otherParameter: string]: any;
27 | }
28 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/streaming.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/trends.v1.types.d.ts:
--------------------------------------------------------------------------------
1 | import { TrendLocationV1, TrendV1 } from './entities.v1.types';
2 | export interface TrendsPlaceV1Params {
3 | exclude: string;
4 | }
5 | export interface TrendMatchV1 {
6 | trends: TrendV1[];
7 | as_of: string;
8 | created_at: string;
9 | locations: TrendLocationV1[];
10 | }
11 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/trends.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/tweet.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | exports.EUploadMimeType = void 0;
4 | var EUploadMimeType;
5 | (function (EUploadMimeType) {
6 | EUploadMimeType["Jpeg"] = "image/jpeg";
7 | EUploadMimeType["Mp4"] = "video/mp4";
8 | EUploadMimeType["Gif"] = "image/gif";
9 | EUploadMimeType["Png"] = "image/png";
10 | EUploadMimeType["Srt"] = "text/plain";
11 | EUploadMimeType["Webp"] = "image/webp";
12 | })(EUploadMimeType = exports.EUploadMimeType || (exports.EUploadMimeType = {}));
13 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v1/user.v1.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from './streaming.v2.types';
2 | export * from './tweet.v2.types';
3 | export * from './tweet.definition.v2';
4 | export * from './user.v2.types';
5 | export * from './spaces.v2.types';
6 | export * from './list.v2.types';
7 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/index.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3 | if (k2 === undefined) k2 = k;
4 | var desc = Object.getOwnPropertyDescriptor(m, k);
5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6 | desc = { enumerable: true, get: function() { return m[k]; } };
7 | }
8 | Object.defineProperty(o, k2, desc);
9 | }) : (function(o, m, k, k2) {
10 | if (k2 === undefined) k2 = k;
11 | o[k2] = m[k];
12 | }));
13 | var __exportStar = (this && this.__exportStar) || function(m, exports) {
14 | for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15 | };
16 | Object.defineProperty(exports, "__esModule", { value: true });
17 | __exportStar(require("./streaming.v2.types"), exports);
18 | __exportStar(require("./tweet.v2.types"), exports);
19 | __exportStar(require("./tweet.definition.v2"), exports);
20 | __exportStar(require("./user.v2.types"), exports);
21 | __exportStar(require("./spaces.v2.types"), exports);
22 | __exportStar(require("./list.v2.types"), exports);
23 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/list.v2.types.d.ts:
--------------------------------------------------------------------------------
1 | import type { TypeOrArrayOf } from '../shared.types';
2 | import type { DataAndIncludeV2, DataMetaAndIncludeV2, DataV2 } from './shared.v2.types';
3 | import type { TTweetv2UserField } from './tweet.v2.types';
4 | import type { UserV2 } from './user.v2.types';
5 | export declare type TListV2Field = 'created_at' | 'follower_count' | 'member_count' | 'private' | 'description' | 'owner_id';
6 | export declare type TListV2Expansion = 'owner_id';
7 | export declare type TListV2Includes = {
8 | users?: UserV2[];
9 | };
10 | export interface ListV2 {
11 | id: string;
12 | name: string;
13 | created_at?: string;
14 | private?: boolean;
15 | follower_count?: number;
16 | member_count?: number;
17 | owner_id?: string;
18 | description?: string;
19 | }
20 | export interface ListCreateV2Params {
21 | name: string;
22 | description?: string;
23 | private?: boolean;
24 | }
25 | export interface GetListV2Params {
26 | expansions: TypeOrArrayOf | string;
27 | 'list.fields': TypeOrArrayOf | string;
28 | 'user.fields': TypeOrArrayOf | string;
29 | }
30 | export interface GetListTimelineV2Params extends Partial {
31 | max_results?: number;
32 | pagination_token?: string;
33 | }
34 | export declare type ListGetV2Result = DataAndIncludeV2;
35 | export declare type ListTimelineV2Result = DataMetaAndIncludeV2;
40 | export declare type ListCreateV2Result = DataV2<{
41 | id: string;
42 | name: string;
43 | }>;
44 | export declare type ListUpdateV2Params = Omit & {
45 | name?: string;
46 | };
47 | export declare type ListUpdateV2Result = DataV2<{
48 | updated: true;
49 | }>;
50 | export declare type ListDeleteV2Result = DataV2<{
51 | deleted: true;
52 | }>;
53 | export declare type ListMemberV2Result = DataV2<{
54 | is_member: boolean;
55 | }>;
56 | export declare type ListFollowV2Result = DataV2<{
57 | following: boolean;
58 | }>;
59 | export declare type ListPinV2Result = DataV2<{
60 | pinned: boolean;
61 | }>;
62 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/list.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/shared.v2.types.d.ts:
--------------------------------------------------------------------------------
1 | import type { InlineErrorV2 } from '../errors.types';
2 | export declare type MetaV2 = {
3 | meta: M;
4 | errors?: InlineErrorV2[];
5 | };
6 | export declare type DataV2 = {
7 | data: D;
8 | errors?: InlineErrorV2[];
9 | };
10 | export declare type IncludeV2 = {
11 | includes?: I;
12 | errors?: InlineErrorV2[];
13 | };
14 | export declare type DataAndMetaV2 = {
15 | data: D;
16 | meta: M;
17 | errors?: InlineErrorV2[];
18 | };
19 | export declare type DataAndIncludeV2 = {
20 | data: D;
21 | includes?: I;
22 | errors?: InlineErrorV2[];
23 | };
24 | export declare type DataMetaAndIncludeV2 = {
25 | data: D;
26 | meta: M;
27 | includes?: I;
28 | errors?: InlineErrorV2[];
29 | };
30 | export interface SentMeta {
31 | /** The time when the request body was returned. */
32 | sent: string;
33 | }
34 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/shared.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/spaces.v2.types.d.ts:
--------------------------------------------------------------------------------
1 | import type { TypeOrArrayOf } from '../shared.types';
2 | import type { DataAndIncludeV2, DataMetaAndIncludeV2 } from './shared.v2.types';
3 | import type { TTweetv2UserField } from './tweet.v2.types';
4 | import type { UsersV2Params, UsersV2Result, UserV2 } from './user.v2.types';
5 | export interface SpaceV2FieldsParams {
6 | expansions: TypeOrArrayOf | string;
7 | 'space.fields': TypeOrArrayOf | string;
8 | 'user.fields': TypeOrArrayOf | string;
9 | }
10 | export declare type TSpaceV2Expansion = 'invited_user_ids' | 'speaker_ids' | 'creator_id' | 'host_ids';
11 | export declare type TSpaceV2SpaceField = 'host_ids' | 'created_at' | 'creator_id' | 'id' | 'lang' | 'invited_user_ids' | 'participant_count' | 'speaker_ids' | 'started_at' | 'state' | 'title' | 'updated_at' | 'scheduled_start' | 'is_ticketed' | 'topic_ids' | 'ended_at';
12 | export declare type TSpaceV2State = 'live' | 'scheduled';
13 | export interface SpaceV2CreatorLookupParams extends SpaceV2FieldsParams {
14 | max_results?: number;
15 | }
16 | export interface SpaceV2SearchParams extends Partial {
17 | query: string;
18 | state: TSpaceV2State;
19 | max_results?: number;
20 | }
21 | export interface SpaceV2BuyersParams extends Partial {
22 | }
23 | declare type SpaceV2Includes = {
24 | users?: UserV2[];
25 | };
26 | export declare type SpaceV2SingleResult = DataAndIncludeV2;
27 | export declare type SpaceV2LookupResult = DataMetaAndIncludeV2;
30 | export declare type SpaceV2BuyersResult = UsersV2Result;
31 | export interface SpaceV2 {
32 | id: string;
33 | state: TSpaceV2State;
34 | created_at?: string;
35 | host_ids?: string[];
36 | lang?: string;
37 | is_ticketed?: boolean;
38 | invited_user_ids?: string[];
39 | participant_count?: number;
40 | scheduled_start?: string;
41 | speaker_ids?: string[];
42 | started_at?: string;
43 | title?: string;
44 | creator_id?: string;
45 | updated_at?: string;
46 | topic_ids?: string[];
47 | ended_at?: string;
48 | }
49 | export {};
50 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/spaces.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/streaming.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | // ---------------
3 | // -- Streaming --
4 | // ---------------
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/tweet.definition.v2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/tweet.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 | ;
4 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/types/v2/user.v2.types.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | Object.defineProperty(exports, "__esModule", { value: true });
3 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v1/media-helpers.v1.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | import * as fs from 'fs';
3 | import type { TUploadableMedia, TUploadTypeV1 } from '../types';
4 | import { EUploadMimeType } from '../types';
5 | export declare type TFileHandle = fs.promises.FileHandle | number | Buffer;
6 | export declare function readFileIntoBuffer(file: TUploadableMedia): Promise;
7 | export declare function getFileHandle(file: TUploadableMedia): number | Buffer | fs.promises.FileHandle | Promise;
8 | export declare function getFileSizeFromFileHandle(fileHandle: TFileHandle): Promise;
9 | export declare function getMimeType(file: TUploadableMedia, type?: TUploadTypeV1 | string, mimeType?: EUploadMimeType | string): string;
10 | export declare function getMediaCategoryByMime(name: string, target: 'tweet' | 'dm'): "TweetVideo" | "DmVideo" | "TweetGif" | "DmGif" | "Subtitles" | "TweetImage" | "DmImage";
11 | export declare function sleepSecs(seconds: number): Promise;
12 | export declare function readNextPartOf(file: TFileHandle, chunkLength: number, bufferOffset?: number, buffer?: Buffer): Promise<[Buffer, number]>;
13 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiv2LabsReadWrite from './client.v2.labs.write';
2 | /**
3 | * Twitter v2 labs client with all rights (read/write/DMs)
4 | */
5 | export declare class TwitterApiv2Labs extends TwitterApiv2LabsReadWrite {
6 | protected _prefix: string;
7 | /**
8 | * Get a client with read/write rights.
9 | */
10 | get readWrite(): TwitterApiv2LabsReadWrite;
11 | }
12 | export default TwitterApiv2Labs;
13 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.TwitterApiv2Labs = void 0;
7 | const globals_1 = require("../globals");
8 | const client_v2_labs_write_1 = __importDefault(require("./client.v2.labs.write"));
9 | /**
10 | * Twitter v2 labs client with all rights (read/write/DMs)
11 | */
12 | class TwitterApiv2Labs extends client_v2_labs_write_1.default {
13 | constructor() {
14 | super(...arguments);
15 | this._prefix = globals_1.API_V2_LABS_PREFIX;
16 | }
17 | /**
18 | * Get a client with read/write rights.
19 | */
20 | get readWrite() {
21 | return this;
22 | }
23 | }
24 | exports.TwitterApiv2Labs = TwitterApiv2Labs;
25 | exports.default = TwitterApiv2Labs;
26 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.read.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiSubClient from '../client.subclient';
2 | /**
3 | * Base Twitter v2 labs client with only read right.
4 | */
5 | export default class TwitterApiv2LabsReadOnly extends TwitterApiSubClient {
6 | protected _prefix: string;
7 | }
8 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.read.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const client_subclient_1 = __importDefault(require("../client.subclient"));
7 | const globals_1 = require("../globals");
8 | /**
9 | * Base Twitter v2 labs client with only read right.
10 | */
11 | class TwitterApiv2LabsReadOnly extends client_subclient_1.default {
12 | constructor() {
13 | super(...arguments);
14 | this._prefix = globals_1.API_V2_LABS_PREFIX;
15 | }
16 | }
17 | exports.default = TwitterApiv2LabsReadOnly;
18 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.write.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiv2LabsReadOnly from './client.v2.labs.read';
2 | /**
3 | * Base Twitter v2 labs client with read/write rights.
4 | */
5 | export default class TwitterApiv2LabsReadWrite extends TwitterApiv2LabsReadOnly {
6 | protected _prefix: string;
7 | /**
8 | * Get a client with only read rights.
9 | */
10 | get readOnly(): TwitterApiv2LabsReadOnly;
11 | }
12 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2-labs/client.v2.labs.write.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | const globals_1 = require("../globals");
7 | const client_v2_labs_read_1 = __importDefault(require("./client.v2.labs.read"));
8 | /**
9 | * Base Twitter v2 labs client with read/write rights.
10 | */
11 | class TwitterApiv2LabsReadWrite extends client_v2_labs_read_1.default {
12 | constructor() {
13 | super(...arguments);
14 | this._prefix = globals_1.API_V2_LABS_PREFIX;
15 | }
16 | /**
17 | * Get a client with only read rights.
18 | */
19 | get readOnly() {
20 | return this;
21 | }
22 | }
23 | exports.default = TwitterApiv2LabsReadWrite;
24 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2/client.v2.d.ts:
--------------------------------------------------------------------------------
1 | import TwitterApiv2ReadWrite from './client.v2.write';
2 | import TwitterApiv2Labs from '../v2-labs/client.v2.labs';
3 | /**
4 | * Twitter v2 client with all rights (read/write/DMs)
5 | */
6 | export declare class TwitterApiv2 extends TwitterApiv2ReadWrite {
7 | protected _prefix: string;
8 | protected _labs?: TwitterApiv2Labs;
9 | /**
10 | * Get a client with read/write rights.
11 | */
12 | get readWrite(): TwitterApiv2ReadWrite;
13 | /**
14 | * Get a client for v2 labs endpoints.
15 | */
16 | get labs(): TwitterApiv2Labs;
17 | }
18 | export default TwitterApiv2;
19 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/lib/v2/client.v2.js:
--------------------------------------------------------------------------------
1 | "use strict";
2 | var __importDefault = (this && this.__importDefault) || function (mod) {
3 | return (mod && mod.__esModule) ? mod : { "default": mod };
4 | };
5 | Object.defineProperty(exports, "__esModule", { value: true });
6 | exports.TwitterApiv2 = void 0;
7 | const globals_1 = require("../globals");
8 | const client_v2_write_1 = __importDefault(require("./client.v2.write"));
9 | const client_v2_labs_1 = __importDefault(require("../v2-labs/client.v2.labs"));
10 | /**
11 | * Twitter v2 client with all rights (read/write/DMs)
12 | */
13 | class TwitterApiv2 extends client_v2_write_1.default {
14 | constructor() {
15 | super(...arguments);
16 | this._prefix = globals_1.API_V2_PREFIX;
17 | }
18 | /* Sub-clients */
19 | /**
20 | * Get a client with read/write rights.
21 | */
22 | get readWrite() {
23 | return this;
24 | }
25 | /**
26 | * Get a client for v2 labs endpoints.
27 | */
28 | get labs() {
29 | if (this._labs)
30 | return this._labs;
31 | return this._labs = new client_v2_labs_1.default(this);
32 | }
33 | }
34 | exports.TwitterApiv2 = TwitterApiv2;
35 | exports.default = TwitterApiv2;
36 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/autotask-1/twitter-api-v2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "twitter-api-v2",
3 | "version": "1.12.9",
4 | "description": "Strongly typed, full-featured, light, versatile yet powerful Twitter API v1.1 and v2 client for Node.js.",
5 | "main": "lib/index.js",
6 | "types": "lib/index.d.ts",
7 | "keywords": [
8 | "twitter",
9 | "api",
10 | "typed",
11 | "types",
12 | "v2",
13 | "v1.1"
14 | ],
15 | "scripts": {
16 | "build": "tsc",
17 | "build-doc": "typedoc src/index.ts --out tsdocs",
18 | "lint": "eslint --ext \".ts\" --ignore-path .gitignore .",
19 | "mocha": "mocha -r ts-node/register --timeout 10000",
20 | "test": "npm run mocha 'test/**/*.test.ts'",
21 | "test-tweet": "npm run mocha 'test/tweet.*.test.ts'",
22 | "test-user": "npm run mocha 'test/user.*.test.ts'",
23 | "test-stream": "npm run mocha test/stream.test.ts",
24 | "test-media": "npm run mocha test/media-upload.test.ts",
25 | "test-auth": "npm run mocha test/auth.test.ts",
26 | "test-dm": "npm run mocha test/dm.*.test.ts",
27 | "test-list": "npm run mocha test/list.*.test.ts",
28 | "test-space": "npm run mocha test/space.v2.test.ts",
29 | "test-account": "npm run mocha test/account.*.test.ts",
30 | "test-plugin": "npm run mocha test/plugin.test.ts",
31 | "prepublish": "npm run build"
32 | },
33 | "repository": "github:plhery/node-twitter-api-v2",
34 | "author": "Paul-Louis Hery (https://twitter.com/plhery)",
35 | "license": "Apache-2.0",
36 | "files": [
37 | "lib"
38 | ],
39 | "devDependencies": {
40 | "@types/chai": "4.2.16",
41 | "@types/mocha": "9.0.0",
42 | "@types/node": "14.14.37",
43 | "@typescript-eslint/eslint-plugin": "4.28.5",
44 | "@typescript-eslint/parser": "4.28.5",
45 | "chai": "4.3.4",
46 | "dotenv": "8.2.0",
47 | "eslint": "7.31.0",
48 | "mocha": "10.0.0",
49 | "ts-node": "9.1.1",
50 | "typedoc": "0.22.15",
51 | "typescript": "4.2.4"
52 | },
53 | "bugs": {
54 | "url": "https://github.com/plhery/node-twitter-api/issues"
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/defender/governance_twitter_summary/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: governance_twitter_summary
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Governance Twitter Summary
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Public Variables
20 | # Compound Governance Address
21 | governanceAddress: "0xc0Da02939E1441F497fd74F78cE7Decb17B66529"
22 | # Private Variables pulled from external secrets.yml file
23 | appKey: ${self:custom.stackSecrets.appKey}
24 | appSecret: ${self:custom.stackSecrets.appSecret}
25 | accessToken: ${self:custom.stackSecrets.accessToken}
26 | accessSecret: ${self:custom.stackSecrets.accessSecret}
27 |
28 | defender:
29 | key: ${self:custom.config.keys.api}
30 | secret: ${self:custom.config.keys.secret}
31 |
32 | functions:
33 | autotask-1:
34 | name: ${self:custom.name} Serverless Autotask
35 | path: autotask-1
36 | trigger:
37 | type: schedule
38 | cron: "0 0 * * *" # Daily at 0000 UTC
39 | paused: false
40 | relayer: ${self:resources.Resources.relayers.relayer-1}
41 |
42 | resources:
43 | Resources:
44 | policies:
45 | policy-1:
46 | gas-price-cap: 1000
47 | whitelist-receivers:
48 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
49 | eip1559-pricing: true
50 |
51 | secrets:
52 | stack: ${self:custom.defenderSecrets}
53 |
54 | relayers:
55 | relayer-1:
56 | name: ${self:custom.name} Serverless Relay
57 | network: mainnet
58 | min-balance: 100000000000000000
59 |
60 | plugins:
61 | - defender-serverless
62 |
--------------------------------------------------------------------------------
/defender/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "defender-compound-monitoring",
3 | "version": "1.0.0",
4 | "description": "",
5 | "jest": {
6 | "testTimeout": 50000
7 | },
8 | "scripts": {
9 | "download": "node download.js",
10 | "deploy": "node deploy.js",
11 | "wipe": "node wipeAccount.js",
12 | "test": "jest"
13 | },
14 | "keywords": [],
15 | "author": "",
16 | "license": "ISC",
17 | "dependencies": {
18 | "axios": "0.21.2",
19 | "axios-retry": "3.1.9",
20 | "defender-autotask-client": "1.37.0-rc.2",
21 | "defender-kvstore-client": "1.37.0-rc.2",
22 | "defender-relay-client": "1.37.0-rc.2",
23 | "defender-sentinel-client": "1.37.0-rc.2",
24 | "defender-serverless": "1.0.3",
25 | "dotenv": "10.0.0",
26 | "ethers": "5.5.3",
27 | "fetch": "^1.1.0",
28 | "forta-agent": "0.1.6",
29 | "jszip": "3.10.0",
30 | "okhttp": "^1.1.0",
31 | "request": "^2.88.2",
32 | "serverless": "3.24.1"
33 | },
34 | "devDependencies": {
35 | "eslint": "8.9.0",
36 | "eslint-config-airbnb-base": "15.0.0",
37 | "eslint-plugin-import": "2.25.4",
38 | "jest": "28.1.0",
39 | "unirest": "^0.6.0"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/defender/proposal_110_automatoooor/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: proposal_110_automatoooor
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 |
14 | # Configure this section and rename secret-example.yml to secrets.yml
15 | name: Proposal 110 Automatoooor
16 |
17 | defender:
18 | key: ${self:custom.config.keys.api}
19 | secret: ${self:custom.config.keys.secret}
20 |
21 | functions:
22 | autotask-1:
23 | name: ${self:custom.name} Serverless Autotask
24 | path: autotask-1
25 | trigger:
26 | type: schedule
27 | frequency: 5
28 | paused: true
29 | relayer: ${self:resources.Resources.relayers.relayer-1}
30 |
31 | resources:
32 | Resources:
33 | policies:
34 | policy-1:
35 | gas-price-cap: 1000
36 | whitelist-receivers:
37 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
38 | eip1559-pricing: true
39 |
40 | secrets:
41 |
42 | relayers:
43 | relayer-1:
44 | name: ${self:custom.name} Serverless Relay
45 | network: mainnet
46 | min-balance: 100000000000000000
47 |
48 | plugins:
49 | - defender-serverless
50 |
--------------------------------------------------------------------------------
/defender/proposal_117_monitor_market_entered/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: proposal_117_monitor_market_entered
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Proposal 117 Monitor Market Entered
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Private variables pulled from external secrets.yml file
20 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
21 | slackWebhook: ${self:custom.stackSecrets.slackWebhook}
22 |
23 | defender:
24 | key: ${self:custom.config.keys.api}
25 | secret: ${self:custom.config.keys.secret}
26 |
27 | functions:
28 | autotask-1:
29 | name: ${self:custom.name} Serverless Autotask
30 | path: autotask-1
31 | trigger:
32 | type: schedule
33 | frequency: 525600000
34 | paused: true
35 | relayer: ${self:resources.Resources.relayers.relayer-1}
36 |
37 | resources:
38 | Resources:
39 | policies:
40 | policy-1:
41 | gas-price-cap: 1000
42 | whitelist-receivers:
43 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
44 | eip1559-pricing: true
45 |
46 | secrets:
47 | stack: ${self:custom.defenderSecrets}
48 |
49 | relayers:
50 | relayer-1:
51 | name: ${self:custom.name} Serverless Relay
52 | network: mainnet
53 | min-balance: 100000000000000000
54 |
55 | plugins:
56 | - defender-serverless
57 |
--------------------------------------------------------------------------------
/defender/proposal_117_monitor_mint/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: proposal_117_monitor_mint
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: Proposal 117 Monitor Mint
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Private variables pulled from external secrets.yml file
20 | discordWebhook: ${self:custom.stackSecrets.discordWebhook}
21 | slackWebhook: ${self:custom.stackSecrets.slackWebhook}
22 |
23 | defender:
24 | key: ${self:custom.config.keys.api}
25 | secret: ${self:custom.config.keys.secret}
26 |
27 | functions:
28 | autotask-1:
29 | name: ${self:custom.name} Serverless Autotask
30 | path: autotask-1
31 | trigger:
32 | type: schedule
33 | frequency: 525600000
34 | paused: true
35 | relayer: ${self:resources.Resources.relayers.relayer-1}
36 |
37 | resources:
38 | Resources:
39 | policies:
40 | policy-1:
41 | gas-price-cap: 1000
42 | whitelist-receivers:
43 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
44 | eip1559-pricing: true
45 |
46 | secrets:
47 | stack: ${self:custom.defenderSecrets}
48 |
49 | relayers:
50 | relayer-1:
51 | name: ${self:custom.name} Serverless Relay
52 | network: mainnet
53 | min-balance: 100000000000000000
54 |
55 | plugins:
56 | - defender-serverless
57 |
--------------------------------------------------------------------------------
/defender/secret-example.yml:
--------------------------------------------------------------------------------
1 | keys:
2 | api:
3 | secret:
4 |
5 | # WARNING: When deploying stacks, the secrets listed below will overwrite the ones in Defender.
6 | # If secrets do not need to be updated, comment them out in your serverless.yml files.
7 | # Note: The overwrite is limited to the stack that you are deploying.
8 | secrets:
9 | ctoken_monitor:
10 | discordWebhook: ""
11 | datadog_alerts_heat_map:
12 | datadogApiKey: ""
13 | datadog_alerts_heat_map_dev:
14 | datadogApiKey: ""
15 | datadog_forta_bot_alerts:
16 | datadogApiKey: ""
17 | datadog_forta_bot_alerts_dev:
18 | datadogApiKey: ""
19 | datadog_forta_detection_bot_health:
20 | datadogApiKey: ""
21 | forta_ctoken:
22 | discordWebhook: ""
23 | forta_distribution:
24 | discordWebhook: ""
25 | forta_governance:
26 | discordWebhook: ""
27 | forta_large_borrows_governance:
28 | discordWebhook: ""
29 | forta_large_delegations:
30 | discordWebhook: ""
31 | forta_low_liquidity:
32 | discordWebhook: ""
33 | forta_multi_sig:
34 | discordWebhook: ""
35 | forta_oracle_price:
36 | discordWebhook: ""
37 | forta_underlying_asset:
38 | discordWebhook: ""
39 | forta_v2_liquidation_monitor_dev:
40 | discordWebhook: ""
41 | forta_v3_liquidation_monitor_dev:
42 | discordWebhook: ""
43 | governance_discord_alert:
44 | discordWebhook: ""
45 | governance_discord_summary:
46 | discordWebhook: ""
47 | governance_twitter_summary:
48 | # Twitter Keys
49 | # Consumer Keys from an elevated developer account
50 | appKey: ""
51 | appSecret: ""
52 | # Authentication Tokens (must have write permissions)
53 | accessToken: ""
54 | accessSecret: ""
55 | proposal_117_monitor_market_entered:
56 | discordWebhook: ""
57 | slackWebhook: ""
58 | proposal_117_monitor_mint:
59 | discordWebhook: ""
60 | slackWebhook: ""
61 |
--------------------------------------------------------------------------------
/defender/template_autotask_relay/autotask-1/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenZeppelin/compound-monitoring/ad6f30e676b23219b4b26ff547958022e7fee8e2/defender/template_autotask_relay/autotask-1/index.js
--------------------------------------------------------------------------------
/defender/template_autotask_relay/serverless.yml:
--------------------------------------------------------------------------------
1 | service: generated-service
2 | configValidationMode: error
3 | frameworkVersion: "3"
4 |
5 | provider:
6 | name: defender
7 | stage: dev
8 | stackName: CHANGE_ME
9 | ssot: false
10 |
11 | custom:
12 | config: ${file(../secrets.yml)}
13 | stackSecrets: ${self:custom.config.secrets.${self:provider.stackName}}
14 |
15 | # Configure this section and rename secret-example.yml to secrets.yml
16 | name: CHANGE_ME
17 | # Comment out any secret that you do not want to be overwritten in Defender
18 | defenderSecrets:
19 | # Public Variables
20 | publicVariable: "Nothing Sensitive"
21 | # Private variables pulled from external secrets.yml file
22 | privateVariable: ${self:custom.stackSecrets.privateVariable}
23 |
24 | defender:
25 | key: ${self:custom.config.keys.api}
26 | secret: ${self:custom.config.keys.secret}
27 |
28 | functions:
29 | autotask-1:
30 | name: ${self:custom.name} Serverless Autotask
31 | path: autotask-1
32 | trigger:
33 | type: schedule
34 | cron: "0 * * * *"
35 | paused: false
36 | relayer: ${self:resources.Resources.relayers.relayer-1}
37 |
38 | resources:
39 | Resources:
40 | policies:
41 | policy-1:
42 | gas-price-cap: 1000
43 | whitelist-receivers:
44 | - "0x0f06aB75c7DD497981b75CD82F6566e3a5CAd8f2"
45 | eip1559-pricing: true
46 |
47 | secrets:
48 | stack: ${self:custom.defenderSecrets}
49 |
50 | relayers:
51 | relayer-1:
52 | name: ${self:custom.name} Serverless Relay
53 | network: mainnet
54 | min-balance: 100000000000000000
55 |
56 | plugins:
57 | - defender-serverless
58 |
--------------------------------------------------------------------------------
/defender/template_autotask_relay_forta/autotask-1/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenZeppelin/compound-monitoring/ad6f30e676b23219b4b26ff547958022e7fee8e2/defender/template_autotask_relay_forta/autotask-1/index.js
--------------------------------------------------------------------------------
/defender/template_autotask_relay_sentinel/abis/sentinel-1.json.abi:
--------------------------------------------------------------------------------
1 | # Delete this and paste you ABI JSON in here
--------------------------------------------------------------------------------
/defender/template_autotask_relay_sentinel/autotask-1/index.js:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenZeppelin/compound-monitoring/ad6f30e676b23219b4b26ff547958022e7fee8e2/defender/template_autotask_relay_sentinel/autotask-1/index.js
--------------------------------------------------------------------------------
/distribution/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/distribution/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/distribution/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/distribution/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/distribution/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Large Distribution Event Forta Bot
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/distribution/README.md:
--------------------------------------------------------------------------------
1 | # Compound Distribution Monitor
2 |
3 | ## Description
4 |
5 | This bot monitors the Compound Finance Comptroller contract for distribution events and
6 | if an amount of COMP is distributed that exceeds a configurable maximum amount an alert is generated.
7 |
8 | ## Alerts
9 |
10 |
11 | - AE-COMP-EXCEEDS-SANE-DISTRIBUTION-EVENT
12 | - Type is always set to `Info`
13 | - Severity is always set to `Info`
14 | - Metadata field contains:
15 | - Amount of COMP distributed
16 | - COMP index
17 |
18 | ## Testing
19 |
20 | The following transactions can be used to test the operation of this bot.
21 |
22 | 0xf4bfef1655f2092cf062c008153a5be66069b2b1fedcacbf4037c1f3cc8a9f45
23 | 0xbc246c878326f2c128462d08a0b74048b1dbee733adde8863f569c949c06422a
24 |
25 | To run, use:
26 | `npm run tx {transactionHash}`
--------------------------------------------------------------------------------
/distribution/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "contracts": {
6 | "Comptroller": {
7 | "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
8 | "abiFile": "Comptroller.json"
9 | },
10 | "CompoundToken": {
11 | "address": "0xc00e94cb662c3520282e6f5717214004a7f26888"
12 | }
13 | },
14 | "maximumSaneDistributionAmount": "1000"
15 | }
16 |
--------------------------------------------------------------------------------
/distribution/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-distribution-bugs",
3 | "version": "0.0.4",
4 | "description": "This Bot monitors Compound distribution bugs.",
5 | "scripts": {
6 | "start": "npm run start:dev",
7 | "start:prod": "forta-agent run --prod",
8 | "tx": "forta-agent run --tx",
9 | "block": "forta-agent run --block",
10 | "range": "forta-agent run --range",
11 | "file": "forta-agent run --file",
12 | "publish": "forta-agent publish",
13 | "push": "forta-agent push",
14 | "disable": "forta-agent disable",
15 | "enable": "forta-agent enable",
16 | "keyfile": "forta-agent keyfile",
17 | "test": "jest"
18 | },
19 | "dependencies": {
20 | "bignumber.js": "9.0.2",
21 | "forta-agent": "0.1.4"
22 | },
23 | "devDependencies": {
24 | "eslint": "8.16.0",
25 | "eslint-config-airbnb-base": "15.0.0",
26 | "eslint-plugin-import": "2.26.0",
27 | "jest": "28.1.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/distribution/src/utils.js:
--------------------------------------------------------------------------------
1 | function getAbi(abiName) {
2 | // eslint-disable-next-line global-require,import/no-dynamic-require
3 | const { abi } = require(`../abi/${abiName}`);
4 | return abi;
5 | }
6 |
7 | module.exports = {
8 | getAbi,
9 | };
10 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/.gitignore:
--------------------------------------------------------------------------------
1 | config.json
2 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | # if using obfuscated code from build stage:
13 | # COPY --from=builder /app/dist ./src
14 | # else if using unobfuscated code:
15 | LABEL "network.forta.settings.agent-logs.enable"="true"
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/abi/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenZeppelin/compound-monitoring/ad6f30e676b23219b4b26ff547958022e7fee8e2/gnosis-safe-deploy/abi/.gitkeep
--------------------------------------------------------------------------------
/gnosis-safe-deploy/abi/AgentRegistryProxy.json:
--------------------------------------------------------------------------------
1 | {
2 | "abi": [
3 | {
4 | "inputs": [
5 | {
6 | "internalType": "address",
7 | "name": "_logic",
8 | "type": "address"
9 | },
10 | {
11 | "internalType": "bytes",
12 | "name": "_data",
13 | "type": "bytes"
14 | }
15 | ],
16 | "stateMutability": "payable",
17 | "type": "constructor"
18 | },
19 | {
20 | "anonymous": false,
21 | "inputs": [
22 | {
23 | "indexed": false,
24 | "internalType": "address",
25 | "name": "previousAdmin",
26 | "type": "address"
27 | },
28 | {
29 | "indexed": false,
30 | "internalType": "address",
31 | "name": "newAdmin",
32 | "type": "address"
33 | }
34 | ],
35 | "name": "AdminChanged",
36 | "type": "event"
37 | },
38 | {
39 | "anonymous": false,
40 | "inputs": [
41 | {
42 | "indexed": true,
43 | "internalType": "address",
44 | "name": "beacon",
45 | "type": "address"
46 | }
47 | ],
48 | "name": "BeaconUpgraded",
49 | "type": "event"
50 | },
51 | {
52 | "anonymous": false,
53 | "inputs": [
54 | {
55 | "indexed": true,
56 | "internalType": "address",
57 | "name": "implementation",
58 | "type": "address"
59 | }
60 | ],
61 | "name": "Upgraded",
62 | "type": "event"
63 | },
64 | {
65 | "stateMutability": "payable",
66 | "type": "fallback"
67 | },
68 | {
69 | "stateMutability": "payable",
70 | "type": "receive"
71 | }
72 | ]
73 | }
74 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Forta",
4 | "protocolAbbreviation": "FORTA",
5 | "contracts": {
6 | "AgentRegistryProxy": {
7 | "address": "0x61447385B019187daa48e91c55c02AF1F1f3F863",
8 | "abiFile": "AgentRegistryProxy.json",
9 | "proxy": "AgentRegistry"
10 | },
11 | "AgentRegistry": {
12 | "address": "0xA8A26969f7Be888D020B595340c490c02ec445dD",
13 | "abiFile": "AgentRegistry.json",
14 | "events": {
15 | "AccessManagerUpdated": {
16 | "type": "Info",
17 | "severity": "Info"
18 | },
19 | "AdminChanged": {
20 | "type": "Info",
21 | "severity": "Info"
22 | },
23 | "AgentCommitted": {
24 | "type": "Info",
25 | "severity": "Info"
26 | },
27 | "AgentEnabled": {
28 | "type": "Info",
29 | "severity": "Info"
30 | },
31 | "AgentUpdated": {
32 | "type": "Info",
33 | "severity": "Info"
34 | },
35 | "Approval": {
36 | "type": "Info",
37 | "severity": "Info"
38 | },
39 | "ApprovalForAll": {
40 | "type": "Info",
41 | "severity": "Info"
42 | },
43 | "BeaconUpgraded": {
44 | "type": "Info",
45 | "severity": "Info"
46 | },
47 | "RouterUpdated": {
48 | "type": "Info",
49 | "severity": "Info"
50 | },
51 | "FrontRunningDelaySet": {
52 | "type": "Info",
53 | "severity": "Info"
54 | },
55 | "StakeControllerUpdated": {
56 | "type": "Info",
57 | "severity": "Info"
58 | },
59 | "StakeThresholdChanged": {
60 | "type": "Info",
61 | "severity": "Info"
62 | },
63 | "Transfer": {
64 | "type": "Info",
65 | "severity": "Info"
66 | },
67 | "Upgraded": {
68 | "type": "Info",
69 | "severity": "Info"
70 | }
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/config.json.example:
--------------------------------------------------------------------------------
1 | {
2 | "safeAccountConfig": {
3 | "owners": [
4 | "0xADDRESSOWNERONE",
5 | "0xADDRESSOWNERTWO",
6 | "0xADDRESSOWNERTHREE"
7 | ],
8 | "threshold": 2
9 | },
10 | "safeVersion": "1.3.0"
11 | }
12 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "gnosis-safe-deploy",
3 | "version": "1.0.0",
4 | "description": "Example deployment of a Forta Bot using a Gnosis Safe smart contract.",
5 | "chainIds": [
6 | 137
7 | ],
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "test": "jest",
16 | "deploy": "node scripts/deploySafe.js",
17 | "propose": "node scripts/proposeFortaBot.js",
18 | "approve": "node scripts/approveTransaction.js",
19 | "execute": "node scripts/executeTransaction.js",
20 | "reject": "node scripts/rejectTransaction.js"
21 | },
22 | "dependencies": {
23 | "@gnosis.pm/safe-core-sdk": "2.0.0",
24 | "@gnosis.pm/safe-ethers-lib": "1.1.0",
25 | "@gnosis.pm/safe-service-client": "1.1.2",
26 | "bignumber.js": "9.0.2",
27 | "dotenv": "16.0.0",
28 | "ethers": "5.6.2",
29 | "forta-agent": "0.1.3"
30 | },
31 | "devDependencies": {
32 | "eslint": "8.16.0",
33 | "eslint-config-airbnb-base": "15.0.0",
34 | "eslint-plugin-import": "2.26.0",
35 | "jest": "28.1.0"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/gnosis-safe-deploy/scripts/approveTransaction.js:
--------------------------------------------------------------------------------
1 | const EthersAdapter = require('@gnosis.pm/safe-ethers-lib').default;
2 | const Safe = require('@gnosis.pm/safe-core-sdk').default;
3 | const SafeServiceClient = require('@gnosis.pm/safe-service-client').default;
4 | const ethers = require('ethers');
5 |
6 | // load values from the .env file
7 | require('dotenv').config();
8 |
9 | // load the Gnosis Safe proxy contract address
10 | const polygonSafeAddress = process.env.POLYGON_SAFE_ADDRESS;
11 |
12 | // load the JSON-RPC endpoint URL
13 | const polygonEndpoint = process.env.POLYGON_ENDPOINT;
14 |
15 | // load the private key for the account that will be signing the transaction
16 | const ownerPrivateKey = process.env.APPROVER_PRIVATE_KEY;
17 |
18 | // load the transaction hash to approve
19 | const safeTxHash = process.env.SAFE_TX_HASH;
20 |
21 | async function main() {
22 | // create an ethers.js provider
23 | const provider = new ethers.providers.JsonRpcProvider(polygonEndpoint);
24 |
25 | // create an ethers.js wallet (signer) and connect it to the provider
26 | const safeWallet = new ethers.Wallet(ownerPrivateKey, provider);
27 | const signer = safeWallet.connect(provider);
28 |
29 | // create an ethAdapter Object
30 | const ethAdapter = new EthersAdapter({
31 | ethers,
32 | signer,
33 | provider,
34 | });
35 |
36 | // initialize the Safe Service Client
37 | const transactionServiceUrl = 'https://safe-transaction.polygon.gnosis.io/';
38 | const safeService = new SafeServiceClient({
39 | txServiceUrl: transactionServiceUrl,
40 | ethAdapter,
41 | });
42 |
43 | console.log('Getting deployed Gnosis Safe Contract');
44 | const safeSdk = await Safe.create({
45 | ethAdapter,
46 | safeAddress: polygonSafeAddress,
47 | });
48 |
49 | // sign the transaction hash and provide confirmation to the Safe Service Client
50 | const signature = await safeSdk.signTransactionHash(safeTxHash);
51 | await safeService.confirmTransaction(safeTxHash, signature.data);
52 | console.log('Transaction confirmed');
53 | }
54 |
55 | main()
56 | .then(() => process.exit(0))
57 | .catch((error) => {
58 | console.error(error);
59 | process.exit(1);
60 | });
61 |
--------------------------------------------------------------------------------
/governance/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/governance/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/governance/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/governance/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/governance/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Protocol Monitoring
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/governance/abi/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/OpenZeppelin/compound-monitoring/ad6f30e676b23219b4b26ff547958022e7fee8e2/governance/abi/.gitkeep
--------------------------------------------------------------------------------
/governance/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "governance": {
6 | "address": "0xc0Da02939E1441F497fd74F78cE7Decb17B66529",
7 | "abiFile": "GovernorBravo.json",
8 | "events": [
9 | "ProposalCanceled",
10 | "ProposalCreated",
11 | "ProposalExecuted",
12 | "ProposalQueued",
13 | "ProposalThresholdSet",
14 | "VoteCast"
15 | ]
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/governance/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-governance-events",
3 | "version": "0.0.5",
4 | "description": "This Bot monitors events emitted from the Compound GovernorBravo contract.",
5 | "scripts": {
6 | "start": "npm run start:dev",
7 | "start:prod": "forta-agent run --prod",
8 | "tx": "forta-agent run --tx",
9 | "block": "forta-agent run --block",
10 | "range": "forta-agent run --range",
11 | "file": "forta-agent run --file",
12 | "publish": "forta-agent publish",
13 | "push": "forta-agent push",
14 | "disable": "forta-agent disable",
15 | "enable": "forta-agent enable",
16 | "keyfile": "forta-agent keyfile",
17 | "test": "jest"
18 | },
19 | "dependencies": {
20 | "axios": "0.27.2",
21 | "forta-agent": "0.0.39"
22 | },
23 | "devDependencies": {
24 | "eslint": "8.16.0",
25 | "eslint-config-airbnb-base": "15.0.0",
26 | "eslint-plugin-import": "2.26.0",
27 | "jest": "^29.5.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/large-borrows-governance/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/large-borrows-governance/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/large-borrows-governance/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/large-borrows-governance/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./abi ./abi
17 | COPY ./src ./src
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/large-borrows-governance/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Large Borrows Governance Forta Bot
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/large-borrows-governance/README.md:
--------------------------------------------------------------------------------
1 | # Compound Large Borrows Governance Bot
2 |
3 | ## Description
4 |
5 | This bot monitors all borrow events of COMP to see if the borrower address has accrued enough COMP
6 | to pass significant governance thresholds. This can be an early indication of governance attacks.
7 |
8 | ## Alerts
9 |
10 |
11 | - AE-COMP-GOVERNANCE-THRESHOLD
12 | - Type is always set to `Suspicious`
13 | - Severity is set to `Medium` for the proposal threshold alert and `High` for the voting quorum
14 | threshold alert
15 | - Metadata field contains:
16 | - Borrower address
17 | - Governance threshold level that has been surpassed, which can be either `proposal` or `votingQuorum`
18 | - The minimum amount of COMP needed to pass the respective governance threshold
19 | - The amount of COMP owned by the borrower address
20 |
21 | ## Testing
22 |
23 | Run unit tests:
24 | ```console
25 | npm test
26 | ```
--------------------------------------------------------------------------------
/large-borrows-governance/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "COMPAddress": "0xc00e94Cb662C3520282E6f5717214004A7f26888",
6 | "cCOMPAddress": "0x70e36f6BF80a52b3B46b3aF8e106CC0ed743E8e4",
7 | "governorAddress": "0xc0Da02939E1441F497fd74F78cE7Decb17B66529",
8 | "borrowLevels": {
9 | "proposal": {
10 | "type": "Suspicious",
11 | "severity": "Medium"
12 | },
13 | "votingQuorum": {
14 | "type": "Suspicious",
15 | "severity": "High"
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/large-borrows-governance/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-large-borrows-governance",
3 | "version": "0.0.3",
4 | "chainIds": [
5 | 1
6 | ],
7 | "description": "This Bot monitors all borrow events of COMP to see if an address has borrowed has enough COMP to influence governance.",
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "publish": "forta-agent publish",
16 | "push": "forta-agent push",
17 | "disable": "forta-agent disable",
18 | "enable": "forta-agent enable",
19 | "keyfile": "forta-agent keyfile",
20 | "test": "jest"
21 | },
22 | "dependencies": {
23 | "bignumber.js": "9.0.2",
24 | "forta-agent": "0.0.39"
25 | },
26 | "devDependencies": {
27 | "eslint": "8.16.0",
28 | "eslint-config-airbnb-base": "15.0.0",
29 | "eslint-plugin-import": "2.26.0",
30 | "jest": "28.1.0"
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/liquidation-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/liquidation-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | 'no-param-reassign': 'off',
22 | },
23 | },
24 | ],
25 | };
26 |
--------------------------------------------------------------------------------
/liquidation-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 | .env
5 |
--------------------------------------------------------------------------------
/liquidation-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | LABEL "network.forta.settings.agent-logs.enable"="true"
12 | WORKDIR /app
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY ./bot-config.json ./bot-config.json
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/liquidation-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "liquidationMonitor": {
6 | "comptrollerAddress": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
7 | "comptrollerABI": "Comptroller.json",
8 | "oneInchAddress": "0x07D91f5fb9Bf7798734C3f606dB065549F6893bb",
9 | "oneInchABI": "OneInch.json",
10 | "triggerLevels": {
11 | "maximumHealth": 100,
12 | "minimumBorrowInETH": 0.1,
13 | "minimumLiquidationInUSD": 400,
14 | "lowHealthThreshold": 1.03
15 | },
16 | "alert": {
17 | "type": "Info",
18 | "severity": "Info"
19 | }
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/liquidation-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-compound-finance-liquidation-monitor",
3 | "version": "0.0.2",
4 | "description": "Forta Bot that monitors Compound Finance for positions that can be liquidated",
5 | "chainIds": [
6 | 1
7 | ],
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "publish": "forta-agent publish",
16 | "push": "forta-agent push",
17 | "disable": "forta-agent disable",
18 | "enable": "forta-agent enable",
19 | "keyfile": "forta-agent keyfile",
20 | "test": "jest"
21 | },
22 | "dependencies": {
23 | "axios": "0.27.2",
24 | "bignumber.js": "9.0.2",
25 | "forta-agent": "0.1.3"
26 | },
27 | "devDependencies": {
28 | "eslint": "8.16.0",
29 | "eslint-config-airbnb-base": "15.0.0",
30 | "eslint-plugin-import": "2.26.0",
31 | "jest": "28.1.0"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/liquidation-monitor/src/utils.js:
--------------------------------------------------------------------------------
1 | const axios = require('axios');
2 |
3 | function getAbi(abiName) {
4 | // eslint-disable-next-line global-require,import/no-dynamic-require
5 | const { abi } = require(`../abi/${abiName}`);
6 | return abi;
7 | }
8 |
9 | // Helper for Compound API
10 | function buildJsonRequest(maxHealth, minBorrow, pageNumber, pageSize) {
11 | const jsonRequest = {
12 | addresses: [], // returns all accounts if empty or not included
13 | block_number: 0, // returns latest if given 0
14 | max_health: { value: maxHealth },
15 | min_borrow_value_in_eth: { value: minBorrow },
16 | page_number: pageNumber,
17 | page_size: pageSize,
18 | };
19 | return jsonRequest;
20 | }
21 |
22 | async function callCompoundAPI(jsonRequest) {
23 | try {
24 | const apiURL = 'https://api.compound.finance/api/v2/account';
25 | const resp = await axios.post(apiURL, jsonRequest);
26 | return resp.data;
27 | } catch (err) {
28 | // Handle Error Here
29 | return null;
30 | }
31 | }
32 |
33 | module.exports = {
34 | getAbi,
35 | callCompoundAPI,
36 | buildJsonRequest,
37 | };
38 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Protocol Monitoring
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/README.md:
--------------------------------------------------------------------------------
1 | # Compound Low Liquidity Market Attack Monitor
2 |
3 | ## Description
4 |
5 | This bot monitors Compound Finance cToken contracts that have low liquidity for potential
6 | market attacks where a malicious actor mints cTokens and then transfers additional tokens in
7 | order to unbalance the contract such that subsequent mints will not yield cTokens.
8 |
9 | ## Alerts
10 |
11 |
12 | - AE-COMP-MARKET-ATTACK-EVENT
13 | - Type is always set to `Suspicious`
14 | - Severity is always set to `Info`
15 | - Metadata field contains:
16 | - COMP Token symbol
17 | - COMP Token Address
18 | - Minted Amount
19 | - Minted COMP Tokens
20 | - Malicious Address
21 | - Malicious Transfer Amount
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "contracts": {
6 | "Comptroller": {
7 | "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
8 | "abiFile": "Comptroller.json"
9 | },
10 | "CompToken": {
11 | "abiFile": "cErc20.json"
12 | }
13 | },
14 | "excludeAddresses": ["0x4ddc2d193948926d02f9b1fe9e1daa0718270ed5"]
15 | }
16 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-comp-market-attack-events",
3 | "version": "0.0.5",
4 | "description": "This Bot monitors Compound Finance cToken contracts for market attack events.",
5 | "scripts": {
6 | "start": "npm run start:dev",
7 | "start:prod": "forta-agent run --prod",
8 | "tx": "forta-agent run --tx",
9 | "block": "forta-agent run --block",
10 | "range": "forta-agent run --range",
11 | "file": "forta-agent run --file",
12 | "publish": "forta-agent publish",
13 | "push": "forta-agent push",
14 | "disable": "forta-agent disable",
15 | "enable": "forta-agent enable",
16 | "keyfile": "forta-agent keyfile",
17 | "test": "jest"
18 | },
19 | "dependencies": {
20 | "bignumber.js": "9.0.2",
21 | "forta-agent": "0.1.6"
22 | },
23 | "devDependencies": {
24 | "eslint": "8.16.0",
25 | "eslint-config-airbnb-base": "15.0.0",
26 | "eslint-plugin-import": "2.26.0",
27 | "jest": "28.1.0"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/low-liquidity-market-attack-monitor/src/utils.js:
--------------------------------------------------------------------------------
1 | const { ethers } = require('forta-agent');
2 |
3 | function getAbi(abiName) {
4 | // eslint-disable-next-line global-require,import/no-dynamic-require
5 | const { abi } = require(`../abi/${abiName}`);
6 | return abi;
7 | }
8 |
9 | // helper function that identifies key strings in the args array obtained from log parsing
10 | // these key-value pairs will be added to the metadata as event args
11 | // all values are converted to strings so that BigNumbers are readable
12 | function extractEventArgs(args) {
13 | const eventArgs = {};
14 | Object.keys(args).forEach((key) => {
15 | if (Number.isNaN(Number(key))) {
16 | eventArgs[key] = args[key].toString();
17 | }
18 | });
19 | return eventArgs;
20 | }
21 |
22 | function isAddress(valueString) {
23 | return ethers.utils.isHexString(valueString, 20);
24 | }
25 |
26 | module.exports = {
27 | getAbi,
28 | extractEventArgs,
29 | isAddress,
30 | };
31 |
--------------------------------------------------------------------------------
/multisig-transactions-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
--------------------------------------------------------------------------------
/multisig-transactions-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-plusplus': 'off',
21 | 'no-continue': 'off',
22 | 'no-console': 'off',
23 | },
24 | },
25 | ],
26 | };
27 |
--------------------------------------------------------------------------------
/multisig-transactions-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/multisig-transactions-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | WORKDIR /app
12 | LABEL "network.forta.settings.agent-logs.enable"="true"
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./src ./src
17 | COPY ./abi ./abi
18 | COPY bot-config.json ./
19 | COPY package*.json ./
20 | RUN npm ci --production
21 | CMD [ "npm", "run", "start:prod" ]
22 |
--------------------------------------------------------------------------------
/multisig-transactions-monitor/bot-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "developerAbbreviation": "AE",
3 | "protocolName": "Compound",
4 | "protocolAbbreviation": "COMP",
5 | "contracts": {
6 | "multisig": {
7 | "address": "0xbbf3f1421D886E9b2c5D716B5192aC998af2012c",
8 | "abiFile": "GnosisSafe.json",
9 | "events": [
10 | "AddedOwner",
11 | "ApproveHash",
12 | "ChangedMasterCopy",
13 | "ChangedThreshold",
14 | "DisabledModule",
15 | "EnabledModule",
16 | "ExecutionFailure",
17 | "ExecutionFromModuleFailure",
18 | "ExecutionFromModuleSuccess",
19 | "ExecutionSuccess",
20 | "RemovedOwner",
21 | "SignMsg"
22 | ]
23 | },
24 | "governance": {
25 | "address": "0xc0Da02939E1441F497fd74F78cE7Decb17B66529",
26 | "abiFile": "GovernorBravo.json",
27 | "events": [
28 | "ProposalCreated",
29 | "ProposalExecuted",
30 | "ProposalCanceled",
31 | "VoteCast",
32 | "ProposalThresholdSet",
33 | "NewAdmin"
34 | ]
35 | },
36 | "comptroller": {
37 | "address": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
38 | "abiFile": "Comptroller.json",
39 | "protocolVersion": "2",
40 | "events": [
41 | "NewPauseGuardian",
42 | "ActionPaused",
43 | "NewBorrowCap",
44 | "NewBorrowCapGuardian"
45 | ]
46 | },
47 | "comet_usdc": {
48 | "address": "0xc3d688B66703497DAA19211EEdff47f25384cdc3",
49 | "abiFile": "Comet.json",
50 | "protocolVersion": "3",
51 | "events": ["PauseAction"]
52 | }
53 | },
54 | "v2Addresses": {
55 | "comptroller": "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B",
56 | "comp": "0xc00e94Cb662C3520282E6f5717214004A7f26888",
57 | "timelock": "0x6d903f6003cca6255d85cca4d3b5e5146dc33925"
58 | },
59 | "v3Addresses": {
60 | "comptrollerV2": "0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b",
61 | "comet": "0xc3d688B66703497DAA19211EEdff47f25384cdc3",
62 | "configurator": "0x316f9708bB98af7dA9c68C1C3b5e79039cD336E3",
63 | "rewards": "0x1B0e765F6224C21223AeA2af16c1C46E38885a40",
64 | "bulker": "0x74a81F84268744a40FEBc48f8b812a1f188D80C3"
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/multisig-transactions-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-compound-finance-multisig-transaction-bot",
3 | "version": "0.0.6",
4 | "description": "Forta Bot monitoring transactions for the Compound Finance Community Multisig Contract",
5 | "chainIds": [
6 | 1
7 | ],
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "publish": "forta-agent publish",
16 | "push": "forta-agent push",
17 | "disable": "forta-agent disable",
18 | "enable": "forta-agent enable",
19 | "keyfile": "forta-agent keyfile",
20 | "test": "jest"
21 | },
22 | "dependencies": {
23 | "forta-agent": "0.1.1"
24 | },
25 | "devDependencies": {
26 | "eslint": "8.16.0",
27 | "eslint-config-airbnb-base": "15.0.0",
28 | "eslint-plugin-import": "2.26.0",
29 | "jest": "28.1.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/oracle-price-monitor/.dockerignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | dist
3 | forta.config.json
4 |
--------------------------------------------------------------------------------
/oracle-price-monitor/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | env: {
3 | commonjs: true,
4 | es2021: true,
5 | jest: true,
6 | node: true,
7 | },
8 | extends: [
9 | 'airbnb-base',
10 | ],
11 | parserOptions: {
12 | ecmaVersion: 12,
13 | },
14 | rules: {
15 | },
16 | overrides: [
17 | {
18 | files: '*',
19 | rules: {
20 | 'no-console': 'off',
21 | },
22 | },
23 | ],
24 | };
25 |
--------------------------------------------------------------------------------
/oracle-price-monitor/.gitignore:
--------------------------------------------------------------------------------
1 | *.swp
2 | .env
3 | forta.config.json
4 | node_modules
5 | dist
6 |
--------------------------------------------------------------------------------
/oracle-price-monitor/Dockerfile:
--------------------------------------------------------------------------------
1 | # Build stage: obfuscate Javascript (optional)
2 | # FROM node:14.15.5-alpine as builder
3 | # WORKDIR /app
4 | # COPY . .
5 | # RUN npm install -g javascript-obfuscator
6 | # RUN javascript-obfuscator ./src --output ./dist --split-strings true --split-strings-chunk-length 3
7 |
8 | # Final stage: install production dependencies
9 | FROM node:12-alpine
10 | ENV NODE_ENV=production
11 | LABEL "network.forta.settings.agent-logs.enable"="true"
12 | WORKDIR /app
13 | # if using obfuscated code from build stage:
14 | # COPY --from=builder /app/dist ./src
15 | # else if using unobfuscated code:
16 | COPY ./abi ./abi
17 | COPY ./src ./src
18 | COPY package*.json ./
19 | RUN npm ci --production
20 | CMD [ "npm", "run", "start:prod" ]
21 |
--------------------------------------------------------------------------------
/oracle-price-monitor/LICENSE:
--------------------------------------------------------------------------------
1 | Compound Oracle Price Monitor Forta Bot
2 |
3 | Copyright (C) 2022 Arbitrary Execution
4 |
5 | This program is free software: you can redistribute it and/or modify
6 | it under the terms of the GNU Affero General Public License as published by
7 | the Free Software Foundation, either version 3 of the License, or
8 | (at your option) any later version.
9 |
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | GNU Affero General Public License for more details.
14 |
15 | You should have received a copy of the GNU Affero General Public License
16 | along with this program. If not, see .
17 |
--------------------------------------------------------------------------------
/oracle-price-monitor/README.md:
--------------------------------------------------------------------------------
1 | # Compound Oracle Price Monitor Bot
2 |
3 | ## Description
4 |
5 | This bot monitors the UniswapAnchoredProxy contract for PriceGuarded events which indicate that
6 | a ValidatorProxy reported a cToken price that is outside of the Uniswap V3 TWAP percent threshold.
7 |
8 | ## Alerts
9 |
10 |
11 | - AE-COMP-CTOKEN-PRICE-REJECTED
12 | - Type is always set to `Degraded`
13 | - Severity is always set to `High`
14 | - Metadata field contains:
15 | - Address of the affected cToken
16 | - Address of the underlying token
17 | - Address of the respective ValidatorProxy contract
18 | - Anchor Price (current price)
19 | - Reporter Price (failed price)
20 |
21 | ## Testing
22 |
23 | Running against a real transaction:
24 | ```console
25 | npx forta-agent run --tx 0xe9456ccee1b1764dfe80291f3b894a29f0789f20f995de7d88ff186e8cafe55c
26 | ```
27 |
28 | Run unit tests:
29 | ```console
30 | npm test
31 | ```
32 |
--------------------------------------------------------------------------------
/oracle-price-monitor/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "forta-ae-oracle-price-monitor",
3 | "version": "0.0.5",
4 | "chainIds": [
5 | 1
6 | ],
7 | "description": "This Bot monitors the UniswapAnchoredView contract to see if any price updates have been rejected.",
8 | "scripts": {
9 | "start": "npm run start:dev",
10 | "start:prod": "forta-agent run --prod",
11 | "tx": "forta-agent run --tx",
12 | "block": "forta-agent run --block",
13 | "range": "forta-agent run --range",
14 | "file": "forta-agent run --file",
15 | "publish": "forta-agent publish",
16 | "push": "forta-agent push",
17 | "disable": "forta-agent disable",
18 | "enable": "forta-agent enable",
19 | "keyfile": "forta-agent keyfile",
20 | "test": "jest"
21 | },
22 | "dependencies": {
23 | "forta-agent": "0.0.38"
24 | },
25 | "devDependencies": {
26 | "eslint": "8.16.0",
27 | "eslint-config-airbnb-base": "15.0.0",
28 | "eslint-plugin-import": "2.26.0",
29 | "jest": "28.1.0"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "compound-monitoring",
3 | "version": "1.0.0",
4 |
5 | "devDependencies": {
6 | "prettier": "^2.8.8",
7 | "prettier-plugin-solidity": "^1.1.3"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------