npm package: @opencollective/token-factory
Description: Library to deploy and manage ERC20 tokens for communities on any EVM chain
Author: Open Collective
Latest version: 0.1.1

# Open Collective Token Factory

Library to deploy and manage an ERC20 token for your community.

## Features
- Deploy on any EVM chain
- Generate a SAFE wallet for any community member based on their email address or discord userid
- Mint and burn on behalf of any account.

## Install

```bash
npm install @opencollective/token-factory
```

## Usage

```ts
import { Token, utils } from "@opencollective/token-factory";

const privateKey = utils.loadPrivateKey(); // generates a new private key if needed, saves it in .privatekey
// or: const privateKey = process.env.PRIVATE_KEY;

const token = new Token(
  { 
    name: "My Community Token",
    symbol: "CT",
    chain: "base_sepolia", // gnosis, base, celo, ...
    deployerPrivateKey: privateKey, // optional: defaults to process.env.PRIVATE_KEY || utils.loadPrivateKey();
    // tokenAddress?: optional: if you already have an ERC20 token deployed  
  }); 

// console.log("OpenCollective/token: using deployer address", publicKeyDerivedFromPrivateKey, "balance:", await utils.getNativeBalance(publicKeyDerivedFromPrivateKey));

const tokenAddress = await token.deployToken(); // Use CREATE2 to make sure it always returns the same address given the same deployerAddress, tokenName and tokenSymbol (deploy first a tokenFactory contract for testing). This makes sure we never deploy twice the same token.

const userAddress = await token.getUserAddress("discord", "1435736971011162152"); // returns a 0xAddress where the SAFE will be eventually be deployed (when needed). The address is a function of the publicKey of the deployer, the provider (email or discord), and the providerUserId (email address, or discordUserId)

token.mintTo(1000000, "0x123..."); // mint 1 CT token to 0x123..., gas paid by deployer address
token.burnFrom(1000000, "0x123..."); // mint 1 CT token from account 0x123...

token.mintTo(1000000, `discord:1435736971011162152`); // mint 1 CT token to discord user 
token.burnFrom(1000000, `discord:1435736971011162152`); // mint 1 CT token from discord user

token.transfer(`discord:1435736971011162152`, `email:test@test.com`, 1000000); // send a token on behalf of the discord user (it's your responsibility to ensure the right discord user is logged in or sending the command). Gas paid by the deployer address since it it the default owner of all SAFE deployed for users. If the SAFE of the sender isn't deployed yet, this method deploys it first.

```

## Design

This is a centralized model. The core principle is: "In Community We Trust".
Since the community could anyway start minting a gazilion of new tokens (diluting the value of your holding), and since the wallets are only used to store that token, there is no reason to bother with proper independent ownership fo those wallets.

That's why all wallets are SAFE 1/n multisig owned by the community (represented by the deployer key). Therefore only the deployer key needs to be topped up with the native token to pay for gas fees.

## Governance

In this first version, we use the benevolent dictator model (aka the source).
The person that controls the deployer key controls the community.
Not happy with it? Fork it.

What's important here is that every single transaction (mint, burn, transfer) is recorded on the blockchain and therefore cannot happen without the community noticing. At any point, anyone can "fork" the community and issue a new token and airdrop it to all existing holders.

## API

```
  - token.getBalance(userIdentifier) // check balances (e.g. token.getBalance("discord:1435736971011162152"))
  - token.isDeployed(userIdentifier) // check if Safe exists
  - token.getSafeOwners(userIdentifier) // who controls this Safe?
  - Factory.deployToken(name, symbol) // deploys a new ERC20 burnable token.
  - token.addMinter(userIdentifier)
  - token.removeMinter(userIdentifier)
```


## Development & Testing

This project uses Deno for development and testing.

### Prerequisites

1. **Install Deno** (if not already installed):
   ```bash
   curl -fsSL https://deno.land/install.sh | sh
   ```

2. **Install Hardhat dependencies** (required for tests):
   ```bash
   deno task hh:install
   # or: cd hardhat && npm install
   ```

3. **Set up test environment**:
   ```bash
   cp .env.example .env.test
   # Edit .env.test and set PRIVATE_KEY
   ```

### Running Tests

Check if your environment is ready for testing:
```bash
deno task test:check
```

Run all tests:
```bash
deno task test
```

Run specific test suites:
```bash
deno task test:blockchain   # Core blockchain operations
deno task test:mint          # Token minting and burning
deno task test:safe          # SAFE wallet operations
deno task test:token         # Token class integration tests
deno task test:factory       # Token factory (CREATE2) tests
```

### Local Blockchain Testing

For tests that require a local blockchain:

1. **Start Hardhat node** (in a separate terminal):
   ```bash
   deno task hh:node
   ```

2. **Run tests**:
   ```bash
   deno task test
   ```

### Test Requirements

The test runner automatically checks for:
- `.env.test` file exists with `PRIVATE_KEY` configured
- Hardhat dependencies installed (SAFE contracts)
- Local blockchain running (for localhost tests)

If requirements are not met, you'll see helpful error messages explaining how to fix them.