@fevertokens/sdk
v0.0.5
Published
TypeScript SDK for Fever smart contract deployment and management
Downloads
7
Maintainers
Readme
@fevertokens/sdk
TypeScript SDK for Fever smart contract deployment and management
Bring manifest-driven smart contract deployment to your TypeScript/Node.js projects. Deploy contracts, POF packages, and complex multi-package systems with a clean, type-safe API.
Table of Contents
Why @fevertokens/sdk?
The Problem
Traditional smart contract deployment is painful:
- ❌ Write custom deployment scripts for every contract
- ❌ Manually manage contract addresses and dependencies
- ❌ No consistent approach across projects
- ❌ Hard to track what's deployed where
- ❌ Hit 24KB contract size limits
The Solution
Manifest-driven deployment + Package-Oriented Framework (POF)
import { FeverDeployer } from '@fevertokens/sdk'
const deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: process.env.PRIVATE_KEY! },
network: { chainId: 1337, rpcUrl: 'http://localhost:8545' }
})
// Deploy a complete lending system with one call
const result = await deployer.deploy({
kind: 'PackageSystem',
spec: {
system: { name: 'LendingApplication' },
packages: [
{ name: 'LoanRegistry' },
{ name: 'LoanFunding' },
{ name: 'LoanRepayment' },
{ name: 'LoanTokenManager' }
]
}
})
console.log(`✓ System deployed to ${result.address}`)
console.log(`✓ Packages attached: ${result.packages.length}`)One call deploys everything, manages dependencies, and tracks results.
Installation
npm
npm install @fevertokens/sdk ethersyarn
yarn add @fevertokens/sdk etherspnpm
pnpm add @fevertokens/sdk ethersRequirements:
- Node.js >= 18
- ethers v6.x
Quick Start
Deploy a simple contract in 3 minutes:
import { FeverDeployer } from '@fevertokens/sdk'
// 1. Create deployer
const deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: '0x...' },
network: { chainId: 1337, rpcUrl: 'http://localhost:8545' }
})
// 2. Deploy
const result = await deployer.deploy({
apiVersion: 'beta/v1',
kind: 'Contract',
spec: {
contract: {
name: 'MyToken',
constructorArgs: [
{ value: 'My Token' },
{ value: 'MTK' }
]
}
}
})
console.log(`Deployed to: ${result.address}`)Core Concepts
1. Manifest-Driven Deployment
Instead of scripts, declare what you want:
// Before: Complex custom script
const token = await TokenFactory.deploy("My Token", "MTK")
const vault = await VaultFactory.deploy(token.address)
// ... manage addresses, gas, errors manually
// After: Simple manifest
kind: Contract
spec:
contract:
name: MyToken
constructorArgs: ["My Token", "MTK"]2. Three Deployment Types
Contract - Regular smart contracts
kind: 'Contract'
spec: {
contract: { name: 'MyToken', constructorArgs: [...] }
}Use for: ERC20, NFTs, utilities, or any regular contract
Package - POF packages
kind: 'Package'
spec: {
package: { name: 'LoanRegistry', constructorArgs: [...] }
}Use for: Modular system components (Diamond facets)
PackageSystem - Complex multi-package systems
kind: 'PackageSystem'
spec: {
system: { name: 'LendingApplication' },
packages: [
{ name: 'LoanRegistry' },
{ name: 'LoanFunding' },
{ name: 'LoanRepayment' }
]
}Use for: DeFi protocols, complex systems, DAOs
3. Package-Oriented Framework (POF)
POF enables:
- ♾️ Unlimited size - Bypass 24KB contract size limit
- 🔄 Upgradeable - Replace packages without full redeployment
- 🧩 Modular - Reusable, composable components
- 💾 Shared storage - All packages access same state through proxy
// Traditional: Monolithic (24KB max)
contract ComplexLending { /* 2000 lines */ }
// POF: Modular (unlimited)
contract LendingApplication (Diamond)
├── LoanRegistry
├── LoanFunding
├── LoanRepayment
└── LoanTokenManagerAPI Reference
FeverDeployer
The main class for smart contract deployment.
Constructor
new FeverDeployer({
wallet: WalletConfig, // Required: How to sign transactions
network: { // Required: Network connection
chainId: number,
rpcUrl: string
},
tracker?: DeploymentTracker, // Optional: Track deployments
artifacts?: ArtifactResolverConfig // Optional: Where to find contract artifacts
})Wallet Configuration
Private Key (Fastest)
wallet: {
type: 'privateKey',
value: process.env.PRIVATE_KEY!
}Mnemonic (HD Wallets)
wallet: {
type: 'mnemonic',
value: 'abandon abandon abandon...',
path: "m/44'/60'/0'/0/0" // Optional BIP44 derivation path
}Ethers.js Signer
wallet: {
type: 'signer',
signer: ethers.Wallet.createRandom()
}Methods
deploy(manifest): Promise<DeploymentResult>
Deploy from a manifest object.
const result = await deployer.deploy({
apiVersion: 'beta/v1',
kind: 'Contract',
metadata: { name: 'my-token', version: '1.0.0' },
spec: {
contract: {
name: 'MyToken',
constructorArgs: [
{ value: 'Token Name' },
{ value: 'TKN' }
]
}
}
})
console.log(`Deployed to: ${result.address}`)deployFromFile(path): Promise<DeploymentResult>
Deploy from a YAML manifest file.
const result = await deployer.deployFromFile('./manifests/token.yaml')getAddress(): Promise<string>
Get deployer's wallet address.
const address = await deployer.getAddress()
console.log(`Deploying from: ${address}`)getChainId(): Promise<number>
Get connected network chain ID.
const chainId = await deployer.getChainId()
if (chainId !== 1337) throw new Error('Wrong network!')getAvailableContracts(): string[]
List all available contracts in artifacts.
const contracts = deployer.getAvailableContracts()
console.log(`Available: ${contracts.join(', ')}`)getDeployment(name, chainId?): Promise<DeploymentRecord | null>
Retrieve a previous deployment record.
const record = await deployer.getDeployment('MyToken', 1337)
if (record) {
console.log(`Previously deployed to: ${record.address}`)
}listDeployments(chainId?): Promise<DeploymentRecord[]>
List all deployments for a chain.
const deployments = await deployer.listDeployments(1337)
deployments.forEach(d => {
console.log(`${d.contractName}: ${d.address}`)
})Wallet Types
PrivateKeyWallet
import { PrivateKeyWallet } from '@fevertokens/sdk'
const wallet = new PrivateKeyWallet(
'0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80',
provider
)MnemonicWallet
import { MnemonicWallet } from '@fevertokens/sdk'
const wallet = new MnemonicWallet(
'abandon abandon abandon...',
provider,
"m/44'/60'/0'/0/0" // BIP44 path
)SignerWallet
import { SignerWallet } from '@fevertokens/sdk'
const wallet = new SignerWallet(ethers.Wallet.createRandom())Deployment Tracking
Track deployments for auditing and reference:
import { FileTracker } from '@fevertokens/sdk'
const deployer = new FeverDeployer({
// ... other config
tracker: new FileTracker('./.fever/deployments')
})
// Deployments automatically saved after each deploy
// Retrieve later
const record = await deployer.getDeployment('MyToken', 1337)
console.log(`Deployed to: ${record.address}`)Examples
1. Simple ERC20 Deployment
import { FeverDeployer } from '@fevertokens/sdk'
async function deployToken() {
const deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: process.env.PRIVATE_KEY! },
network: { chainId: 1337, rpcUrl: 'http://localhost:8545' }
})
const result = await deployer.deploy({
apiVersion: 'beta/v1',
kind: 'Contract',
metadata: { name: 'my-token', version: '1.0.0' },
spec: {
contract: {
name: 'MyToken',
constructorArgs: [
{ value: 'My Token' },
{ value: 'MTK' }
]
}
}
})
console.log(`✓ Deployed to: ${result.address}`)
return result
}
deployToken().catch(console.error)2. Lending Protocol (PackageSystem)
async function deployLendingSystem() {
const deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: process.env.PRIVATE_KEY! },
network: { chainId: 1337, rpcUrl: 'http://localhost:8545' }
})
const result = await deployer.deploy({
apiVersion: 'beta/v1',
kind: 'PackageSystem',
metadata: { name: 'lending-v1', version: '1.0.0' },
spec: {
system: {
name: 'LendingApplication',
constructorArgs: [
'$dependencies.packageController.address', // Auto-injected!
'$dependencies.packageViewer.address',
'${ADMIN_ADDRESS}' // From env
]
},
packages: [
{ name: 'LoanRegistry', functions: '*' },
{ name: 'LoanFunding', functions: '*' },
{ name: 'LoanRepayment', functions: '*' },
{ name: 'LoanTokenManager', functions: '*' }
],
dependencies: {
packageViewer: { name: 'PackageViewer' },
packageController: { name: 'PackageController' }
}
}
})
console.log(`✓ System: ${result.address}`)
console.log(`✓ Packages: ${result.packages.length}`)
console.log(`✓ Gas: ${result.totalGasUsed}`)
}
deployLendingSystem().catch(console.error)3. CI/CD Deployment
import { FeverDeployer, FileTracker } from '@fevertokens/sdk'
async function cicdDeploy() {
const deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: process.env.DEPLOYER_KEY! },
network: {
chainId: parseInt(process.env.CHAIN_ID || '1'),
rpcUrl: process.env.RPC_URL!
},
tracker: new FileTracker('./.fever/deployments'),
artifacts: { combinedPath: './.fever/combined.json' }
})
// Verify network
const chainId = await deployer.getChainId()
if (chainId !== parseInt(process.env.CHAIN_ID!)) {
throw new Error('Wrong network!')
}
// Deploy
const result = await deployer.deployFromFile('./manifests/production.yaml')
// Export for CI/CD
console.log(`::set-output name=address::${result.address}`)
console.log(`::set-output name=tx::${result.transactionHash}`)
}
cicdDeploy().catch(error => {
console.error('Deployment failed:', error.message)
process.exit(1)
})4. Testing Contracts
import { FeverDeployer } from '@fevertokens/sdk'
describe('MyToken', () => {
let deployer: FeverDeployer
let tokenAddress: string
beforeAll(async () => {
deployer = new FeverDeployer({
wallet: { type: 'privateKey', value: '0xac0974...' },
network: { chainId: 1337, rpcUrl: 'http://localhost:8545' }
})
})
it('should deploy MyToken', async () => {
const result = await deployer.deploy({
apiVersion: 'beta/v1',
kind: 'Contract',
spec: {
contract: {
name: 'MyToken',
constructorArgs: [{ value: 'Test' }, { value: 'TEST' }]
}
}
})
expect(result.address).toBeDefined()
tokenAddress = result.address
})
it('should retrieve deployment', async () => {
const record = await deployer.getDeployment('MyToken', 1337)
expect(record?.address).toBe(tokenAddress)
})
})Advanced Features
Environment Variables
Use ${VAR_NAME} in manifests:
spec: {
contract: {
name: 'MyContract',
constructorArgs: [
{ value: '${ADMIN_ADDRESS}' },
{ value: '${INITIAL_SUPPLY}' }
]
}
}
// Set in .env:
// ADMIN_ADDRESS=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
// INITIAL_SUPPLY=1000000Dependency Resolution
Automatically resolve addresses from previous deployments:
spec: {
system: {
name: 'App',
constructorArgs: [
'$dependencies.tokenManager.address', // Auto-injected!
'$dependencies.controller.address'
]
},
dependencies: {
tokenManager: { name: 'TokenManager' },
controller: { name: 'PackageController' }
}
}Custom Artifact Sources
// From file
deployer.setCombinedJsonPath('./.fever/combined.json')
// From direct data
const artifacts = {
contracts: {
MyToken: {
abi: [...],
bytecode: '0x...'
}
}
}
deployer.setCombinedJsonData(artifacts)
// From HTTP
const response = await fetch('https://api.example.com/artifacts')
deployer.setCombinedJsonData(await response.json())Error Handling
try {
const result = await deployer.deploy(manifest)
} catch (error) {
if (error.code === 'NONCE_EXPIRED') {
console.error('Check pending transactions')
} else if (error.code === 'INSUFFICIENT_FUNDS') {
console.error('Not enough balance for gas')
} else {
console.error('Deployment failed:', error.message)
}
}FAQ
Q: What's the difference between Contract, Package, and PackageSystem?
- Contract: Regular smart contracts (ERC20, NFTs, etc.)
- Package: POF facets designed to be composed into systems
- PackageSystem: Complete system of coordinated packages
Q: How does POF work?
POF uses the Diamond pattern to split large contracts into modular packages. All packages share the same storage and are routed through a proxy, allowing:
- Contracts larger than 24KB
- Upgradeable packages without full redeployment
- Modular, testable components
Q: Can I deploy to multiple chains?
Yes, create separate deployers:
const mainnet = new FeverDeployer({ network: { chainId: 1, rpcUrl: '...' } })
const polygon = new FeverDeployer({ network: { chainId: 137, rpcUrl: '...' } })
await mainnet.deploy(manifest)
await polygon.deploy(manifest)Q: How do I track production deployments?
Use FileTracker:
tracker: new FileTracker('/var/lib/fever/deployments')Q: How is this different from Fever CLI?
- Fever CLI: Command-line tool (
fever deploy -f manifest.yaml) - SDK: Programmatic API for Node.js/TypeScript
Both use the same deployment engine.
Support & Resources
- Documentation: docs.fevertokens.app
- GitHub: FeverTokens/fever-cli
- Issues: GitHub Issues
- Discord: FeverTokens Community
License
FeverTokens Proprietary Base Code License v1.0
This SDK is licensed under the FeverTokens Proprietary License. See LICENSE.md for full terms.
Summary
- ✅ Use as integrated component in your Product
- ✅ Create Derivative Works with modifications
- ❌ Cannot extract or reuse Base Code independently
- ❌ Cannot reverse engineer or decompile
- ❌ Cannot redistribute separately
For full license terms, see LICENSE.md
Made with ❤️ by the FeverTokens team
