arnacon-sdk
v1.0.41
Published
A comprehensive SDK for deploying and managing Arnacon smart contracts across multiple networks
Readme
Arnacon SDK
A single-class SDK that wraps Arnacon's entire blockchain backend — ENS domains, service providers, identity proofs, token operations — so any developer can integrate with one import and one initialization.
Installation
npm install arnacon-sdkQuick Start
const ArnaconSDK = require("arnacon-sdk");
const sdk = new ArnaconSDK(privateKey, 137); // Polygon mainnetThe second argument can be a chain ID (recommended), an RPC URL, or an existing ethers Signer object.
// Chain ID (recommended)
const sdk = new ArnaconSDK(privateKey, 137);
// RPC URL
const sdk = new ArnaconSDK(privateKey, "https://polygon-rpc.com");
// Existing signer
const sdk = new ArnaconSDK(privateKey, existingSigner);Supported Networks
| Chain ID | Network | RPC | |----------|---------|-----| | 137 | Polygon | https://polygon-rpc.com | | 23295 | Oasis Sapphire | https://1rpc.io/oasis/sapphire | | 23294 | Oasis Sapphire Testnet | https://testnet.sapphire.oasis.dev | | 80002 | Polygon Amoy | https://rpc-amoy.polygon.technology | | 31337 | Hardhat Local | http://localhost:8545 |
Domain Administration
This is the primary use case. As a domain admin you deploy the system, purchase names, and manage subdomains.
1. Deploy the Core System
// Deploy ENS infrastructure (registry, registrar, resolver, name wrapper, etc.)
await sdk.deployContracts("global");
// Deploy Global Service Management (GlobalRegistrarController, ProvisionRegistry, etc.)
await sdk.deployGSM();2. Register as a Domain Owner
// Deploys your SecondLevelInteractor, resolver, ProductTypeRegistry, and NFT contracts
await sdk.registerAsDomainOwner("mydomain");3. Purchase a Domain Name
// Purchase "mydomain.global" for 365 days
await sdk.purchaseName("mydomain", 365);4. Register Subdomains
// Register "alice.mydomain.global" owned by the given address
await sdk.registerSubdomain("0xAliceAddress...", "alice", "mydomain");5. Manage DNS-like Records
// Set a text record
await sdk.createRecord("website", "https://example.com", "mydomain");
// Read it back
const website = await sdk.getRecord("website", "mydomain");6. Query Domain Info
// Owner of a name
const owner = await sdk.getOwner("mydomain");
// Expiry timestamp
const expiry = await sdk.getExpiry("mydomain.global");
// All names registered to an address
const names = await sdk.getRegisteredNames();
// Full data for a name (owner, resolver, records, etc.)
const data = await sdk.getData("alice.mydomain.global");Service Providers
Register as a service provider, create services, and let users purchase products.
Registration & Services
// Register as a service provider (providerInfo is metadata uploaded to IPFS)
await sdk.registerAsServiceProvider({ name: "My Company", description: "..." });
// Create a service
await sdk.createService("premium-plan", { name: "Premium", features: ["..."] }, 100, 2592000);
// Update a service
await sdk.updateService("premium-plan", { name: "Premium v2" }, 150, 2592000);
// Query services
const services = await sdk.getServicesForProvider(providerAddress);
const service = await sdk.getService("premium-plan");
const metadata = await sdk.getServiceProviderMetadata(providerAddress);Products & NFTs
// Deploy an NFT contract for a domain
await sdk.deployNFTContract("mydomain");
// Create a product type
await sdk.createProductType("mydomain", "standard", { name: "Basic Plan", price: "50" });
// Mint a product
await sdk.createProduct("alice", "mydomain", { name: "Product 1" }, "standard");
// Batch mint
await sdk.batchCreateProduct("mydomain.global", [info1, info2], ["standard", "premium"]);
// Query products
const types = await sdk.getProductTypes("mydomain");
const allProducts = await sdk.getAllProducts("mydomain");
const nftContracts = await sdk.getNFTContracts("mydomain");
// Burn an NFT
await sdk.burnNFT("mydomain", tokenId);Provisions
await sdk.createProvisionAndUpdateResolver("key", tokenURI, "mydomain", "identifier");
const provision = await sdk.getProvision("mydomain", "identifier");
await sdk.replaceProvision("key", newTokenURI);PALO Token
// Send PALO tokens to an address
await sdk.sendPalo(amount, "0xRecipient...");Semaphore (Zero-Knowledge Proofs)
Privacy-preserving subdomain registration using Semaphore. Users can prove group membership and claim a subdomain without revealing their identity.
// Deploy the Semaphore system
await sdk.deploySemaphoreInteractor();
// Domain admin inserts a commitment for a label
const { userSecret, commitment } = await sdk.insertCommitment("alice");
// User creates an identity from their secret
const identity = sdk.createIdentity(userSecret, "alice");
// User generates a proof and registers the subdomain
await sdk.registerWithProof(userSecret, "alice", "mydomain", "0xOwnerAddress...");
// Get the deployed Semaphore contract address
const addr = sdk.getSemaphoreInteractorAddress();Blockchain Explorer
Read-only queries against deployed contracts.
const owner = await sdk.getOwner("mydomain");
const ensOwner = await sdk.getEnsOwner("mydomain");
const wrapperOwner = await sdk.getWrapperOwner("mydomain");
const expiry = await sdk.getExpiry("mydomain.global");
const resolver = await sdk.getResolver("alice.mydomain.global");
const ttl = await sdk.getTTL("alice.mydomain.global");
const names = await sdk.getRegisteredNames(address);
const data = await sdk.getData("alice.mydomain.global");
const service = await sdk.getRegisteredServiceForSubname("alice.mydomain.global");IPFS
Upload and fetch metadata via Pinata. Requires the PINATA_JWT_TOKEN environment variable.
const uri = await sdk.uploadToIPFS({ name: "My Item", description: "..." });
const metadata = await sdk.fetchFromIPFS(uri);Advanced: Dynamic Controller Transactions
Execute arbitrary contract calls through the SecondLevelController.
// With pre-encoded data
await sdk.executeControllerTransaction(targetAddress, encodedData, value);
// With ABI encoding handled for you
await sdk.executeControllerTransactionWithABI(targetAddress, abi, "functionName", [arg1, arg2]);
// Encoding helpers
const data = sdk.encodeFunctionCall(abi, "functionName", [arg1]);
const result = sdk.decodeFunctionResult(abi, "functionName", returnData);Contract Management
const address = sdk.getContractAddress("ENSRegistry");
const all = sdk.getAllContractAddresses();
const exists = sdk.hasContract("PublicResolver");Upgradeable Contracts
await sdk.deployProviderRegistryUpgradeable();
await sdk.upgradeContract("ProxyName", "NewImplementation");Ownership
await sdk.transferAllOwnership("0xNewOwner...");
await sdk.makeWrapperController("0xControllerAddress...");Configuration
Logging
sdk.setLogLevel("silent"); // "debug" | "info" | "warn" | "error" | "silent"
// Plug in your own logger
sdk.setLogger({
log: (msg) => myLogger.info(msg),
warn: (msg) => myLogger.warn(msg),
error: (msg) => myLogger.error(msg),
});Network Info
sdk.getChainId();
sdk.getNetworkName();
sdk.getRpcUrl();
sdk.getExplorerUrl();
sdk.getSupportedChainIds();
sdk.getAllNetworks();Signer & Provider
sdk.getSignerAddress();
sdk.getSigner();
sdk.getProvider();Architecture
ArnaconSDK (index.js)
│
├── DeploymentManager — contract deployment, gas, transactions
├── ServiceProviderManager — domain ownership, products, NFTs, services
├── SemaphoreManager — ZK proof identity and registration
├── BlockchainExplorer — read-only chain queries
├── ContractFactoryLoader — ABI/bytecode loading
├── IPFSManager — Pinata upload/fetch
├── SignatureUtils — signature generation
├── NetworkConfig — chain ID → RPC/explorer mapping
├── logger — pluggable log backend
└── ArnaconSDKError — typed SDK errorsContract Address Storage
The SDK ships with global infrastructure addresses (ENSRegistry, GlobalRegistrarController, etc.) for each supported network. These are read-only and bundled inside the package.
When you deploy your own contracts (e.g. registerAsDomainOwner, deploySemaphoreInteractor), the addresses are saved to a .arnacon/ directory in your project root. On subsequent runs the SDK merges both: global addresses from the package, overlaid with your local addresses.
Add .arnacon/ to your .gitignore — it contains wallet-specific deployment state:
# .gitignore
.arnacon/Environment Variables
| Variable | Purpose |
|----------|---------|
| PINATA_JWT_TOKEN | Required for IPFS uploads |
License
MIT
