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
Winkswrapper 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 rootstockwinksQuick 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: stringrequiredchildren: ReactNoderequiredfallback?: 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, Explorerhttps://explorer.rootstock.io, Currency RBTC - Rootstock Testnet: Chain ID 31, RPC
https://public-node.testnet.rsk.co, Explorerhttps://explorer.testnet.rootstock.io, Currency tRBTC
Server API (local metadata server)
GET /healthPOST /api/keys→{ id, key, name, createdAt, isActive }GET /api/keys(auth)DELETE /api/keys/:key(auth)GET /api/meta/:apiKey→ returnsMetaDataPOST /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
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m 'Add some amazing feature' - Push:
git push origin feature/amazing-feature - Open a Pull Request