npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

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-sdk

Quick Start

const ArnaconSDK = require("arnacon-sdk");

const sdk = new ArnaconSDK(privateKey, 137); // Polygon mainnet

The 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 errors

Contract 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