{"id":22128962,"url":"https://github.com/inverternetwork/funding-pot","last_synced_at":"2026-03-07T06:02:44.192Z","repository":{"id":256290188,"uuid":"839035614","full_name":"InverterNetwork/funding-pot","owner":"InverterNetwork","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-22T21:51:49.000Z","size":1507,"stargazers_count":0,"open_issues_count":0,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-05-22T22:01:16.194Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/InverterNetwork.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-08-06T20:42:45.000Z","updated_at":"2025-05-22T21:51:52.000Z","dependencies_parsed_at":"2024-12-13T15:47:02.619Z","dependency_job_id":"8f0b0b66-6541-4637-a353-939903bb91b7","html_url":"https://github.com/InverterNetwork/funding-pot","commit_stats":null,"previous_names":["inverternetwork/funding-pot"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/InverterNetwork/funding-pot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InverterNetwork%2Ffunding-pot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InverterNetwork%2Ffunding-pot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InverterNetwork%2Ffunding-pot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InverterNetwork%2Ffunding-pot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InverterNetwork","download_url":"https://codeload.github.com/InverterNetwork/funding-pot/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InverterNetwork%2Ffunding-pot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272342736,"owners_count":24917686,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-27T02:00:09.397Z","response_time":76,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-01T17:57:26.024Z","updated_at":"2026-03-07T06:02:44.174Z","avatar_url":"https://github.com/InverterNetwork.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Funding Pot\n\n## Quickstart\n\n1. Get an ankr api key [here](\u003c[here](https://www.ankr.com/rpc/advanced-api/)\u003e)\n2. Fund two accounts with testnet ETH on Base Sepolia\n3. Copy the `.env.example` file to `.env.test` and fill in the api key as well as the two private keys\n4. Run `npm install`\n5. Run `npm run test:e2e`\n6. Check the following files for the results:\n\n- inputs:\n  - batchConfig (to be set per batch): `data/test/input/batches/s1/3.json`\n    **NOTE**: subdivided by seasons, where s1 refers to season 1\n  - projects (to be set once): `data/test/input/projects.json` (=\u003e `GENERATED_TEST_PROJECT`)\n- outputs:\n  - batchReport: `data/test/output/GENERATED_TEST_PROJECT/3.json`\n\n## Terminology\n\nWithin the project the term `batch` refers to one instance of running a funding interval. That includes\n\n- users contributing within a given time interval (= transferring collateral tokens to the safe)\n- using these funds to buy from the bonding curve\n- calculating the amounts of issuance tokens that contributors receive\n- creating linear vestings for contributors\n\nNote: this script does not cover the claiming of tokens by contributors\n\n## Installation\n\nClone the repository and install the dependencies:\n\n`git clone https://github.com/InverterNetwork/funding-pot.git \u0026\u0026 cd funding-pot \u0026\u0026 npm install`\n\nNext you will have to set some environment variables.\n\n## Run the tests\n\n### Prerequisites\n\n- you have an ANKR API key for their \"advanced API\" (get one [here](https://www.ankr.com/rpc/advanced-api/))\n- you have two private keys whose addresses are funded with small amounts of testnet gas tokens\n\n### Instructions\n\nCopy `.env.example` to `.env.test` and fill in the values. In order to run all tests, you need to have an **ANKR API key** and specify **two private keys**. One key is associated with the **single owner of a Safe** and the other the key is associated with the role of a **delegate** who can **propose transactions** to that safe. If the delegation mechanism is configured to be disabled, the second address will only be used to emulate a second contributor to a test funding round You will require a small amount of _testnet ETH_ for both accounts. When running the e2e tests, the private keys will be used to setup an safe and workflow for your personal accounts that is used to test against.\n\n### End-to-end test\n\n**Prerequisites**:\n\n- hold a small amount of wrapped native tokens in the wallet associated with the PK of the .env\n\nThe `main.e2e.test.js` file is an end-to-end test that tests the whole flow from safe creation to vesting creation. Specifically it does the following steps:\n\n- deploy a safe (via Safe's Protocol and API Kits)\n- deploy the workflow (via the [Inverter SDK](https://github.com/InverterNetwork/sdk))\n- make all inverter-related workflow configurations\n- send some contributions to the safe from the owner and delegate accounts (using the native token)\n- generate \u0026 save a project \u0026 batch config\n- execute the funding pot script\n\nBy running this test, you will be able to understand the input parameters that the script requires, as well as the output that it produces.\n\nTo just the end-to-end test use the following command:\n\n`npm run test:e2e`\n\n**NOTE:** Due to the number of transactions and API calls involved with this test, it regularly fails for wallet-related reasons (nonce issues). If this happens, you can try to run the test again.\n\n### Cleanup\n\nSince the end-to-end test uses some randomness for determining the contribution sizes, it can happen that both test contributors hit the 2% cap and don't qualify for joining the funding pot. In this case you can clean up the test data by running `npm run clean` and start from scratch.\n\nThis command will remove all auto-generated files from `/data` and allows you to generate new ones the next time you run the tests.\n\n## Run the script\n\n### Prerequisites\n\n- you have an ANKR API key\n- you have added the address associated with your delegate private key as delegate to the safe (you can also do this via [this](https://gnosis-safe-delegate-dapp-nine.vercel.app/) UI)\n- you have deployed and configured the workflow\n- you have deployed the NFT contract used for the early access round\n\n### Instructions\n\nCopy `.env.example` to `.env` and fill in the values. If the delegate has already been added to the Safe that you want to propose to, setting the `DELEGATE` private key is enough.\n\n- add at least the delegate key (`DELEGATE`) to your `.env`\n- add the ANKR API (`ANKR_API_KEY`) key to your `.env`\n- make sure that `CHAIN_ID` and `ANKR_NETWORK_ID` are set to the correct values\n\n### Configuration options / Inputs\n\nThere are three types of inputs that the script executor can take. They can all be found under `/data/production/input`.\n\n1. `projects.json`: Contains on object where each key is a project name and each value is an object containing the safe address and the orchestrator address of the project, the NFT contract address associated with the early access round, and the amount of collateral tokens to be used as matching funds. This file should be updated whenever a new project is added or an existing one is updated. There is an example file under `/data/test/input/projects.json`. If you run the tests for the first time, an additional project (\"GENERATED_TEST_PROJECT\") will be added to `/data/test/input/projects.json`.\n\nNested under the key `BATCH_CONFIGS` you need - surprise - to put the batch config. The key corresponds to the batch number.\n\n**Example:**\n\n```json\n{\n  \"SOME_PROJECT\": {\n    \"SAFE\": \"0x0000000000000000000000000000000000000000\",\n    \"ORCHESTRATOR\": \"0x0000000000000000000000000000000000000001\",\n    \"NFT\": \"0x0000000000000000000000000000000000000002\",\n    \"BATCH_CONFIGS:\" {\n      \"3\": {\n        \"VESTING_DETAILS\": {\n          \"START\": \"1726861746\", // vesting start in unix time\n          \"CLIFF\": \"60\", // seconds until cliff from start\n          \"END\": \"1726861806\" // vesting end in unix time\n        },\n        \"TIMEFRAME\": {\n          \"FROM_TIMESTAMP\": \"1726861686\", // start timestamp\n          \"TO_TIMESTAMP\": \"1726861818\" // end timestamp =\u003e between these timestamps users can contribute\n        },\n        \"LIMITS\": {\n          \"INDIVIDUAL\": \"2000\", // individual contribution limit in dollar; for the EA and QACC round this corresponds to the cap for zkID users\n          \"INDIVIDUAL_2\": \"250\", // ONLY REQUIRED FOR QACC ROUND: individual contribution limit in dollar for GTCPass users\n          \"TOTAL\": \"1500\" // batch limit in dollar\n        },\n        \"IS_EARLY_ACCESS\": false, // if its an early access round (true) or a qacc round (false),\n        \"PRICE\": \"0.1\", // assumed dollar price per collateral token for that batch,\n        \"MATCHING_FUNDS\": \"420.69\" // ONLY REQUIRED FOR QACC ROUND: amount of collateral tokens to be used as matching funds; e.g. 420.69 POL coming from the matching pool\n      }\n    }\n  },\n  \"ANOTHER_PROJECT\": {\n    \"SAFE\": \"0x0000000000000000000000000000000000000003\",\n    \"ORCHESTRATOR\": \"0x0000000000000000000000000000000000000004\",\n    \"NFT\": \"0x0000000000000000000000000000000000000005\",\n    \"MATCHING_FUNDS\": \"420.69\",\n    \"BATCH_CONFIGS:\" {\n      \"1\": {\n        ...\n      },\n      \"2\": {\n        ...\n      }\n    }\n  },\n  }\n}\n```\n\n### Running the script\n\n#### For a single project\n\nTo run the script for one project use the following command:\n\n`npm run project \u003cSEASON\u003e \u003cPROJECT_NAME\u003e \u003cBATCH_NUMBER\u003e`\n\n- `SEASON`: the season you want to run the script for; used to fetch season-specific configurations from `batches/\u003cSEASON\u003e/\u003cBATCH_NUMBER\u003e.json`\n- `PROJECT_NAME`: the name of the project you want to run the script for; used to fetch project-specific configurations from `projects.json`\n- `BATCH_NUMBER`: the batch number you want to run the script for; used to fetch batch-specific configurations from `batches/\u003cSEASON\u003e/\u003cBATCH_NUMBER\u003e.json`\n\n**Example:**\n\nThe following command will run the script for the 2nd batch of the project `FUNKY_FOXES` in season 3:\n\n`npm run project 3 \"FUNKY_FOXES\" 2`\n\n### Checking the script's output\n\nWhen the script has executed a JSON report will be added under `data/production/output/\u003cPROJECT_NAME\u003e/\u003cBATCH_NUMBER\u003e.json`. You can use this file to better understand what has been proposed to the safe.\n\n**Running the script will store a json to data/\u003cenvironment\u003e/output/transactions that can then be executed in the safe UI.**\n\n## Running the vesting script\n\n### Pre-requisites\n\n- the `data/production/input/projects.json` file is set\n- all environment variables are set that are also required for the funding pot script\n- the total amount of vesting tokens has been sent to the payment router\n\n### Necessary steps\n\n1. set the `vestings.json` file under `/utils/scripts/inputs/vestings.json`\n\nNOTE: there is an example file set (`vestings.example.json`), which you can use as reference.\n\nThe following is an example. Note that all projects share the same vesting details and each key in in `VESTINGS` corresponds to a project name. These need to be the same project names as in the `projects.json` file. Associated with each project is an array of vestings, where the recipient is the address that will receive the vesting and the amount is the amount of tokens that will be vested.\n\n```json\n{\n  \"VESTING_DETAILS\": {\n    \"START\": 1,\n    \"END\": 3,\n    \"CLIFF\": 1\n  },\n  \"VESTINGS\": {\n    \"GENERATED_TEST_PROJECT\": [\n      {\n        \"recipient\": \"0x6747772f37a4F7CfDEA180D38e8ad372516c9548\",\n        \"amount\": \"420000000000000000000\"\n      },\n      {\n        \"recipient\": \"0xa6e12EDe427516a56a5F6ab6e06dD335075eb04b\",\n        \"amount\": \"69000000000000000000\"\n      }\n    ],\n    \"GENERATED_TEST_PROJECT_2\": [\n      {\n        \"recipient\": \"0x6747772f37a4F7CfDEA180D38e8ad372516c9548\",\n        \"amount\": \"420000000000000000000\"\n      },\n      {\n        \"recipient\": \"0xa6e12EDe427516a56a5F6ab6e06dD335075eb04b\",\n        \"amount\": \"69000000000000000000\"\n      }\n    ]\n  }\n}\n```\n\n2. **per project** run the script with `npm run vestings \u003cPROJECT_NAME\u003e`\n\n```\n\nnpm run vesting:project \u003cproject_name\u003e\n\n```\n\nThis will create and store a transaction json. The command needs to be repeated for each project.\n\n## Setting up Roles (claiming tributes)\n\n### Running the script\n\n**Prerequisites**:\n\n1. Set up the roles config in utils/scripts/inputs/roles.json\n\nThe following is an example. Note that all projects share the same vesting details and each key in in `VESTINGS` corresponds to a project name. These need to be the same project names as in the `projects.json` file. There is one workflow admin for all projects. That is the workflow admin multisig set upon deployment as `initialAdmin`.Associated with each project is a `feeClaimer` and a `feeRecipient`. The `feeClaimer` is the address that will be able to claim the tributes from the safe. The `feeRecipient` is the address that will receive the tributes.\n\n```json\n{\n  \"workflowAdmin\": \"0x...\",\n  \"projects\": {\n    \"GENERATED_TEST_PROJECT\": {\n      \"feeClaimer\": \"0x...\",\n      \"feeRecipient\": \"0x...\"\n    },\n    \"\u003cPROJECT_NAME_2\u003e\": {\n      \"feeClaimer\": \"0x...\",\n      \"feeRecipient\": \"0x...\"\n    }\n  }\n}\n```\n\n2. **Per project** run the script with `npm run roles:project \u003cPROJECT_NAME\u003e`\n\nThis will save a transaction JSON to transactions folder. The json needs to be dropped in the Safe UI and confirmed by the workflow admin multisig.\n\n## Distribute Protocol Fees Script\n\nThis script facilitates the distribution of accumulated ERC20 tokens and the native blockchain token from a central fee collector multisig to a predefined list of recipients based on specified shares.\n\n### Purpose\n\nThe script performs the following actions:\n\n1.  Connects to the specified blockchain via an RPC URL.\n2.  Optionally, fetches current balances of configured ERC20 tokens and the native token held by the `feeCollectorMs`.\n3.  Calculates the amount of each token to be distributed to each recipient according to their defined share.\n4.  Generates Gnosis Safe compatible transaction JSON files for these transfers. These files can then be uploaded to the Gnosis Safe UI to execute the distributions.\n5.  Handles batching of transactions if the total number of transfers exceeds the configured `batchSize`.\n\n### Configuration\n\nThe script's behavior is controlled by the `utils/scripts/distributeProtocolFees/config.js` file. Key configuration options include:\n\n- `feeCollectorMs`: (String) The address of the Gnosis Safe multisig wallet that holds the fees to be distributed.\n- `tokens`: (Array of Strings) A list of ERC20 token contract addresses that the script should attempt to distribute.\n- `recipients`: (Array of Objects) Defines who receives the fees and their respective shares. Each object should have:\n  - `name`: (String) A descriptive name for the recipient.\n  - `address`: (String) The recipient's blockchain address.\n  - `share`: (Number) The proportion of fees this recipient should receive (e.g., `0.6` for 60%). The sum of shares for all recipients should ideally be 1.0 for full distribution.\n- `rpcUrl`: (String) The URL of the RPC provider for the blockchain network (e.g., `https://1rpc.io/matic`).\n- `chainId`: (String) The chain ID of the network (e.g., `\"137\"` for Polygon Mainnet).\n- `batchSize`: (Number) The maximum number of individual transfer transactions to include in a single Gnosis Safe JSON file. Default is `100`.\n- `distributeNativeToken`: (Boolean) Set to `true` to enable distribution of the native blockchain token (e.g., ETH, MATIC), or `false` to disable it.\n- `nativeTokenSymbol`: (String) The symbol of the native token (e.g., `\"MATIC\"`). Used for logging.\n- `transactionMeta`: (Object) Contains metadata for the generated transaction files:\n  - `namePrefix`: (String) A prefix used in the output JSON `meta.name` field and filename (e.g., `\"Fee Distribution\"`).\n  - `description`: (String) A description for the transaction batch.\n\n**Example `config.js` snippet:**\n\n```javascript\n// utils/scripts/distributeProtocolFees/config.js\nexport const config = {\n  feeCollectorMs: '0x7022CE36B265cAcD497b2d3AC70fB7020d3892a6',\n  tokens: [\n    '0x6fc91fbe42f72941486c98d11724b14fb8d18b36', // Example Token 1\n    // ... more token addresses\n  ],\n  recipients: [\n    { name: 'QACC', address: '0x...', share: 0.6 },\n    { name: 'Inverter', address: '0x...', share: 0.3 },\n    // ... more recipients\n  ],\n  rpcUrl: 'https://1rpc.io/matic',\n  chainId: '137',\n  batchSize: 100,\n  distributeNativeToken: true,\n  nativeTokenSymbol: 'MATIC',\n  transactionMeta: {\n    namePrefix: 'Fee Distribution',\n    description: 'Distribute protocol fees from the main multisig.',\n  },\n};\n```\n\n### Running the Script\n\nTo execute the script, navigate to the project's root directory and run:\n\n```bash\nnpm run distribute-fees\n```\n\nThis command will run the script with `NODE_ENV` set to `production` by default, causing output files to be saved in `data/production/transactions/`.\n\nIf you need to run the script for a different environment (e.g., to output files to `data/development/transactions/`), you can still override the `NODE_ENV` variable when invoking the script:\n\n```bash\nNODE_ENV=development npm run distribute-fees\n```\n\n### Output\n\nThe script generates one or more Gnosis Safe transaction JSON files in the `data/{NODE_ENV}/transactions/` directory.\nThe naming convention for these files is:\n\n- `[FEE_DISTRIBUTION]-{timestamp}.json` (if only one file is generated)\n- `[FEE_DISTRIBUTION]-{timestamp}-{index}.json` (e.g., `[FEE_DISTRIBUTION]-1678886400000-1.json`, `[FEE_DISTRIBUTION]-1678886400000-2.json`) if multiple files are generated due to `batchSize`.\n\nThe `{timestamp}` is a Unix millisecond timestamp from the time the script was run. The `{index}` is a 1-based counter for multiple files from the same run.\n\nThese JSON files can be uploaded to the Gnosis Safe interface to propose and execute the fee distribution transactions.\n\n### Important Notes\n\n- **Environment Configuration**: The script relies on the `NODE_ENV` environment variable to determine the output directory for transaction files (e.g., `data/production/transactions/` or `data/development/transactions/`). Ensure this is set appropriately before running.\n- **RPC URL and Chain ID**: For the script to fetch live on-chain data (like token balances and decimals), the `rpcUrl` and `chainId` in `config.js` must be correctly set to valid values. If placeholder values are used (e.g., `'YOUR_RPC_PROVIDER_URL_PLACEHOLDER'`), the script will skip blockchain interactions and assume zero balances for all tokens, though it will still generate transaction JSONs based on this assumption.\n- **Token Decimals**: The script attempts to fetch ERC20 token decimals on-chain. If this fails or if blockchain interactions are skipped, it defaults to 18 decimals. Native token distributions always assume 18 decimals.\n\n## Technical Specification\n\nIn summary this project does three things:\n\n1. Contributions: it records transfers of the funding token to a safe that occur within a given timeframe (= contributions)\n2. Calculations: filters these transfers by eligibility (specified by allowlist \u0026 NFT holdings) and calculates the amount of reward tokens that will be vested to each contributor in return for contribution\n3. Execution: assembles and proposes (via a Safe delegate flow) multisend transactions to the safe to use contributions for buying reward tokens from the bonding curve and stream them to contributors\n\n### Details on the calculation logic\n\n- contributions per user per batch are capped\n- how much a user can contribute is calculated as follows:\n  1. the batch config (`/input/batches/s\u003cseason\u003e/\u003cbatchNr\u003e.json`) specifies the amount of collateral tokens that a user can contribute per batch\n  2. the batch config also specifies a total cap on the batch and if this cap is reached the batch is closed\n  3. the unfilled total cap carries over to the next batch (the individual cap doesn't)\n\n## Implementation details\n\n### Structure\n\n#### Data\n\n- subdivided into `production` and `test`\n- `input`: contains the user input data for the scripts\n- `output`: per batch and project, a JSON report will be generated in this folder\n\n```\n\n.\n├── README.md\n├── config.js\n└── data\n  ├── abis.js\n  ├── test\n  └── production\n    ├── input\n    │   ├── batches\n    │   │   ├── s1\n    │   │   │   ├── 1.json\n    │   │   │   ├── 2.json\n    │   │   │   └── 3.json\n    │   │   └── s2\n    │   │       ├── 1.json\n    │   │       ├── 2.json\n    │   │       └── 3.json\n    │   └── projects.json\n    └── output\n        ├── GENERATED_TEST_PROJECT\n        │   ├── 1.json\n        │   ├── 2.json\n        │   └── 3.json\n        ├── STATIC_TEST_PROJECT_1\n        └── STATIC_TEST_PROJECT_2\n            ├── 1.json\n            └── 2.json\n```\n\n#### Services\n\nThe services are where the most of the logic sits. All services are classes that store most of the outputs of their respective operations in state. This is then later used to generate the report.\n\n- `Batch`: contains the logic for calculating who gets how many tokens\n- `Queries`: contains the logic for querying external data sources\n- `Safe`: contains the logic for interacting with the safe\n- `TransactionBuilder`: contains the logic for generating transaction batches\n\n```\n\n├── env.js\n├── index.js\n├── package-lock.json\n├── package.json\n└── services\n  ├── Batch\n  │ ├── Batch.js\n  │ └── Batch.test.js\n  ├── Queries\n  │ ├── Queries.js\n  │ ├── Queries.test.js\n  │ └── queryBuilder.js\n  ├── Safe\n  │ ├── Safe.js\n  │ └── Safe.test.js\n  └── TransactionBuilder\n    ├── TransactionBuilder.js\n    └── TransactionBuilder.test.js\n\n```\n\n#### Steps\n\nThe steps tie the services together and bring an order into the execution flow.\n\n1. `loadInputs`: loads input parameters provided by the user as JSON files as well as environment variables\n2. `validateInputs`: validates the input parameters and environment variables\n3. `instantiateServices`: instantiates the services using the input parameters and environment variables\n4. `defineBatch`: defines the batch by calculating the contributions, eligibility, received allocations, vesting details etc.\n5. `proposeBatch`: bundles all transactions into batched multisend transactions that are then proposed to the safe via the delegation mechanism (tx batch size is defined in `config.js`)\n6. `storeReport`: services \"log\" their logic operations; this data is used to generate a `report` json file that describes the batch\n\n```\n\n├── steps\n│ ├── 01_loadInputs\n│ │ ├── 01_loadInputs.js\n│ │ └── 01_loadInputs.test.js\n│ ├── 02_validateInputs\n│ │ ├── 02_validateInputs.js\n│ │ └── 02_validateInputs.test.js\n│ ├── 03_instantiateServices\n│ │ ├── 03_instantiateServices.js\n│ │ └── 03_instantiateServices.test.js\n│ ├── 04_defineBatch\n│ │ ├── 04_defineBatch.js\n│ │ └── 04_defineBatch.test.js\n│ ├── 05_proposeBatch\n│ │ ├── 05_proposeBatch.js\n│ │ └── 05_proposeBatch.test.js\n│ ├── 06_storeReport\n│ │ └── 06_storeReport.js\n│ ├── main.e2e.test.js\n│ └── main.js\n└── utils\n├── helpers.js\n├── scripts\n│ ├── addDelegate.js\n│ └── resetTestFiles.js\n└── testUtils\n├── staticTestData.js\n├── testHelpers.js\n└── unitTestRunner.js\n\n```\n\n```\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finverternetwork%2Ffunding-pot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Finverternetwork%2Ffunding-pot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Finverternetwork%2Ffunding-pot/lists"}