Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@stratosphere-network/token

Token module for StratoSphere SDK - ERC20 token minting and factory functionality

stratosphere, token, erc20, minting, factory, blockchain, defi

readme

@stratosphere-network/token

This package provides a Token class to deploy and manage upgradeable ERC20 tokens on supported blockchains using the UUPS proxy pattern.

Features

  • Upgradeable Tokens: Deploy tokens as UUPS proxies, allowing you to upgrade the underlying contract logic later without requiring users to migrate.
  • Role-Based Access Control: Manage permissions with distinct roles (MINTER_ROLE, BURNER_ROLE, PAUSER_ROLE, UPGRADER_ROLE) instead of a single owner.
  • Factory-Based Deployment: A central factory contract deploys lightweight proxy contracts, saving significant gas fees for your users.
  • Comprehensive SDK: A simple SDK to handle deployment, role management, feature toggling, and upgrades.

Installation

To install the package, you can use npm or yarn:

npm install @stratosphere-network/token
# or
yarn add @stratosphere-network/token

Usage

First, import the Token class and the necessary types from the package. If you plan to use an existing ethers.Wallet instance for deployment, you'll also need to import ethers:

First, import the Token class and the necessary types from the package. If you plan to use an existing ethers.Wallet instance, you'll also need to import ethers:

import Token, { TokenConfig, Chain } from "@stratosphere-network/token";
import { ethers } from "ethers"; // Required if providing your own ethers.Wallet instance

Next, create an instance of the Token class:

const tokenClient = new Token();

Deploying a Token

To deploy a new token, you'll need to provide a tokenConfig object. The deployer's credentials for the deployToken method can be supplied in one of the following ways:

  1. deployerPrivateKey (string, optional): The private key of the deployer's account.
  2. walletInstance (ethers.Wallet, optional): An existing ethers.Wallet object from the ethers library.

You must provide at least one of these to the deployToken method.

  • If only deployerPrivateKey is provided, a new ethers.Wallet is created internally using a default provider for the specified chain.
  • If only walletInstance is provided, that instance is used directly for deploying.
  • If both deployerPrivateKey and walletInstance are provided, a new ethers.Wallet is created using the deployerPrivateKey and the provider from the supplied walletInstance.

    const sdk = new Token();

### 1. Deploying an Upgradeable Token

To deploy a new token, provide a `tokenConfig` object. The `deployToken` method returns an object containing the `transactionHash` and the `tokenAddress` of the newly created proxy contract.

The address that deploys the token will automatically be granted the `DEFAULT_ADMIN_ROLE`, as well as the `MINTER_ROLE`, `BURNER_ROLE`, `PAUSER_ROLE`, and `UPGRADER_ROLE`.

Currently, token deployment is **only supported on Berachain Mainnet**.

```typescript
// Ensure tokenClient is instantiated as shown in the "Usage" section:
// import Token from "@stratosphere-network/token";
// const tokenClient = new Token();

async function deployMyToken() {
  const tokenConfig: TokenConfig = {
    name: "My Awesome Token",
    symbol: "MAT",
    totalSupply: "1000000000000000000000000", // 1 million tokens with 18 decimals
    decimals: 18,
    chain: Chain.BERACHAIN_MAINNET, // Ensure this matches supported chains
    isMintable: true, // Optional: Can the token supply be increased after deployment? Defaults to false.
    isBurnable: true, // Optional: Can tokens be burned to reduce supply? Defaults to false.
    isPausable: false, // Optional: Can token transfers be paused? Defaults to false.
  };

  // --- Option 1: Using deployerPrivateKey (simplest for quick start) ---
  const deployerPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY"; // Replace with actual private key
  try {
    console.log("Attempting to deploy with private key...");
    const txHashPk = await tokenClient.deployToken(
      tokenConfig,
      deployerPrivateKey
      // walletInstance is omitted or undefined here
    );
    console.log(
      "Token deployment with private key successful! Transaction Hash:",
      txHashPk
    );
  } catch (error) {
    console.error("Error deploying token with private key:", error);
  }

  // --- Option 2: Using an existing ethers.Wallet instance ---
  // This requires 'ethers' to be imported and a wallet instance prepared.
  // Example setup (replace with your actual provider and private key/mnemonic):
  /*
  // Ensure ethers is imported: import { ethers } from "ethers";
  // const BERACHAIN_RPC_URL = "https://mainnet.rpc.berachain.com/"; // Replace with actual official RPC for Berachain
  // const provider = new ethers.JsonRpcProvider(BERACHAIN_RPC_URL);
  // const existingWallet = new ethers.Wallet(deployerPrivateKey, provider); // Or from a connected wallet like MetaMask

  try {
    console.log("Attempting to deploy with wallet instance...");
    // Note: Pass undefined for deployerPrivateKey if primarily using walletInstance
    const txHashWallet = await tokenClient.deployToken(
      tokenConfig,
      undefined,
      existingWallet
    );
    console.log(
      "Token deployment with wallet instance successful! Transaction Hash:",
      txHashWallet
    );
  } catch (error) {
    console.error("Error deploying token with wallet instance:", error);
  }
  */
}

deployMyToken();

Note: Ensure your deployer account has enough native currency (e.g., BERA on Berachain) to cover the gas fees for the deployment transaction.

TokenConfig Parameters

  • name (string): The name of your token (e.g., "My Awesome Token").
  • symbol (string): The symbol for your token (e.g., "MAT").
  • totalSupply (string): The total supply of your token, expressed as a string in its smallest unit (e.g., wei for an 18-decimal token).
  • decimals (number): The number of decimal places your token will have (typically 18).
  • chain (Chain): The chain to deploy the token on. Currently, only Chain.BERACHAIN_MAINNET is supported.
  • isMintable (boolean, optional): Determines if new tokens can be minted after initial deployment. Defaults to false if not specified.
  • isBurnable (boolean, optional): Determines if tokens can be burned (destroyed) after deployment. Defaults to false if not specified.
  • isPausable (boolean, optional): Determines if token transfers and other operations can be paused. Defaults to false if not specified.

    // Ensure sdk is instantiated as shown above.

async function deployNewToken() { const tokenConfig: TokenConfig = { name: "My Upgradeable Token", symbol: "MUT", totalSupply: "1000000000000000000000000", // 1 million tokens with 18 decimals decimals: 18, chain: Chain.BERACHAIN_MAINNET, };

// Provide the private key of the deployer's account. // Ensure this account has enough native currency (e.g., BERA) to pay for gas. const deployerPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY";

try { console.log("Attempting to deploy token..."); const { transactionHash, tokenAddress } = await sdk.deployToken( tokenConfig, deployerPrivateKey ); console.log("Token deployment successful!"); console.log(- Transaction Hash: ${transactionHash}); console.log(- Token Proxy Address: ${tokenAddress}); // This is the address to interact with return tokenAddress; } catch (error) { console.error("Error deploying token:", error); } }


### 2. Managing the Token

Once deployed, you can manage the token using its proxy address.

#### Role Management

You can grant and revoke roles to other addresses.

```typescript
// You need the token's address from the deployment step.
const tokenAddress = "0xYourTokenProxyAddress";
const anotherAddress = "0x...someOtherAddress";
const adminPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY"; // The key of an address with DEFAULT_ADMIN_ROLE

// Grant the MINTER_ROLE
await sdk.grantRole(
  Chain.BERACHAIN_MAINNET,
  tokenAddress,
  "MINTER_ROLE",
  anotherAddress,
  adminPrivateKey
);
console.log("MINTER_ROLE granted.");

// Check if an address has a role
const hasRole = await sdk.hasRole(
  Chain.BERACHAIN_MAINNET,
  tokenAddress,
  "MINTER_ROLE",
  anotherAddress
);
console.log(`Does the address have MINTER_ROLE? ${hasRole}`); // true

// Revoke the MINTER_ROLE
await sdk.revokeRole(
  Chain.BERACHAIN_MAINNET,
  tokenAddress,
  "MINTER_ROLE",
  anotherAddress,
  adminPrivateKey
);
console.log("MINTER_ROLE revoked.");

Feature Control

Enable or disable token transfers, and pause or unpause the contract.

const tokenAddress = "0xYourTokenProxyAddress";
const pauserPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY"; // The key of an address with PAUSER_ROLE
const adminPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY"; // The key of an address with DEFAULT_ADMIN_ROLE

// Enable token transfers for all users
await sdk.setTransferable(
  Chain.BERACHAIN_MAINNET,
  tokenAddress,
  true,
  adminPrivateKey
);
console.log("Token transfers are now enabled for everyone.");

// Pause the contract
await sdk.pause(Chain.BERACHAIN_MAINNET, tokenAddress, pauserPrivateKey);
console.log("Contract is paused.");

// Unpause the contract
await sdk.unpause(Chain.BERACHAIN_MAINNET, tokenAddress, pauserPrivateKey);
console.log("Contract is unpaused.");

3. Upgrading the Token

If you deploy a new version of the Token.sol implementation contract, you can upgrade your proxies to point to the new logic.

const tokenAddress = "0xYourTokenProxyAddress";
const newImplementationAddress = "0x...addressOfNewTokenImplementation";
const upgraderPrivateKey = "YOUR_DEPLOYER_PRIVATE_KEY"; // The key of an address with UPGRADER_ROLE

await sdk.upgradeTo(
  Chain.BERACHAIN_MAINNET,
  tokenAddress,
  newImplementationAddress,
  upgraderPrivateKey
);
console.log("Token proxy has been upgraded to the new implementation!");

API Reference

TokenConfig Parameters

  • name (string): The name of your token (e.g., "My Upgradeable Token").
  • symbol (string): The symbol for your token (e.g., "MUT").
  • totalSupply (string): The initial supply of your token, expressed as a string in its smallest unit (e.g., wei for an 18-decimal token). This supply is minted to the deployer.
  • decimals (number): The number of decimal places your token will have (typically 18).
  • chain (Chain): The chain to deploy the token on. Currently, only Chain.BERACHAIN_MAINNET is supported.

SDK Methods

All methods that perform on-chain transactions require either a deployerPrivateKey or a walletInstance to be passed as the final argument.

  • deployToken(config, privateKey?, wallet?): Deploys a new token proxy. Returns { transactionHash, tokenAddress }.
  • grantRole(chain, tokenAddress, role, toAddress, ...): Grants a role to an address.
  • revokeRole(chain, tokenAddress, role, fromAddress, ...): Revokes a role from an address.
  • hasRole(chain, tokenAddress, role, address): Checks if an address has a specific role. Returns a boolean.
  • setTransferable(chain, tokenAddress, isTransferable, ...): Enables or disables token transfers for non-admins.
  • pause(chain, tokenAddress, ...): Pauses all token transfers, mints, and burns.
  • unpause(chain, tokenAddress, ...): Resumes a paused contract.
  • upgradeTo(chain, tokenAddress, newImplementation, ...): Upgrades the token proxy to a new implementation contract.

role parameter must be one of: "MINTER_ROLE", "BURNER_ROLE", "PAUSER_ROLE", "UPGRADER_ROLE".

5efa2a7fe3f1a6bd0d3e705d1dd6bdc7f677cdb2