arnacon-sdk
Version:
A comprehensive SDK for deploying and managing Arnacon smart contracts across multiple networks
496 lines (375 loc) ⢠13.7 kB
Markdown
# Arnacon SDK
A comprehensive SDK for deploying and managing Arnacon smart contracts across multiple networks with ease.
## Installation
```bash
npm install @arnacon/sdk
```
## Quick Start
### Using ChainId (Recommended)
```javascript
const ArnaconSDK = require('@arnacon/sdk');
// Initialize the SDK with your private key and chainId
const privateKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
const chainId = 137; // Polygon mainnet
const sdk = new ArnaconSDK(privateKey, chainId);
// Get network information
console.log("Network:", sdk.getNetworkName());
console.log("RPC URL:", sdk.getRpcUrl());
console.log("Explorer:", sdk.getExplorerUrl());
// Deploy all contracts with custom TLD
await sdk.deployContracts("global"); // or any TLD you want
await sdk.deployGSM();
await sdk.registerAsServiceProvider("mycompany");
```
### Using RPC URL (Backward Compatibility)
```javascript
const ArnaconSDK = require('@arnacon/sdk');
// Initialize the SDK with your private key and RPC URL
const privateKey = "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef";
const rpcUrl = "https://polygon-rpc.com"; // or your preferred RPC endpoint
const sdk = new ArnaconSDK(privateKey, rpcUrl);
// Deploy all contracts with custom TLD
await sdk.deployContracts("global"); // or any TLD you want
await sdk.deployGSM();
await sdk.registerAsServiceProvider("mycompany");
```
## Supported Networks
The SDK supports the following networks out of the box:
| Chain ID | Network Name | RPC URL | Explorer |
|----------|--------------|---------|----------|
| 137 | Polygon | https://polygon-rpc.com | https://polygonscan.com |
| 23295 | Oasis Sapphire | https://1rpc.io/oasis/sapphire | https://explorer.sapphire.oasis.dev |
| 23294 | Oasis Sapphire Testnet | https://testnet.sapphire.oasis.dev | https://testnet.explorer.sapphire.oasis.dev |
| 80002 | Polygon Amoy | https://rpc-amoy.polygon.technology | https://amoy.polygonscan.com |
| 31337 | Hardhat Local | http://localhost:8545 | null |
| 1337 | Testing Global | http://localhost:8545 | null |
## Features
### š Deploy Functions
#### `deployContracts(tld = "global")`
Deploys all core contracts for the specified TLD (Top Level Domain) including:
- ENS Registry
- Base Registrar Implementation
- Reverse Registrar
- Static Metadata Service
- Name Wrapper
- Public Resolver
- Simple Price Oracle
- ETH Registrar Controller
The TLD parameter allows you to deploy for any domain extension (e.g., "global", "test", "app", etc.).
```javascript
// Deploy for .global TLD
const contracts = await sdk.deployContracts("global");
console.log("Deployed contracts:", Object.keys(contracts));
// Deploy for .test TLD
const contracts = await sdk.deployContracts("test");
console.log("Deployed contracts:", Object.keys(contracts));
// Deploy for .app TLD
const contracts = await sdk.deployContracts("app");
console.log("Deployed contracts:", Object.keys(contracts));
```
#### `deployGSM()`
Deploys Global Service Management contracts:
- Poseidon T3 Library
- ETH Registrar Controller
- Public Resolver
- Name Wrapper
- Global Registrar Controller
- Provision Registry
```javascript
const gsmContracts = await sdk.deployGSM();
console.log("GSM contracts deployed:", Object.keys(gsmContracts));
```
#### `registerAsServiceProvider(name)`
Registers as a service provider with the specified name:
- Deploys required contracts
- Sets up second level interactor
- Configures Arnacon resolver
- Deploys product type registry
- Sets up NFT contracts
```javascript
const serviceProviderInfo = await sdk.registerAsServiceProvider("mycompany");
console.log("Service provider info:", serviceProviderInfo);
```
### š¤ Service Provider Methods
#### `getSecondLevelController()`
Get the second level controller address for the current service provider.
```javascript
const controller = await sdk.getSecondLevelController();
console.log("Second level controller:", controller);
```
#### `getSecondLevelInteractor()`
Get the second level interactor address for the current service provider.
```javascript
const interactor = await sdk.getSecondLevelInteractor();
console.log("Second level interactor:", interactor);
```
#### `getProductRegistry(name)`
Get the product type registry contract for a specific name.
```javascript
const registry = await sdk.getProductRegistry("mydomain");
console.log("Product type registry:", registry);
```
#### `getProductTypes(name)`
Get all product types from the registry for a specific name.
```javascript
const productTypes = await sdk.getProductTypes("mydomain");
console.log("Product types:", productTypes);
```
#### `getAllProductsWithMetadata(name)`
Get all products with their full metadata from the ProductTypeRegistry.
```javascript
const productsWithMetadata = await sdk.getAllProductsWithMetadata("mydomain");
console.log("Products with metadata:", productsWithMetadata);
```
#### `getProductsFromContract(nftContractAddress)`
Get all products from a specific NFT contract.
```javascript
const products = await sdk.getProductsFromContract("0x123...");
console.log("Products from contract:", products);
```
#### `getAllProducts(name)`
Get all products from all NFT contracts for a service provider and name.
```javascript
const allProducts = await sdk.getAllProducts("mydomain");
console.log("All products:", allProducts);
```
#### `createProvisionAndUpdateResolver(key, tokenURI, name, identifier)`
Create a provision and update the resolver for a specific key and identifier.
```javascript
const provisionInfo = {
name: "Premium Service",
description: "High-quality service package",
price: "100"
};
const result = await sdk.createProvisionAndUpdateResolver("service", provisionInfo, "mydomain", "premium");
console.log("Provision created:", result);
```
#### `createRecord(key, value, name)`
Create a text record for a specific key and value.
```javascript
const result = await sdk.createRecord("website", "https://example.com", "mydomain");
console.log("Record created:", result);
```
#### `createProductType(name, productType, productInfo)`
Create a new product type in the registry.
```javascript
const productInfo = {
name: "Premium Service",
description: "High-quality service package",
price: "100",
features: ["24/7 support", "Priority access"]
};
await sdk.createProductType("mydomain", "premium", productInfo);
```
#### `deployNFTContract(name)`
Deploy an NFT contract and add it to the resolver for a specific name.
```javascript
const nftInfo = await sdk.deployNFTContract("mydomain");
console.log("NFT contract deployed:", nftInfo.nftContractAddress);
```
#### `getNFTContracts(name)`
Get all NFT contracts associated with a specific name.
```javascript
const nftContracts = await sdk.getNFTContracts("mydomain");
console.log("NFT contracts:", nftContracts);
```
#### `createProduct(ens, productInfo, productType)`
Create a product by minting an NFT and attaching it to the resolver.
```javascript
const productInfo = {
name: "Product 1",
description: "Description of product 1"
};
const result = await sdk.createProduct("mydomain.global", productInfo, "standard");
console.log("Product created:", result);
```
#### `batchCreateProduct(ens, productInfos, productTypes)`
Batch create multiple products at once.
```javascript
const productInfos = [
{ name: "Product 1", description: "Description 1" },
{ name: "Product 2", description: "Description 2" }
];
const productTypes = ["standard", "premium"];
const results = await sdk.batchCreateProduct("mydomain.global", productInfos, productTypes);
console.log("Products created:", results);
```
#### `registerSubdomain(owner, label, name)`
Register a subdomain for a specific owner.
```javascript
const result = await sdk.registerSubdomain("0x123...", "api", "mydomain");
console.log("Subdomain registered:", result);
```
### �� Utility Functions
#### `getContractAddress(name)`
Get the address of a specific deployed contract.
```javascript
const ensAddress = sdk.getContractAddress("ENSRegistry");
console.log("ENS Registry:", ensAddress);
```
#### `getAllContractAddresses()`
Get all deployed contract addresses.
```javascript
const allAddresses = sdk.getAllContractAddresses();
console.log("All addresses:", allAddresses);
```
### š Network Information Methods
#### `getChainId()`
Get the current chainId.
```javascript
const chainId = sdk.getChainId();
console.log("Chain ID:", chainId);
```
#### `getNetworkName()`
Get the current network name.
```javascript
const networkName = sdk.getNetworkName();
console.log("Network:", networkName);
```
#### `getRpcUrl()`
Get the current RPC URL.
```javascript
const rpcUrl = sdk.getRpcUrl();
console.log("RPC URL:", rpcUrl);
```
#### `getExplorerUrl()`
Get the explorer URL for the current network.
```javascript
const explorerUrl = sdk.getExplorerUrl();
console.log("Explorer:", explorerUrl);
```
#### `getSupportedChainIds()`
Get all supported chainIds.
```javascript
const supportedChainIds = sdk.getSupportedChainIds();
console.log("Supported networks:", supportedChainIds);
```
#### `getAllNetworks()`
Get all network configurations.
```javascript
const allNetworks = sdk.getAllNetworks();
console.log("All networks:", allNetworks);
```
## TLD Support
The SDK supports any TLD (Top Level Domain) you specify. The TLD is automatically hashed to generate the correct node and label for ENS registration.
### Examples:
```javascript
// Deploy for .global
await sdk.deployContracts("global");
// Deploy for .test
await sdk.deployContracts("test");
// Deploy for .app
await sdk.deployContracts("app");
// Deploy for .company
await sdk.deployContracts("company");
// Deploy for .local
await sdk.deployContracts("local");
```
### TLD Hashing
The SDK automatically:
1. Uses `namehash.hash(tld)` to generate the TLD node
2. Uses `keccak256(tld)` to generate the TLD label
3. Sets up the base registrar as the owner of the TLD
4. Configures all contracts to work with the specified TLD
## RPC URL Support
The SDK works with any Ethereum RPC endpoint. Here are some common examples:
### Local Development
```javascript
const sdk = new ArnaconSDK(privateKey, "http://localhost:8545");
```
### Test Networks
```javascript
// Sepolia
const sdk = new ArnaconSDK(privateKey, "https://sepolia.infura.io/v3/YOUR_PROJECT_ID");
// Goerli
const sdk = new ArnaconSDK(privateKey, "https://goerli.infura.io/v3/YOUR_PROJECT_ID");
```
### Mainnet
```javascript
const sdk = new ArnaconSDK(privateKey, "https://mainnet.infura.io/v3/YOUR_PROJECT_ID");
```
### Other Providers
```javascript
// Alchemy
const sdk = new ArnaconSDK(privateKey, "https://eth-mainnet.alchemyapi.io/v2/YOUR_API_KEY");
// QuickNode
const sdk = new ArnaconSDK(privateKey, "https://your-endpoint.quiknode.pro/YOUR_API_KEY/");
```
## Environment Variables
Set these environment variables for IPFS functionality:
```bash
export PINATA_JWT_TOKEN="your_pinata_jwt_token" # For IPFS uploads
```
## Contract Address Storage
The SDK automatically saves deployed contract addresses to `deployed-addresses.json`. This allows you to:
- Reuse deployed contracts across sessions
- Avoid redeploying existing contracts
- Track all deployments for your RPC endpoint
## Gas Optimization
The SDK includes automatic gas estimation with:
- 20% buffer on gas estimates
- Fallback gas limits for failed estimations
- Configurable priority and max fees (25 gwei priority, 50 gwei max)
- Transaction execution with proper error handling
## Error Handling
All functions include comprehensive error handling:
```javascript
try {
await sdk.deployContracts("global");
} catch (error) {
console.error("Deployment failed:", error.message);
}
```
## Example Usage
See `example.js` for complete usage examples including:
- Full deployment workflow with custom TLDs
- Step-by-step deployment
- Contract address retrieval
- Error handling
- Multi-network deployment examples
- Multiple TLD deployment examples
## Running Examples
```bash
# Run the main example
node example.js
# Or import and use specific functions
const { main, deployStepByStep, deployWithDifferentTLDs } = require('./example');
await main();
```
## Key Differences from deploy.js
This SDK is designed to work independently of the hardhat runtime environment:
1. **Direct ethers usage**: Uses ethers v5.8.0 directly instead of hardhat's ethers
2. **RPC URL initialization**: Takes RPC URL directly instead of network names
3. **Contract factory creation**: Uses `ethers.getContractFactory()` directly
4. **Provider management**: Creates JsonRpcProvider from RPC URL
5. **Address storage**: Uses generic `deployed-addresses.json` file
6. **TLD flexibility**: Accepts any TLD parameter instead of hardcoded "global"
## Architecture
The SDK is built with a clean, modular architecture:
```
ArnaconSDK
āāā Constructor (privateKey, rpcUrl)
āāā Provider/Signer initialization
āāā Contract management
āāā Deploy functions
ā āāā deployContracts(tld)
ā āāā deployGSM()
ā āāā registerAsServiceProvider()
āāā Utility functions
ā āāā getContractAddress()
ā āāā getAllContractAddresses()
āāā Helper functions
āāā deployIfNeeded()
āāā getGasSettings()
āāā executeTransaction()
```
## Contributing
When adding new functionality to the SDK:
1. Follow the existing code structure
2. Include proper JSDoc comments
3. Add error handling
4. Update the README with new functions
5. Add examples to `example.js`
6. Ensure compatibility with ethers v5.8.0
## License
This SDK is part of the Arnacon project.