{"_id":"555x402-vap","_rev":"2-9d28ec67c5a2e66265b91148549efadb","name":"555x402-vap","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"555x402-vap","version":"0.1.0","keywords":["attention","vap","rewards","solana","web3","verification","engagement"],"author":{"name":"Render Network OS"},"license":"MIT","_id":"555x402-vap@0.1.0","maintainers":[{"name":"rndrntwrk","email":"555rendernet.work@gmail.com"}],"homepage":"https://github.com/Render-Network-OS/555x402-vap-sdk#readme","bugs":{"url":"https://github.com/Render-Network-OS/555x402-vap-sdk/issues"},"dist":{"shasum":"bc6c5c59df82a55264221dd6b9fc73025818c03c","tarball":"https://registry.npmjs.org/555x402-vap/-/555x402-vap-0.1.0.tgz","fileCount":4,"integrity":"sha512-xdNSdWL0XY0vnLUzRXZVi5kmVyGCDbHSCZ/onTtZOP6rXo3tJbrzVxzIwtXuGsVYKTLvwEytZoBHrR6QM4tJbA==","signatures":[{"sig":"MEQCID8mRB8WBpk2iDsQOGuypR4eT1T+N56fCfO8Q9bBE2ciAiA0qojVWDiOkfz5H16KkpiocZ9yIACsf8dkFso+j9B67A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":15695},"main":"dist/index.js","type":"module","types":"dist/index.d.ts","engines":{"node":">=18.0.0"},"gitHead":"72f256dabea5d327b23b6396b2d78f88fc2842f3","scripts":{"build":"tsc -p tsconfig.json","pack:dry":"npm pack","publish:dry":"npm publish --dry-run","prepublishOnly":"npm run build"},"_npmUser":{"name":"rndrntwrk","email":"555rendernet.work@gmail.com"},"repository":{"url":"git+https://github.com/Render-Network-OS/555x402-vap-sdk.git","type":"git"},"_npmVersion":"10.8.2","description":"Verifiable Attention Protocol SDK - Earn rewards for real, verified attention","directories":{},"_nodeVersion":"20.19.5","_hasShrinkwrap":false,"devDependencies":{"typescript":"^5.6.2","@types/node":"^20.0.0"},"_npmOperationalInternal":{"tmp":"tmp/555x402-vap_0.1.0_1762897833163_0.9502144242318165","host":"s3://npm-registry-packages-npm-production"}}},"time":{"created":"2025-11-11T21:50:33.062Z","modified":"2025-12-27T05:41:42.031Z","0.1.0":"2025-11-11T21:50:33.384Z"},"bugs":{"url":"https://github.com/Render-Network-OS/555x402-vap-sdk/issues"},"author":{"name":"Render Network OS"},"license":"MIT","homepage":"https://github.com/Render-Network-OS/555x402-vap-sdk#readme","keywords":["attention","vap","rewards","solana","web3","verification","engagement"],"repository":{"url":"git+https://github.com/Render-Network-OS/555x402-vap-sdk.git","type":"git"},"description":"Verifiable Attention Protocol SDK - Earn rewards for real, verified attention","maintainers":[{"email":"555rendernet.work@gmail.com","name":"glassprism"}],"readme":"# @vap/sdk\n\n> Verifiable Attention Protocol SDK - Earn rewards for real, verified attention on any platform\n\n[![npm version](https://img.shields.io/npm/v/@vap/sdk.svg)](https://www.npmjs.com/package/@vap/sdk)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n## Overview\n\nVAP (Verifiable Attention Protocol) enables platforms to reward users for genuine attention through cryptographic proof-of-attention. Users earn micro-rewards by proving they're actively engaged through WebSocket heartbeat challenges.\n\n**How it works:**\n1. User connects to VAP session via WebSocket\n2. Server sends cryptographic challenges every 5 seconds\n3. User's wallet signs challenges proving presence\n4. Server validates signatures and accumulates attention credits\n5. Rewards paid out instantly or accumulated for batch settlement\n\n## Features\n\n- ✅ **Cryptographic Proof**: Ed25519 signature-based attention verification\n- ✅ **Real-Time Rewards**: Instant micro-payments for verified attention\n- ✅ **State Channels**: Off-chain accumulation with on-chain settlement\n- ✅ **Wallet Agnostic**: Works with any Solana wallet or embedded wallet\n- ✅ **Framework Agnostic**: Vanilla JS, React, Vue, Svelte\n- ✅ **Auto-Reconnect**: Handles disconnections gracefully\n- ✅ **TypeScript**: Full type safety\n\n## Installation\n\n```bash\nnpm install @vap/sdk\n# or\npnpm add @vap/sdk\n# or  \nyarn add @vap/sdk\n```\n\n## Quick Start\n\n### Vanilla JavaScript\n\n```typescript\nimport { VapClient } from '@vap/sdk';\n\nconst client = new VapClient({\n  wsUrl: 'wss://vap.rendernet.work/session?uid=user123&cid=channel456'\n});\n\n// Set up wallet signer\nclient.setSigner(async (message) => {\n  // Sign with your wallet\n  const signature = await wallet.signMessage(message);\n  return signature;\n});\n\n// Handle rewards\nclient.onReward((amount, unit) => {\n  console.log(`Earned ${amount} ${unit}!`);\n  // Update UI, show notification, etc.\n});\n\n// Start session\nclient.startVap();\n\n// Stop when user leaves\nclient.stop();\n```\n\n### React Integration\n\n```tsx\nimport { VapClient } from '@vap/sdk';\nimport { useWallet } from '@solana/wallet-adapter-react';\nimport { useEffect, useState } from 'react';\n\nexport function useVapSession(userId: string, channelId: string) {\n  const { signMessage, publicKey } = useWallet();\n  const [totalRewards, setTotalRewards] = useState(0);\n  const [client, setClient] = useState<VapClient | null>(null);\n  \n  useEffect(() => {\n    if (!publicKey || !signMessage) return;\n    \n    const vapClient = new VapClient({\n      wsUrl: `wss://vap.rendernet.work/session?uid=${userId}&cid=${channelId}`\n    });\n    \n    // Configure signer\n    vapClient.setSigner(async (msg) => {\n      const sig = await signMessage(msg);\n      return sig;\n    });\n    \n    // Handle rewards\n    vapClient.onReward((amount, unit) => {\n      setTotalRewards(prev => prev + amount);\n      console.log(`+${amount} ${unit}`);\n    });\n    \n    // Start session\n    vapClient.startVap();\n    setClient(vapClient);\n    \n    // Cleanup on unmount\n    return () => vapClient.stop();\n  }, [publicKey, signMessage, userId, channelId]);\n  \n  return { totalRewards, isActive: !!client };\n}\n\n// Usage in component:\nfunction VideoPlayer() {\n  const { totalRewards } = useVapSession('user-123', 'video-456');\n  \n  return (\n    <div>\n      <video src=\"...\" />\n      <div className=\"rewards-badge\">\n        Earned: ${totalRewards.toFixed(4)} SOL\n      </div>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### Class: `VapClient`\n\n#### Constructor\n\n```typescript\nnew VapClient(options: VapOptions)\n```\n\n**Options:**\n```typescript\ninterface VapOptions {\n  wsUrl: string;  // WebSocket URL with user/channel params\n}\n```\n\n**Example:**\n```typescript\nconst client = new VapClient({\n  wsUrl: 'wss://vap.rendernet.work/session?uid=alice&cid=stream-789'\n});\n```\n\n#### Methods\n\n##### `setSigner(fn: SignerFunction): void`\n\nConfigures the message signing function.\n\n**Parameters:**\n```typescript\ntype SignerFunction = (message: Uint8Array) => Promise<Uint8Array>;\n```\n\n**Example with Phantom:**\n```typescript\nclient.setSigner(async (msg) => {\n  const signature = await window.solana.signMessage(msg, 'utf8');\n  return signature.signature;\n});\n```\n\n**Example with Privy:**\n```typescript\nimport { useSolanaWallets } from '@privy-io/react-auth/solana';\n\nconst { wallets } = useSolanaWallets();\nconst wallet = wallets[0];\n\nclient.setSigner(async (msg) => {\n  const sig = await wallet.signMessage(msg);\n  return new Uint8Array(sig);\n});\n```\n\n##### `onReward(handler: RewardHandler): void`\n\nSets the reward callback handler.\n\n**Parameters:**\n```typescript\ntype RewardHandler = (amount: number, unit: string) => void;\n```\n\n**Example:**\n```typescript\nclient.onReward((amount, unit) => {\n  // Update state\n  setEarnings(prev => prev + amount);\n  \n  // Show toast notification\n  toast.success(`+${amount} ${unit}`);\n  \n  // Track analytics\n  analytics.track('reward_earned', { amount, unit });\n});\n```\n\n##### `startVap(): void`\n\nInitiates the VAP session and WebSocket connection.\n\n**Example:**\n```typescript\nclient.startVap();\n```\n\n##### `stop(): void`\n\nStops the session and closes WebSocket connection.\n\n**Example:**\n```typescript\n// When user navigates away\nwindow.addEventListener('beforeunload', () => {\n  client.stop();\n});\n```\n\n##### `connect(): void`\n\nManually connect/reconnect to WebSocket (called automatically by `startVap()`).\n\n## Advanced Usage\n\n### Auto-Reconnect with Exponential Backoff\n\n```typescript\nimport { VapClient } from '@vap/sdk';\n\nclass ResilientVapClient extends VapClient {\n  private reconnectAttempts = 0;\n  private maxReconnectDelay = 30000;\n  \n  connect() {\n    super.connect();\n    \n    if (this.ws) {\n      this.ws.onclose = () => {\n        const delay = Math.min(\n          1000 * Math.pow(2, this.reconnectAttempts),\n          this.maxReconnectDelay\n        );\n        \n        console.log(`Reconnecting in ${delay}ms...`);\n        \n        setTimeout(() => {\n          this.reconnectAttempts++;\n          this.connect();\n        }, delay);\n      };\n      \n      this.ws.onopen = () => {\n        this.reconnectAttempts = 0;\n        console.log('VAP connected');\n      };\n    }\n  }\n}\n```\n\n### Session Analytics\n\n```typescript\nclass AnalyticsVapClient extends VapClient {\n  private sessionStart = Date.now();\n  private heartbeatsCount = 0;\n  private rewardsCount = 0;\n  \n  constructor(opts: VapOptions) {\n    super(opts);\n    \n    // Track heartbeats\n    this.onMessage((data) => {\n      if (data.nonce) {\n        this.heartbeatsCount++;\n      }\n    });\n    \n    // Track rewards\n    this.onReward((amount) => {\n      this.rewardsCount++;\n    });\n  }\n  \n  getSessionStats() {\n    return {\n      duration: Date.now() - this.sessionStart,\n      heartbeats: this.heartbeatsCount,\n      rewards: this.rewardsCount,\n      avgRewardInterval: this.heartbeatsCount / (this.rewardsCount || 1)\n    };\n  }\n}\n```\n\n### Multiple Concurrent Sessions\n\n```typescript\n// User watching multiple streams simultaneously\nconst sessions = [\n  new VapClient({ wsUrl: 'wss://vap.../session?cid=stream1' }),\n  new VapClient({ wsUrl: 'wss://vap.../session?cid=stream2' }),\n  new VapClient({ wsUrl: 'wss://vap.../session?cid=stream3' })\n];\n\n// Configure all with same signer\nsessions.forEach(client => {\n  client.setSigner(walletSigner);\n  client.onReward((amt, unit) => {\n    console.log(`Earned ${amt} ${unit} from ${client.opts.wsUrl}`);\n  });\n  client.startVap();\n});\n\n// Stop all on page unload\nwindow.addEventListener('beforeunload', () => {\n  sessions.forEach(c => c.stop());\n});\n```\n\n## WebSocket Protocol\n\n### Connection\n\n```\nwss://vap.rendernet.work/session?uid=<userId>&cid=<channelId>\n```\n\n**Query Parameters:**\n- `uid` - Unique user identifier\n- `cid` - Channel/content identifier\n\n### Message Flow\n\n**Server → Client (Challenge):**\n```json\n{\n  \"nonce\": \"abc123...\",\n  \"seq\": 1,\n  \"ts\": 1699564800000\n}\n```\n\n**Client → Server (Response):**\n```json\n{\n  \"userId\": \"alice\",\n  \"channelId\": \"stream-789\",\n  \"seq\": 1,\n  \"sig\": \"base64_signature\",\n  \"pubkey\": \"base64_public_key\",\n  \"cts\": 1699564801000\n}\n```\n\n**Server → Client (Reward):**\n```json\n{\n  \"reward\": {\n    \"amount\": 0.0001,\n    \"unit\": \"SOL\"\n  }\n}\n```\n\n## Examples\n\n### Next.js App with Privy\n\n```tsx\n'use client';\n\nimport { VapClient } from '@vap/sdk';\nimport { usePrivy, useSolanaWallets } from '@privy-io/react-auth';\nimport { useEffect, useState } from 'react';\n\nexport default function VideoWithRewards() {\n  const { authenticated, login } = usePrivy();\n  const { wallets } = useSolanaWallets();\n  const [earnings, setEarnings] = useState(0);\n  \n  useEffect(() => {\n    if (!authenticated || wallets.length === 0) return;\n    \n    const wallet = wallets[0];\n    const client = new VapClient({\n      wsUrl: `wss://vap.rendernet.work/session?uid=${wallet.address}&cid=video-123`\n    });\n    \n    client.setSigner(async (msg) => {\n      const sig = await wallet.signMessage(msg);\n      return new Uint8Array(sig);\n    });\n    \n    client.onReward((amount) => {\n      setEarnings(prev => prev + amount);\n    });\n    \n    client.startVap();\n    \n    return () => client.stop();\n  }, [authenticated, wallets]);\n  \n  if (!authenticated) {\n    return (\n      <button onClick={login} className=\"...\">\n        Connect to Earn Rewards\n      </button>\n    );\n  }\n  \n  return (\n    <div>\n      <video src=\"content.mp4\" controls />\n      <div className=\"earnings\">\n        You've earned: ${earnings.toFixed(4)}\n      </div>\n    </div>\n  );\n}\n```\n\n### Vanilla JS (No Framework)\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n  <script type=\"module\">\n    import { VapClient } from 'https://esm.sh/@vap/sdk';\n    \n    const client = new VapClient({\n      wsUrl: 'wss://vap.rendernet.work/session?uid=user&cid=page'\n    });\n    \n    // Setup signer (Phantom example)\n    client.setSigner(async (msg) => {\n      const resp = await window.solana.signMessage(msg, 'utf8');\n      return resp.signature;\n    });\n    \n    // Handle rewards\n    client.onReward((amount, unit) => {\n      document.getElementById('earnings').textContent = \n        `Earned: ${amount} ${unit}`;\n    });\n    \n    // Start on page load\n    client.startVap();\n    \n    // Stop on page unload\n    window.addEventListener('beforeunload', () => client.stop());\n  </script>\n</head>\n<body>\n  <div id=\"earnings\">Earned: 0 SOL</div>\n  <div>Watch content to earn...</div>\n</body>\n</html>\n```\n\n## Configuration\n\n### Environment Variables\n\n```bash\n# WebSocket endpoint (optional, defaults to production)\nNEXT_PUBLIC_VAP_WS_URL=wss://vap.rendernet.work/session\n\n# User identifier\nNEXT_PUBLIC_USER_ID=user-abc-123\n\n# Channel identifier  \nNEXT_PUBLIC_CHANNEL_ID=content-xyz-789\n```\n\n## Troubleshooting\n\n### WebSocket Connection Fails\n\n**Symptom**: `onclose` fires immediately after `connect()`\n\n**Solutions:**\n- Check network connectivity\n- Verify WebSocket URL format\n- Check CORS headers (should allow your origin)\n- Ensure uid and cid params are present\n\n### Signature Verification Fails\n\n**Symptom**: No rewards despite heartbeats\n\n**Solutions:**\n- Verify `setSigner` is called before `startVap()`\n- Check wallet is connected and can sign messages\n- Ensure signature format is raw bytes (Uint8Array)\n- Test with `console.log` in signer function\n\n### Rewards Not Triggering\n\n**Symptom**: Connected but `onReward` never fires\n\n**Solutions:**\n- Verify server-side VAP session is active\n- Check minimum attention threshold (usually 30 seconds)\n- Ensure channel has rewards enabled\n- Check server logs for signature validation errors\n\n## Security\n\n### Message Signing\n\n- All heartbeat responses must be signed with user's private key\n- Server validates Ed25519 signatures on-chain public key\n- Replay attacks prevented via sequence numbers and timestamps\n- No private keys transmitted over WebSocket\n\n### Privacy\n\n- No PII transmitted (only wallet addresses)\n- Session data encrypted in transit (WSS)\n- Minimal fingerprinting (only UA for fraud detection)\n\n## Performance\n\n**Typical metrics:**\n- WebSocket latency: <100ms\n- Heartbeat interval: 5 seconds\n- Signature verification: <10ms\n- Reward accumulation: off-chain (instant)\n- Settlement: batched every 5 minutes or on-demand\n\n## Changelog\n\n### v0.1.0 (2025-11-11)\n- Initial release\n- WebSocket client with heartbeat challenges\n- Reward handler\n- TypeScript support\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md)\n\n## License\n\nMIT © 555x402\n\n## Support\n\n- **Docs**: https://docs.rendernet.work/vap\n- **Issues**: https://github.com/Render-Network-OS/555x402-vap-sdk/issues\n- **Discord**: https://discord.gg/555x402\n\n## Related Packages\n\n- [@555x402/agg](https://www.npmjs.com/package/@555x402/agg) - Payment aggregation\n- [@555x402/hyperlink](https://www.npmjs.com/package/@555x402/hyperlink) - Payment links\n\n---\n\n**Earn while you engage** 🎯\n","readmeFilename":"README.md"}