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

gainlings-sdk-viem

v1.0.34

Published

Gainlings SDK using Viem

Readme

Gainlings SDK

Usage

First install the SDK:

npm install gainlings-sdk-viem
# or
yarn add gainlings-sdk-viem

Then use the SDK:

import { GainlingsSDK, getLatestSeasonContractAddress } from "gainlings-sdk-viem";
import { createWalletClient, custom } from "viem";
import { arbitrumSepolia } from "viem/chains"; // Or your desired chain
import { parseEther, zeroAddress } from "viem"; // Need parseEther for value calculation, add zeroAddress for referrer example

// Define the contract addresses (Replace with actual addresses)
const managerAddress = "0xYOUR_MANAGER_CONTRACT_ADDRESS";
const marketPlaceContractAddress = "0xYOUR_MARKETPLACE_CONTRACT_ADDRESS";
const trophyAddress = "0xYOUR_TROPHY_CONTRACT_ADDRESS";

// Define your RPC endpoints. 
// An HTTP(S) endpoint is required for standard operations.
// A WebSocket (WSS) endpoint is required for real-time event subscriptions.
const HTTP_RPC_URL = "https://arb-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_API_KEY"; 
const WSS_RPC_URL = "wss://arb-sepolia.g.alchemy.com/v2/YOUR_ALCHEMY_WEBSOCKET_API_KEY"; // Provide if subscriptions are needed

async function main() {
  // Get the latest season contract address using the HTTP endpoint
  const latestSeasonContractAddress = await getLatestSeasonContractAddress(managerAddress, HTTP_RPC_URL); 
  console.log("Latest Season Contract Address: ", latestSeasonContractAddress);
  
  // Optional: Create a Wallet Client
  let walletClient;
  if (typeof window !== 'undefined' && window.ethereum) { 
    walletClient = createWalletClient({
      chain: arbitrumSepolia,
      transport: custom(window.ethereum)
    });
  } else {
    console.warn("No Ethereum browser provider found. Wallet functionality may be limited.");
  }
  
  // Create a new GainlingsSDK instance
  const gainlingsSdk = new GainlingsSDK(
    latestSeasonContractAddress,
    trophyAddress,
    marketPlaceContractAddress,
    arbitrumSepolia, // The viem Chain object    
    HTTP_RPC_URL,    // Required HTTP(S) RPC URL
    WSS_RPC_URL,     // Optional WebSocket (WSS) RPC URL for subscriptions
    walletClient     // Optional viem WalletClient       
  );
  
  // Example: Setup wallet 
  if (walletClient) {
    await gainlingsSdk.setupWallet();
    console.log("Connected Address:", gainlingsSdk.getAddress());
  }
  
  // --- Example: Minting Gainlings (Requires Wallet Client and Funds) --- 
  console.log("\n[Example] Minting Gainlings...");
  if (gainlingsSdk.walletClient && gainlingsSdk.address) {
    try {
        // 1. Get the required price per token 
        const contractInfo = await gainlingsSdk.gainlingsFactory.getContractInfo();
        const pricePerTokenEth = contractInfo.publicPrice; // e.g., '0.001'
        const pricePerTokenWei = parseEther(pricePerTokenEth); // Convert to bigint wei

        // 2. Define quantity and calculate total value
        const quantityToMint = 1;
        const totalValueWei = pricePerTokenWei * BigInt(quantityToMint);
        
        // 3. Define referrer (optional)
        const referrerAddress = zeroAddress; // Use zeroAddress if no referrer

        console.log(`  Attempting to mint ${quantityToMint} token(s).`);
        console.log(`  Price per token: ${pricePerTokenEth} ETH`);
        console.log(`  Referrer: ${referrerAddress}`);
        console.log(`  Value to send: ${totalValueWei} wei`);

        // --- Choose ONE of the following --- 
        
        // 4a. Call the mint function WITH referrer
        const mintTxHashWithRef = await gainlingsSdk.gainlingsFactory.mintQRNGWithReferrer(quantityToMint, referrerAddress, totalValueWei);
        console.log(`  ✅ Mint (with referrer) Tx Sent: ${mintTxHashWithRef}`);
        // const receiptWithRef = await gainlingsSdk.publicClient.waitForTransactionReceipt({ hash: mintTxHashWithRef });
        // console.log(`  ✅ Mint (with referrer) Tx Confirmed: Block ${receiptWithRef.blockNumber}`);

        /*
        // OR
        
        // 4b. Call the mint function WITHOUT referrer
        const mintTxHashNoRef = await gainlingsSdk.gainlingsFactory.mintQRNG(quantityToMint, totalValueWei);
        console.log(`  ✅ Mint (no referrer) Tx Sent: ${mintTxHashNoRef}`);
        // const receiptNoRef = await gainlingsSdk.publicClient.waitForTransactionReceipt({ hash: mintTxHashNoRef });
        // console.log(`  ✅ Mint (no referrer) Tx Confirmed: Block ${receiptNoRef.blockNumber}`);
        */
        
    } catch (error) {
      console.error(`  ❌ FAILED: Minting error.`, error);
    }
  } else {
    console.log("  ℹ️ SKIPPED: WalletClient not available or setupWallet not called.");
  }
  // ----------------------------------------------------------------------
  
  // Example: Get minted supply (uses HTTP client)
  try {
    let mintedSupply = await gainlingsSdk.gainlingsFactory.getMintedSupply();
    console.log("Gainlings Minted Supply: ", mintedSupply.toString()); 
  } catch (error) {
    console.error("Error getting minted supply:", error);
  }
  
  // Example: Subscribe to events (requires WSS_RPC_URL to be provided)
  if (WSS_RPC_URL) { // Only attempt if WSS URL was provided
      console.log("\nSubscribing to Gainling mint events (will run for 60s)...");
      let unwatchMints = null;
      try {
          // Call subscribe method directly on the SDK instance
          unwatchMints = gainlingsSdk.subscribeToMints((eventData) => {
              console.log("\n--- New Mint Event Received ---");
              console.log("Type:", eventData.type);
              console.log("Issuer:", eventData.data.issuer);
              console.log("Quantity:", eventData.data.quantity);
              console.log("Block:", eventData.event.blockNumber?.toString());
              console.log("-----------------------------\n");
          });
          console.log("Successfully subscribed to mint events.");
          await new Promise(resolve => setTimeout(resolve, 60000)); // Wait 60s
      } catch (error) {
          console.error("Error subscribing to mint events:", error);
      } finally {
          if (unwatchMints) {
              console.log("\nUnsubscribing from mint events...");
              unwatchMints(); 
              console.log("Unsubscribed.");
          }
      }
  } else {
      console.log("\nSkipping event subscription example as no WebSocket RPC URL was provided.");
  }

}

main().catch(console.error);

## Subscribing to Events

The SDK allows you to subscribe to real-time contract events using methods directly on the `GainlingsSDK` instance (e.g., `gainlingsSdk.subscribeToMints(...)`). 

For this functionality, you **must** initialize the SDK with both an `httpRpcUrl` and a `webSocketRpcUrl` (`wss://...`) in the constructor. The SDK uses the WebSocket URL exclusively for subscriptions.

```javascript
// Example assuming gainlingsSdk was initialized with both HTTP and WSS URLs

async function subscribeExample(gainlingsSdk) { 
  console.log("Subscribing to Gainling mint events...");
  let unwatch = null;
  try {
    // Pass a callback function to handle incoming events
    // Call the method directly on the SDK instance
    unwatch = gainlingsSdk.subscribeToMints((eventData) => {
      console.log("\n--- New Mint Event Received ---");
      console.log("Type:", eventData.type); // 'mint'
      console.log("Issuer:", eventData.data.issuer);
      console.log("Quantity:", eventData.data.quantity);
      console.log("Block:", eventData.event.blockNumber?.toString());
      console.log("-----------------------------\n");
    });

    console.log("Successfully subscribed. Listening for events...");
    // Keep the process alive or manage subscription state
    await new Promise(resolve => setTimeout(resolve, 120000)); // Wait 2 mins

  } catch (error) {
    console.error("Subscription error:", error);
  } finally {
    if (unwatch) {
      console.log("Unsubscribing...");
      unwatch(); 
      console.log("Unsubscribed.");
    }
  }
}

// Example call:
// const sdk = new GainlingsSDK(..., httpUrl, wssUrl, ...);
// subscribeExample(sdk).catch(console.error);

Similar subscribeTo... methods exist directly on the GainlingsSDK instance for other events like GainlingSeeded, GainlingApproached, and GainlingAttacked.

Build