JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 19
  • Score
    100M100P100Q44206F
  • License MIT

A NextJS component that populates meta tags based on API key

Package Exports

  • rootstockwinks
  • rootstockwinks/dist/index.cjs
  • rootstockwinks/dist/index.mjs

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (rootstockwinks) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

Winks SDK (Rootstock)

A React/Next.js SDK that automatically populates SEO meta tags from a secure API and provides Rootstock-ready wallet integration, token/NFT utilities, signature management, and RPC failover.

Features

  • 🚀 Easy Integration: drop-in Winks wrapper for Next.js
  • 🔑 API-keyed metadata management (server included)
  • 📱 Social meta: Open Graph, Twitter Cards
  • 🎯 Full SEO meta coverage
  • 💰 Token utilities: ERC-20 transfer/approve/balance/allowance
  • 🎨 NFT utilities: ERC-721 owner, ERC-721/1155 transfers, ERC-1155 balance
  • 🔗 Rootstock ready (Mainnet 30, Testnet 31)
  • 🌐 Wallet integration via RainbowKit + WalletConnect
  • ✍️ Signature management (tx/message/personal/typed data)
  • 🔄 Network switching helpers
  • 🧭 RPC Management with health checks and latency-based selection
  • 🧩 EIP-1193 Provider adapter (MetaMask et al.)
  • 🧯 Signature queueing to avoid overlapping prompts
  • 🛠️ Dual builds (Rollup + Vite) outputting CJS + ESM
  • ✅ Testing setup (Jest unit, Playwright E2E)

Installation

npm install rootstockwinks

Quick Start (Next.js)

// pages/_app.js or app/layout.js
import { Winks } from 'rootstockwinks';

export default function App({ Component, pageProps }) {
  return (
    <Winks apikey="YOUR_API_KEY">
      <Component {...pageProps} />
    </Winks>
  );
}

Start the local metadata server and create an API key:

cd server
npm install
npm run build
npm start

# Create API Key
curl -X POST http://localhost:3001/api/keys \
  -H "Content-Type: application/json" \
  -d '{"name": "My Website"}'

# Set metadata
curl -X POST http://localhost:3001/api/meta/YOUR_API_KEY \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{
    "title": "My Awesome Website",
    "description": "The best website ever created",
    "ogTitle": "My Awesome Website",
    "ogDescription": "The best website ever created",
    "ogImage": "https://example.com/og-image.jpg",
    "ogUrl": "https://example.com",
    "twitterCard": "summary_large_image",
    "twitterTitle": "My Awesome Website",
    "twitterDescription": "The best website ever created",
    "twitterImage": "https://example.com/twitter-image.jpg",
    "canonical": "https://example.com",
    "robots": "index, follow",
    "viewport": "width=device-width, initial-scale=1",
    "charset": "utf-8",
    "author": "Your Name"
  }'

Winks Component

Props:

  • apikey: string required
  • children: ReactNode required
  • fallback?: MetaData (used if server fetch fails)

MetaData shape:

interface MetaData {
  title?: string;
  description?: string;
  keywords?: string;
  ogTitle?: string;
  ogDescription?: string;
  ogImage?: string;
  ogUrl?: string;
  twitterCard?: string;
  twitterTitle?: string;
  twitterDescription?: string;
  twitterImage?: string;
  canonical?: string;
  robots?: string;
  viewport?: string;
  charset?: string;
  author?: string;
}

RPC Manager

import { RpcManager } from 'rootstockwinks';

const rpc = new RpcManager();
const provider = rpc.createProvider('mainnet'); // or 'testnet'
const bestUrl = rpc.getBestRpcUrl('mainnet');
// Health snapshot
const health = rpc.getHealth('mainnet');
  • Periodic health checks (eth_blockNumber) with timeouts
  • Chooses lowest-latency healthy endpoint; fails over automatically

EIP-1193 Provider Adapter

import { Eip1193Provider } from 'rootstockwinks';

const eip = new Eip1193Provider(window.ethereum);
await eip.request({ method: 'eth_requestAccounts' });

Signature Manager (Queued)

import { SignatureManager, Eip1193Provider } from 'rootstockwinks';

const sm = new SignatureManager(new Eip1193Provider(window.ethereum));
// Requests are queued to avoid multiple wallet prompts
await sm.requestTransactionSignature({ to: '0x...', value: 0n });
await sm.requestMessageSignature('Hello Rootstock');
await sm.requestPersonalSignature('Personal message');
await sm.requestTypedDataSignature({ domain, types, value });

Wallet Integration (RainbowKit + wagmi)

Wrap your app:

import { WalletProvider } from 'rootstockwinks';

export default function App({ Component, pageProps }) {
  return (
    <WalletProvider>
      <Component {...pageProps} />
    </WalletProvider>
  );
}

Use the connection UI:

import { WalletConnection } from 'rootstockwinks';

function MyComponent() {
  return <WalletConnection showBalance showNetwork />;
}

Advanced hook:

import { useWalletIntegration } from 'rootstockwinks';

const {
  walletState,
  connectWallet,
  disconnectWallet,
  switchToRootstockMainnet,
  switchToRootstockTestnet,
  requestTransactionSignature,
  requestMessageSignature,
  requestPersonalSignature,
  requestTypedDataSignature,
  sendTransaction,
} = useWalletIntegration();

Enhanced Token Transfer Hook

import { useEnhancedTokenTransfer } from 'rootstockwinks';

const {
  transferERC20,
  transferNFT,
  approveToken,
  getTokenBalance,
  getNFTOwner,
  getTokenAllowance,
  ensureRootstockNetwork,
  address,
  isConnected,
} = useEnhancedTokenTransfer();

Simple Token/NFT Functions

import {
  transferERC20,
  approveToken,
  getTokenBalance,
  getTokenAllowance,
  getNFTOwner,
  transferNFT,
} from 'rootstockwinks';
import { ethers } from 'ethers';

const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();

await transferERC20('0xToken', '0xRecipient', '1.0', signer);
await approveToken('0xToken', '0xSpender', '100.0', signer);
const bal = await getTokenBalance('0xToken', '0xAccount', provider);
const allowance = await getTokenAllowance('0xToken', '0xOwner', '0xSpender', provider);
const owner = await getNFTOwner('0xNft', '123', provider);
await transferNFT('0xNft', '0xFrom', '0xTo', '123', signer);

Network Configuration

  • Rootstock Mainnet: Chain ID 30, RPC https://public-node.rsk.co, Explorer https://explorer.rootstock.io, Currency RBTC
  • Rootstock Testnet: Chain ID 31, RPC https://public-node.testnet.rsk.co, Explorer https://explorer.testnet.rootstock.io, Currency tRBTC

Server API (local metadata server)

  • GET /health
  • POST /api/keys{ id, key, name, createdAt, isActive }
  • GET /api/keys (auth)
  • DELETE /api/keys/:key (auth)
  • GET /api/meta/:apiKey → returns MetaData
  • POST /api/meta/:apiKey (auth) { metadata: MetaData }
  • PUT /api/meta/:apiKey (auth) { metadata: MetaData }
  • DELETE /api/meta/:apiKey (auth)

Auth header: X-API-Key: {apiKey}

Development

Build

npm run build           # TypeScript + Rollup (CJS + ESM)
npm run build:vite      # Vite library build (optional)

Testing

npm test                # Jest unit tests
npx playwright install chromium
npm run test:e2e        # Playwright (ensure example app is running or use a prod build)

License

MIT

Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Commit your changes: git commit -m 'Add some amazing feature'
  4. Push: git push origin feature/amazing-feature
  5. Open a Pull Request