stacksagent 1.2.3 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,41 @@
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,javascript,pagination,swr-pagination,"SWR-based pagination for transactions","const fetcher = (url: string) => fetch(url).then(res => res.json()); const {data isLoading} = useSWR(`/api/activities?page=${page}&limit=${limit}` fetcher { keepPreviousData: true }); const totalPages = useMemo(() => data?.total ? Math.ceil(data.total / limit) : 0 [data?.total limit])","import useSWR from 'swr'; import { useMemo } from 'react'","keepPreviousData prevents flicker during page changes; calculate pages in useMemo"
3
+ 2,javascript,activities,activity-summary-stats,"Fetch and display activity summary statistics","const {data: summaryData} = useSWR('/api/activities_summary' fetcher); const stats = { dailyVolume: summaryData?.daily_volume_stx || 0 dailyVolumeUsd: summaryData?.daily_volume_usd || 0 uniqueAddresses: summaryData?.unique_addresses || 0 totalTxs: summaryData?.total_transactions || 0 }","import useSWR from 'swr'","Aggregate metrics for dashboard; combine with STX price API for USD conversion"
4
+ 3,javascript,activities,format-activity-type,"Color-code transaction types in activity feed","const getActivityColor = (type: string) => { switch(type) { case 'BUY': return '#22c55e'; case 'SELL': return '#ef4444'; case 'TRANSFER': return '#3b82f6'; default: return '#6b7280' }}; const getBadgeClass = (type: string) => `bg-${getActivityColor(type)} text-white px-2 py-1 rounded`","None","Consistent color coding: green=buy red=sell blue=transfer gray=other"
5
+ 4,javascript,launchpad,token-deployment-flow,"No-code token deployment with template replacement","const deployToken = async (metadata) => { const contractCode = await replacePlaceholders(templateCode { TOKEN_NAME: metadata.name TOKEN_SYMBOL: metadata.symbol TOKEN_SUPPLY: metadata.supply TOKEN_DECIMALS: metadata.decimals TOKEN_URI: metadataUrl }); const response = await request('stx_deployContract' { name: metadata.slug clarityCode: contractCode clarityVersion: 3 network: 'mainnet' postConditions: [paymentPostCondition] fee: 100000 }); return response.txid }","import { request } from '@stacks/connect'","Upload logo/metadata first; replace template placeholders; deploy with payment post-condition"
6
+ 5,javascript,launchpad,flexible-deployment-payment,"Accept multiple payment tokens for deployment","const buildPaymentPostCondition = (paymentToken amount userAddress) => { if (paymentToken === 'STX') { return Pc.principal(userAddress).willSendEq(amount).ustx() } else { const [contractAddr contractName assetName] = paymentToken.split('.'); return Pc.principal(userAddress).willSendEq(amount).ft(contractAddr + '.' + contractName assetName) }}","import { Pc } from '@stacks/transactions'","Support STX or custom tokens (WELSH VELAR); calculate equivalent amounts; add 0.1% token allocation"
7
+ 6,javascript,launchpad,metadata-upload-ipfs,"Upload token metadata to IPFS via API","const uploadMetadata = async (tokenData) => { const metadata = { name: tokenData.name description: tokenData.description image: tokenData.logoUrl xlink: tokenData.twitter homepage: tokenData.website telegram: tokenData.telegram discord: tokenData.discord }; const formData = new FormData(); formData.append('file' new Blob([JSON.stringify(metadata)] {type: 'application/json'})); formData.append('type' 'uri'); const response = await fetch('/api/upload' {method: 'POST' body: formData}); return response.json().url }","None (FormData native)","Upload logo first then metadata JSON; type='uri' for metadata type='logo' for images"
8
+ 7,javascript,presale,presale-wizard-state,"Multi-step wizard state management for presale creation","const [currentStep setCurrentStep] = useState(1); const [presaleData setPresaleData] = useState({ tokenAddress: '' softCap: 0 hardCap: 0 minBuy: 0 maxBuy: 0 tokenPrice: 0 liquidityPercent: 70 startBlock: 0 endBlock: 0 whitelistEnabled: false vestingMilestones: [] }); const nextStep = () => setCurrentStep(prev => Math.min(prev + 1 6)); const prevStep = () => setCurrentStep(prev => Math.max(prev - 1 1))","import { useState } from 'react'","6-step wizard: token selection → parameters → AMM config → timeframe → vesting → deploy"
9
+ 8,javascript,presale,vesting-milestone-config,"Configure token vesting milestones for presale","const [vestingMilestones setVestingMilestones] = useState([ { blockHeight: startBlock + 2100 percentage: 25 description: 'First unlock' } { blockHeight: startBlock + 4200 percentage: 25 description: 'Second unlock' } { blockHeight: startBlock + 6300 percentage: 50 description: 'Final unlock' } ]); const totalPercentage = vestingMilestones.reduce((sum m) => sum + m.percentage 0); const isValid = totalPercentage === 100","import { useState } from 'react'","Block-based vesting; 2100 blocks ≈ 2 weeks; validate total = 100%"
10
+ 9,javascript,presale,presale-participation-tx,"Build presale participation transaction","const participateInPresale = async (presaleContract amount) => { const response = await request('stx_callContract' { contract: presaleContract functionName: 'participate' functionArgs: [] postConditions: [ Pc.principal(userAddress).willSendEq(amount).ustx() ] postConditionMode: 'deny' network: 'mainnet' fee: 100000 }); return response }","import { request } from '@stacks/connect'; import { Pc } from '@stacks/transactions'","Post-condition protects buyer; contract validates min/max buy limits; check whitelist status first"
11
+ 10,javascript,presale,claim-vested-tokens,"Claim vested tokens from presale","const claimVestedTokens = async (presaleContract milestoneIndex) => { const response = await request('stx_callContract' { contract: presaleContract functionName: 'claim-milestone' functionArgs: [uintCV(milestoneIndex)] postConditions: [ Pc.principal(presaleContract).willSendGte(0).ft(tokenContract tokenName) ] network: 'mainnet' }); return response }","import { request } from '@stacks/connect'; import { Pc uintCV } from '@stacks/transactions'","Milestone-based claiming; check block height >= milestone block; partial claims supported"
12
+ 11,javascript,lottery,lottery-status-fetch,"Fetch current lottery round status","const getLotteryStatus = async () => { const response = await fetch('/api/lottery-4-winners/contract-calls/get-lottery-status'); const data = await response.json(); return { lotteryId: data.lottery_id active: data.active ticketsSold: data.tickets_sold totalRaised: data.total_raised goal: data.goal ticketPrice: data.ticket_price maxTickets: data.max_tickets winnerRevealed: data.winner_revealed winners: data.winners || [] }}","fetch","Poll every 10 seconds while lottery active; update UI in real-time"
13
+ 12,javascript,lottery,buy-lottery-ticket,"Purchase lottery ticket with STX","const buyTicket = async (ticketPrice) => { const response = await request('stx_callContract' { contract: `${lotteryAddress}.${lotteryContract}` functionName: 'buy-ticket' functionArgs: [] postConditions: [ Pc.principal(userAddress).willSendEq(ticketPrice).ustx() ] postConditionMode: 'deny' network: 'mainnet' fee: 100000 }); return response }","import { request } from '@stacks/connect'; import { Pc } from '@stacks/transactions'","Exact ticket price required; no change given; auto-assigns ticket ID"
14
+ 13,javascript,lottery,buy-ticket-for-friend,"Gift lottery ticket to another address","const buyTicketForFriend = async (friendAddress ticketPrice) => { const response = await request('stx_callContract' { contract: `${lotteryAddress}.${lotteryContract}` functionName: 'buy-ticket-for-friend' functionArgs: [principalCV(friendAddress)] postConditions: [ Pc.principal(userAddress).willSendEq(ticketPrice).ustx() ] postConditionMode: 'deny' network: 'mainnet' }); return response }","import { request } from '@stacks/connect'; import { Pc principalCV } from '@stacks/transactions'","Sender pays; friend receives ticket; useful for gifting or promotions"
15
+ 14,javascript,lottery,reveal-lottery-winners,"Reveal lottery winners (admin only)","const revealWinners = async (goal) => { const response = await request('stx_callContract' { contract: `${lotteryAddress}.${lotteryContract}` functionName: 'reveal-winner' functionArgs: [] postConditions: [ Pc.principal(`${lotteryAddress}.${lotteryContract}`).willSendLte(goal).ustx() ] postConditionMode: 'deny' network: 'mainnet' fee: 100000 }); return response }","import { request } from '@stacks/connect'; import { Pc } from '@stacks/transactions'","Contract sends prizes; VRF-based random selection; 4 winners for 4-winners lottery"
16
+ 15,javascript,lottery,get-user-lottery-tickets,"Get all tickets owned by user","const getUserTickets = async (userAddress) => { const response = await fetch(`/api/lottery-4-winners/contract-calls/get-user-tickets?user_address=${userAddress}`); const tickets = await response.json(); return tickets.map(ticket => ({ ticketId: ticket.ticket_id purchaseBlock: ticket.purchase_block isWinner: ticket.is_winner || false }))}","fetch","Returns array of ticket objects; check isWinner to highlight winning tickets"
17
+ 16,javascript,lottery,lottery-winner-animation,"Confetti animation for lottery winners","const showWinnerAnimation = () => { const balloonCount = 20; const balloons = Array.from({length: balloonCount} (__ i) => ({ id: i color: ['#FF6B6B' '#4ECDC4' '#45B7D1' '#FFA07A' '#98D8C8'][i % 5] delay: i * 300 left: Math.random() * 80 + 10 })); return balloons.map(b => ( <div key={b.id} className='balloon' style={{ backgroundColor: b.color animationDelay: `${b.delay}ms` left: `${b.left}%` }} /> ))}","import { useMemo } from 'react'","20 balloons; staggered animation (300ms); 5 colors; random horizontal position"
18
+ 17,javascript,portfolio,multi-wallet-fetch,"Fetch data for multiple wallets in parallel","const fetchMultiWalletData = async (addresses) => { const fetchPromises = addresses.map(address => Promise.all([ fetch(`/api/profile/overview?address=${address}`).then(r => r.json()) fetch(`/api/profile/portfolio?address=${address}`).then(r => r.json()) fetch(`/api/profile/nft_stats?address=${address}`).then(r => r.json()) fetch(`/api/profile/bonding_holdings?address=${address}`).then(r => r.json()) ])); return Promise.all(fetchPromises)}","fetch","Parallel fetching; combine results client-side; cache with SWR"
19
+ 18,javascript,portfolio,combine-wallet-portfolios,"Aggregate portfolio data from multiple wallets","const combinePortfolios = (portfolios) => { return portfolios.reduce((combined current) => ({ stxBalance: combined.stxBalance + current.stxBalance totalUsdValue: combined.totalUsdValue + current.totalUsdValue tokens: mergeTokenArrays(combined.tokens current.tokens) nfts: [...combined.nfts ...current.nfts] bondingCurveHoldings: [...combined.bondingCurveHoldings ...current.bondingCurveHoldings] }) {stxBalance: 0 totalUsdValue: 0 tokens: [] nfts: [] bondingCurveHoldings: []})}","None","Sum balances; merge token arrays (combine duplicates); concat NFT/bonding arrays"
20
+ 19,javascript,portfolio,token-balance-with-price,"Calculate token balance with USD value","const enrichTokenBalance = (token tokenPrices) => { const priceData = tokenPrices.find(p => p.contract_id === token.tokenContract); const priceUsd = priceData?.metrics.price_usd || 0; const realBalance = token.balance / Math.pow(10 token.decimals); const totalUsdValue = priceUsd * realBalance; return { ...token realBalance priceUsd totalUsdValue }}","None","Divide by 10^decimals for real balance; multiply by USD price; handle missing prices"
21
+ 20,javascript,portfolio,portfolio-doughnut-chart,"Render portfolio allocation doughnut chart","const portfolioChartData = { labels: ['STX' ...tokens.map(t => t.symbol)] datasets: [{ data: [stxValue ...tokens.map(t => t.totalUsdValue)] backgroundColor: ['#FF6384' '#36A2EB' '#FFCE56' '#4BC0C0' '#9966FF' '#FF9F40'] borderWidth: 2 }]}; <Doughnut data={portfolioChartData} options={{plugins: {legend: {position: 'bottom'}}}} />","import { Doughnut } from 'react-chartjs-2'","Use Chart.js; show STX + all fungible tokens; color-coded segments; legend below chart"
22
+ 21,javascript,portfolio,nft-stats-aggregate,"Aggregate NFT statistics across collections","const aggregateNftStats = (nftData) => { const stats = { totalCollections: new Set(nftData.map(nft => nft.collectionId)).size totalNfts: nftData.length totalFloorValue: nftData.reduce((sum nft) => sum + (nft.floorPrice || 0) 0) topCollections: Object.entries(groupBy(nftData 'collectionId')).sort((a b) => b[1].length - a[1].length).slice(0 5) }; return stats}","None","Count unique collections; sum floor values; rank by NFT count; top 5 collections"
23
+ 22,javascript,responsive,mobile-accordion-table,"Mobile-responsive table with accordion rows","const MobileTable = ({data}) => ( <Accordion variant='splitted'> {data.map(row => ( <AccordionItem key={row.id} title={<div><span>{row.name}</span><span>{row.value}</span></div>}> <div className='grid grid-cols-2 gap-2'> <div>Type: {row.type}</div> <div>Time: {timeAgo(row.timestamp)}</div> <div>Amount: {formatNumber(row.amount)}</div> <div>Status: {row.status}</div> </div> </AccordionItem> ))} </Accordion>)","import { Accordion AccordionItem } from '@nextui-org/react'","Desktop: full table; Mobile: accordion with summary in title; details in expandable content"
24
+ 23,javascript,responsive,conditional-table-render,"Conditionally render mobile vs desktop tables","const TableView = ({data isMobile}) => { if (isMobile) { return <MobileAccordionTable data={data} /> } return ( <Table aria-label='Desktop table'> <TableHeader>{columns.map(c => <TableColumn key={c.key}>{c.label}</TableColumn>)}</TableHeader> <TableBody>{data.map(row => <TableRow key={row.id}>{cells}</TableRow>)}</TableBody> </Table> )}","import { useMediaQuery } from 'react-responsive'","useMediaQuery to detect mobile; render different components; same data source"
25
+ 24,javascript,modal,quick-trade-modal,"Quick trade modal from activity feed","const [isQuickTradeOpen setIsQuickTradeOpen] = useState(false); const [selectedToken setSelectedToken] = useState(null); const openQuickTrade = (token) => { setSelectedToken(token); setIsQuickTradeOpen(true) }; <Modal isOpen={isQuickTradeOpen} onClose={() => setIsQuickTradeOpen(false)}> <QuickTrade token={selectedToken} onSuccess={() => {setIsQuickTradeOpen(false); mutate()}} /> </Modal>","import { Modal } from '@nextui-org/react'","Click row → open modal → trade → mutate() refreshes list"
26
+ 25,javascript,notifications,themed-sweetalert,"Theme-aware SweetAlert notifications","const showAlert = (title text icon) => { Swal.fire({ icon title text confirmButtonText: 'OK' confirmButtonColor: '#3085d6' background: theme === 'dark' ? '#131C32' : '#fff' color: theme === 'dark' ? '#fff' : '#000' })}","import Swal from 'sweetalert2'; import { useTheme } from 'next-themes'","Dark mode support; consistent styling; accessible colors"
27
+ 26,javascript,time,relative-time-display,"Display relative time (timeAgo)","function timeAgo(dateParam: Date): string { const now = new Date(); const date = new Date(dateParam); const seconds = Math.floor((now.getTime() - date.getTime()) / 1000); if (seconds < 60) return `${seconds}s ago`; const minutes = Math.floor(seconds / 60); if (minutes < 60) return `${minutes}m ago`; const hours = Math.floor(minutes / 60); if (hours < 24) return `${hours}h ago`; const days = Math.floor(hours / 24); if (days < 30) return `${days}d ago`; const months = Math.floor(days / 30); if (months < 12) return `${months}M ago`; const years = Math.floor(months / 12); return `${years}y ago`}","None","Human-readable timestamps; always singular suffix; no pluralization"
28
+ 27,javascript,formatting,mobile-number-abbreviation,"Format numbers for mobile display with K/M/B suffixes","function formatNumberForMobile(num: number): string { const absNum = Math.abs(num); if (absNum < 1 && absNum > 0) return num.toFixed(2); if (absNum < 1000) return Math.floor(num).toString(); if (absNum < 1000000) { const k = Math.floor(num / 1000); const hundreds = Math.floor((num % 1000) / 100); return k + 'k' + (hundreds || '') } if (absNum < 1000000000) { const m = Math.floor(num / 1000000); const hundredK = Math.floor((num % 1000000) / 100000); return m + 'M' + (hundredK || '') } const b = Math.floor(num / 1000000000); return b + 'B'}","None","< 1: 2 decimals; < 1K: integer; ≥ 1K: K/M/B suffix with single decimal"
29
+ 28,javascript,contract,contract-template-replacement,"Replace placeholders in Clarity contract template","function replacePlaceholders(template params) { let result = template; Object.entries(params).forEach(([key value]) => { const placeholder = new RegExp(`\\$${key}` 'g'); result = result.replace(placeholder String(value)) }); return result}; const modifiedCode = replacePlaceholders(templateCode { TOKEN_NAME: name TOKEN_SYMBOL: symbol TOKEN_SUPPLY: supply TOKEN_DECIMALS: decimals TOKEN_URI: uri DEPLOYER_ADDRESS: deployerAddr })","None","Use $VARIABLE placeholders; escape regex special chars; convert values to string"
30
+ 29,javascript,image,upload-with-preview,"Upload image with preview and validation","const [preview setPreview] = useState(''); const handleImageUpload = async (e) => { const file = e.target.files[0]; if (file.size > 5 * 1024 * 1024) { alert('File too large (max 5MB)'); return } const reader = new FileReader(); reader.onloadend = () => setPreview(reader.result); reader.readAsDataURL(file); const formData = new FormData(); formData.append('file' file); formData.append('type' 'logo'); const res = await fetch('/api/upload' {method: 'POST' body: formData}); return res.json().url}","None (FileReader native)","Validate size client-side; show preview before upload; FormData for multipart"
31
+ 30,javascript,skeleton,loading-skeleton-pattern,"Display skeleton loaders during data fetch","const TableSkeleton = () => ( <div className='space-y-3'> {Array.from({length: 10}).map((__ i) => ( <div key={i} className='flex space-x-4'> <Skeleton className='h-12 w-12 rounded-full' /> <div className='space-y-2 flex-1'> <Skeleton className='h-4 w-3/4' /> <Skeleton className='h-4 w-1/2' /> </div> </div> ))} </div>); return isLoading ? <TableSkeleton /> : <Table data={data} />","import { Skeleton } from '@nextui-org/react'","Match shape of actual content; 10 rows typical; fade-in when data arrives"
32
+ 31,javascript,postConditions,multi-asset-post-conditions,"Build post-conditions for multi-asset transactions","const buildPostConditions = (transfers) => { return transfers.map(transfer => { if (transfer.asset === 'STX') { return Pc.principal(transfer.from).willSendEq(transfer.amount).ustx() } else if (transfer.asset === 'NFT') { return Pc.principal(transfer.from).willSendAsset().nft(transfer.contract transfer.tokenId) } else { return Pc.principal(transfer.from).willSendEq(transfer.amount).ft(transfer.contract transfer.assetName) }})}","import { Pc } from '@stacks/transactions'","Support STX, NFT, and FT in same transaction; map over transfer array; use willSendEq for exact amounts"
33
+ 32,javascript,initialization,prevent-double-initialization,"Prevent double initialization in React Strict Mode","const initialized = useRef(false); useEffect(() => { if (initialized.current) return; initialized.current = true; fetchData() }, []); const [data setData] = useState(null); const fetchData = async () => { const result = await fetch('/api/data'); setData(result) }","import { useRef useEffect useState } from 'react'","useRef persists across re-renders; protects against React 18 double-mount in dev mode"
34
+ 33,javascript,debounce,debounced-search-input,"Debounce search input to reduce API calls","const [searchTerm setSearchTerm] = useState(''); const [debouncedTerm setDebouncedTerm] = useState(''); useEffect(() => { const timer = setTimeout(() => setDebouncedTerm(searchTerm) 500); return () => clearTimeout(timer) }, [searchTerm]); const {data} = useSWR(debouncedTerm ? `/api/search?q=${debouncedTerm}` : null fetcher)","import { useState useEffect } from 'react'; import useSWR from 'swr'","500ms delay; cancel timer on new input; only fetch when debouncedTerm changes"
35
+ 34,javascript,infiniteScroll,infinite-scroll-pattern,"Infinite scroll for activity feeds","const [page setPage] = useState(1); const [allData setAllData] = useState([]); const {data} = useSWR(`/api/activities?page=${page}` fetcher); useEffect(() => { if (data?.items) setAllData(prev => [...prev ...data.items]) }, [data]); const loadMore = () => setPage(p => p + 1); <IntersectionObserver onIntersect={loadMore}> <div>Loading more...</div> </IntersectionObserver>","import useSWR from 'swr'; import { useState useEffect } from 'react'","Append new data to existing; increment page on scroll; use IntersectionObserver for trigger"
36
+ 35,javascript,copy,copy-to-clipboard-with-toast,"Copy text to clipboard with visual feedback","const copyToClipboard = async (text) => { try { await navigator.clipboard.writeText(text); toast.success('Copied to clipboard!' { position: 'bottom-right' duration: 2000 })} catch (err) { toast.error('Failed to copy') }}; <button onClick={() => copyToClipboard(walletAddress)}> <Copy size={16} /> Copy </button>","import toast from 'react-hot-toast'; import { Copy } from 'lucide-react'","Use Clipboard API; show toast feedback; graceful error handling; icon for UX"
37
+ 36,javascript,confirmation,confirmation-modal-pattern,"Confirmation modal for destructive actions","const [isConfirmOpen setIsConfirmOpen] = useState(false); const [actionToConfirm setActionToConfirm] = useState(null); const confirmDelete = async () => { await actionToConfirm(); setIsConfirmOpen(false); mutate() }; <Modal isOpen={isConfirmOpen}> <ModalHeader>Confirm Action</ModalHeader> <ModalBody>Are you sure? This cannot be undone.</ModalBody> <ModalFooter> <Button color='danger' onPress={confirmDelete}>Confirm</Button> <Button variant='light' onPress={() => setIsConfirmOpen(false)}>Cancel</Button> </ModalFooter> </Modal>","import { Modal ModalHeader ModalBody ModalFooter Button } from '@nextui-org/react'","Store action as callback; confirm modal triggers it; mutate() refreshes data after action"
38
+ 37,javascript,zustand,zustand-wallet-store,"Zustand store for wallet state management","import create from 'zustand'; interface WalletState { isConnected: boolean; address: string | null; userData: any; connect: () => Promise<void>; disconnect: () => void }; const useWalletStore = create<WalletState>((set) => ({ isConnected: false address: null userData: null connect: async () => { const userData = await connectWallet(); set({isConnected: true address: userData.address userData})} disconnect: () => set({isConnected: false address: null userData: null}) }))","import create from 'zustand'","Centralized wallet state; async connect action; disconnect resets state; use throughout app"
39
+ 38,javascript,cache,swr-cache-invalidation,"Invalidate SWR cache on mutation","import { useSWRConfig } from 'swr'; const { mutate } = useSWRConfig(); const deleteItem = async (id) => { await fetch(`/api/items/${id}` {method: 'DELETE'}); mutate('/api/items'); mutate(`/api/items/${id}`)}; const updateItem = async (id data) => { await fetch(`/api/items/${id}` {method: 'PUT' body: JSON.stringify(data)}); mutate(`/api/items/${id}`) mutate('/api/items')}","import { useSWRConfig } from 'swr'","Call mutate() after mutations; revalidate specific keys; cascade to list endpoints"
40
+ 39,javascript,filtering,multi-filter-state,"Manage multiple filter states for data tables","const [filters setFilters] = useState({ search: '' status: 'all' dateRange: null sortBy: 'date' sortOrder: 'desc' }); const updateFilter = (key value) => setFilters(prev => ({...prev [key]: value})); const filteredData = useMemo(() => { let result = data; if (filters.search) result = result.filter(item => item.name.includes(filters.search)); if (filters.status !== 'all') result = result.filter(item => item.status === filters.status); return result.sort((a b) => filters.sortOrder === 'asc' ? a[filters.sortBy] - b[filters.sortBy] : b[filters.sortBy] - a[filters.sortBy]) }, [data filters])","import { useState useMemo } from 'react'","Single filter object; partial updates; compute filtered data in useMemo; chain filters"
41
+ 40,javascript,export,export-table-to-csv,"Export table data to CSV file","const exportToCSV = (data filename) => { const headers = Object.keys(data[0]); const csvContent = [ headers.join(',') ...data.map(row => headers.map(h => JSON.stringify(row[h] || '')).join(',')) ].join('\\n'); const blob = new Blob([csvContent] {type: 'text/csv;charset=utf-8;'}); const link = document.createElement('a'); link.href = URL.createObjectURL(blob); link.download = filename; link.click()}; <button onClick={() => exportToCSV(tableData 'export.csv')}>Export CSV</button>","None (native Blob and URL APIs)","Extract headers from first row; JSON.stringify handles commas in values; trigger download"
@@ -0,0 +1,23 @@
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,javascript,connect,authenticate-user,"Authenticate user with wallet","import { showConnect } from '@stacks/connect'; import { AppConfig, UserSession } from '@stacks/auth'; const appConfig = new AppConfig(['store_write', 'publish_data']); const userSession = new UserSession({ appConfig }); showConnect({ appDetails: { name: 'My App', icon: '/logo.png' }, redirectTo: '/', onFinish: () => window.location.reload(), userSession })","import { showConnect } from '@stacks/connect'; import { AppConfig, UserSession } from '@stacks/auth'","Opens wallet connection modal; redirects after auth"
3
+ 2,javascript,connect,check-authentication,"Check if user is authenticated","import { UserSession, AppConfig } from '@stacks/auth'; const appConfig = new AppConfig(['store_write']); const userSession = new UserSession({ appConfig }); if (userSession.isUserSignedIn()) { const userData = userSession.loadUserData(); console.log('User:', userData.profile.stxAddress.mainnet) } else { console.log('Not authenticated') }","import { UserSession, AppConfig } from '@stacks/auth'","Check auth status before protected operations"
4
+ 3,javascript,connect,sign-out-user,"Sign out user","import { UserSession, AppConfig } from '@stacks/auth'; const appConfig = new AppConfig(['store_write']); const userSession = new UserSession({ appConfig }); userSession.signUserOut(); window.location.href = '/'","import { UserSession, AppConfig } from '@stacks/auth'","Clears session and redirects to home"
5
+ 4,javascript,profile,get-user-profile,"Get user profile data","import { UserSession } from '@stacks/auth'; const userSession = new UserSession(); const userData = userSession.loadUserData(); const profile = { stxAddress: userData.profile.stxAddress.mainnet, btcAddress: userData.profile.btcAddress, username: userData.username, name: userData.profile.name, image: userData.profile.image }","import { UserSession } from '@stacks/auth'","Returns wallet addresses and BNS username"
6
+ 5,javascript,signing,sign-message,"Sign message with wallet","import { openSignatureRequestPopup } from '@stacks/connect'; const message = 'Verify ownership of this address'; openSignatureRequestPopup({ message, onFinish: (data) => { console.log('Signature:', data.signature); console.log('Public key:', data.publicKey) }})","import { openSignatureRequestPopup } from '@stacks/connect'","Proves wallet ownership without transaction"
7
+ 6,javascript,signing,verify-signature,"Verify signed message","import { verifyMessageSignature } from '@stacks/encryption'; const isValid = verifyMessageSignature({ message: 'Verify ownership', signature: signatureData.signature, publicKey: publicKey }); console.log('Valid:', isValid)","import { verifyMessageSignature } from '@stacks/encryption'","Cryptographically verify message was signed by public key"
8
+ 7,javascript,session,persist-session,"Persist auth session to localStorage","import { UserSession } from '@stacks/auth'; const userSession = new UserSession(); if (userSession.isUserSignedIn()) { const userData = userSession.loadUserData(); localStorage.setItem('stacks_session', JSON.stringify({ address: userData.profile.stxAddress.mainnet, username: userData.username, timestamp: Date.now() })) }","import { UserSession } from '@stacks/auth'","Cache session data for faster page loads"
9
+ 8,javascript,session,restore-session,"Restore auth session from cache","const cachedSession = localStorage.getItem('stacks_session'); if (cachedSession) { const session = JSON.parse(cachedSession); const hourAgo = Date.now() - 3600000; if (session.timestamp > hourAgo) { console.log('Cached session:', session.address) } else { localStorage.removeItem('stacks_session') }}","None","Validate timestamp to prevent stale sessions"
10
+ 9,javascript,permissions,request-permissions,"Request specific permissions","import { AppConfig, UserSession } from '@stacks/auth'; const appConfig = new AppConfig(['store_write', 'publish_data', 'email']); const userSession = new UserSession({ appConfig })","import { AppConfig, UserSession } from '@stacks/auth'","Permissions: store_write, publish_data, email"
11
+ 10,javascript,encryption,encrypt-data,"Encrypt data with user key","import { encryptContent } from '@stacks/encryption'; import { UserSession } from '@stacks/auth'; const userSession = new UserSession(); const userData = userSession.loadUserData(); const encrypted = await encryptContent(JSON.stringify(sensitiveData), { publicKey: userData.profile.publicKey })","import { encryptContent } from '@stacks/encryption'; import { UserSession } from '@stacks/auth'","Only user with private key can decrypt"
12
+ 11,javascript,encryption,decrypt-data,"Decrypt encrypted data","import { decryptContent } from '@stacks/encryption'; import { UserSession } from '@stacks/auth'; const userSession = new UserSession(); const userData = userSession.loadUserData(); const decrypted = await decryptContent(encryptedData, { privateKey: userData.appPrivateKey })","import { decryptContent } from '@stacks/encryption'; import { UserSession } from '@stacks/auth'","Requires user private key from session"
13
+ 12,javascript,auth-hooks,use-auth-hook,"React hook for authentication","import { UserSession } from '@stacks/auth'; import { useState, useEffect } from 'react'; function useAuth() { const [user, setUser] = useState(null); useEffect(() => { const userSession = new UserSession(); if (userSession.isUserSignedIn()) { setUser(userSession.loadUserData()) }}, []); return { user, isAuthenticated: !!user, signOut: () => new UserSession().signUserOut() }}","import { UserSession } from '@stacks/auth'; import { useState, useEffect } from 'react'","Reusable auth state for React apps"
14
+ 13,javascript,auth-guards,protected-route,"Protect routes with auth guard","function ProtectedRoute({ children }) { const { user } = useAuth(); const router = useRouter(); useEffect(() => { if (!user) { router.push('/login') }}, [user, router]); return user ? children : <div>Loading...</div> }","import { useAuth } from './hooks'; import { useRouter } from 'next/router'","Redirect to login if not authenticated"
15
+ 14,javascript,middleware,auth-middleware,"API route auth middleware","export function withAuth(handler) { return async (req, res) => { const token = req.headers.authorization?.split(' ')[1]; if (!token) return res.status(401).json({ error: 'Unauthorized' }); try { const verified = verifyJWT(token); req.user = verified; return handler(req, res) } catch { return res.status(401).json({ error: 'Invalid token' }) }}}","None","Protect API routes; verify JWT tokens"
16
+ 15,javascript,jwt,create-auth-token,"Create JWT auth token","import jwt from 'jsonwebtoken'; const token = jwt.sign({ address: userData.profile.stxAddress.mainnet, username: userData.username, exp: Math.floor(Date.now() / 1000) + (60 * 60 * 24)}, JWT_SECRET)","import jwt from 'jsonwebtoken'","Token expires in 24 hours; include user identity"
17
+ 16,javascript,jwt,verify-auth-token,"Verify JWT auth token","import jwt from 'jsonwebtoken'; try { const decoded = jwt.verify(token, JWT_SECRET); console.log('User:', decoded.address); return decoded } catch (error) { console.error('Invalid token:', error); return null }","import jwt from 'jsonwebtoken'","Throws error if token invalid or expired"
18
+ 17,javascript,session-tokens,exchange-session-token,"Exchange auth token for session","async function exchangeAuthToken(authToken) { const response = await fetch('/api/auth/session', { method: 'POST', headers: { 'Authorization': `Bearer ${authToken}` } }); const { sessionToken } = await response.json(); localStorage.setItem('session_token', sessionToken); return sessionToken }","fetch","Backend validates auth token and issues session token"
19
+ 18,javascript,oauth,connect-with-oauth,"Authenticate with OAuth provider","import { showConnect } from '@stacks/connect'; showConnect({ authOrigin: 'https://app.blockstack.org', appDetails: { name: 'My App', icon: '/icon.png' }, onFinish: (payload) => { const { authResponse } = payload; fetch('/api/auth/verify', { method: 'POST', body: JSON.stringify({ token: authResponse }) }) }})","import { showConnect } from '@stacks/connect'","OAuth-like flow with Stacks auth"
20
+ 19,javascript,social,connect-with-bns,"Resolve BNS to get social links","import { lookupProfile } from '@stacks/auth'; const profile = await lookupProfile('username.btc'); console.log(profile.name, profile.description); const socialLinks = profile.account?.filter(a => a.service === 'twitter' || a.service === 'github')","import { lookupProfile } from '@stacks/auth'","BNS profiles can include social media links"
21
+ 20,javascript,access-control,verify-nft-ownership,"Gate content by NFT ownership","async function hasAccessNFT(userAddress, nftContract, nftId) { const response = await fetch(`https://api.hiro.so/extended/v1/tokens/nft/holdings?principal=${nftContract}&token_id=${nftId}`); const data = await response.json(); return data.results[0]?.owner === userAddress }","fetch","Token-gated access pattern"
22
+ 21,javascript,access-control,verify-token-balance,"Gate content by token balance","async function hasMinBalance(userAddress, tokenContract, minAmount) { const response = await fetch(`https://api.hiro.so/extended/v1/address/${userAddress}/balances`); const balances = await response.json(); const balance = balances.fungible_tokens[tokenContract]?.balance || '0'; return parseInt(balance) >= minAmount }","fetch","Require minimum token holdings for access"
23
+ 22,javascript,webhooks,verify-webhook-signature,"Verify webhook signature","import crypto from 'crypto'; function verifyWebhook(payload, signature, secret) { const hmac = crypto.createHmac('sha256', secret); hmac.update(JSON.stringify(payload)); const digest = hmac.digest('hex'); return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest)) }","import crypto from 'crypto'","Verify webhook came from trusted source"
@@ -1,11 +1,21 @@
1
- id,category,name,description,code,contract,notes
2
- 1,resolve,name-to-address,"Resolve BNS name to address","(contract-call? .bns name-resolve namespace name)","SP000000000000000000002Q6VF78.bns","Returns principal of name owner"
3
- 2,resolve,address-to-name,"Get primary name for address","(contract-call? .bns resolve-principal address)","SP000000000000000000002Q6VF78.bns","Returns primary BNS name"
4
- 3,register,register-name,"Register a new BNS name","(contract-call? .bns-v2 name-register namespace name salt zonefile-hash)","BNS-V2 contract","Requires STX payment based on name length"
5
- 4,transfer,transfer-name,"Transfer BNS name ownership","(contract-call? .bns-v2 name-transfer namespace name new-owner zonefile-hash)","BNS-V2 contract","Owner only can transfer names"
6
- 5,update,update-zonefile,"Update name zonefile hash","(contract-call? .bns-v2 name-update namespace name zonefile-hash)","BNS-V2 contract","Updates DNS records for name"
7
- 6,lookup,name-info,"Get name details","(contract-call? .bns name-resolve namespace name)","SP000000000000000000002Q6VF78.bns","Returns owner zonefile-hash lease-ending-at"
8
- 7,lookup,get-namespace-price,"Get registration price","(contract-call? .bns-v2 get-namespace-price namespace)","BNS-V2 contract","Price in microSTX"
9
- 8,lookup,can-name-be-registered,"Check name availability","(contract-call? .bns-v2 can-name-be-registered namespace name)","BNS-V2 contract","Returns true if available"
10
- 9,bulk,batch-register,"Register multiple names","(map register-single-name names)","Custom contract","Loop through list of names"
11
- 10,renew,renew-name,"Renew name registration","(contract-call? .bns-v2 name-renewal namespace name)","BNS-V2 contract","Extends lease period"
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,clarity,resolve,name-to-address,"Resolve BNS name to address","(contract-call? .bns name-resolve namespace name)","SP000000000000000000002Q6VF78.bns","Returns principal of name owner"
3
+ 2,clarity,resolve,address-to-name,"Get primary name for address","(contract-call? .bns resolve-principal address)","SP000000000000000000002Q6VF78.bns","Returns primary BNS name"
4
+ 3,clarity,register,register-name,"Register a new BNS name","(contract-call? .bns-v2 name-register namespace name salt zonefile-hash)","BNS-V2 contract","Requires STX payment based on name length"
5
+ 4,clarity,transfer,transfer-name,"Transfer BNS name ownership","(contract-call? .bns-v2 name-transfer namespace name new-owner zonefile-hash)","BNS-V2 contract","Owner only can transfer names"
6
+ 5,clarity,update,update-zonefile,"Update name zonefile hash","(contract-call? .bns-v2 name-update namespace name zonefile-hash)","BNS-V2 contract","Updates DNS records for name"
7
+ 6,clarity,lookup,name-info,"Get name details","(contract-call? .bns name-resolve namespace name)","SP000000000000000000002Q6VF78.bns","Returns owner zonefile-hash lease-ending-at"
8
+ 7,clarity,lookup,get-namespace-price,"Get registration price","(contract-call? .bns-v2 get-namespace-price namespace)","BNS-V2 contract","Price in microSTX"
9
+ 8,clarity,lookup,can-name-be-registered,"Check name availability","(contract-call? .bns-v2 can-name-be-registered namespace name)","BNS-V2 contract","Returns true if available"
10
+ 9,clarity,bulk,batch-register,"Register multiple names","(map register-single-name names)","Custom contract","Loop through list of names"
11
+ 10,clarity,renew,renew-name,"Renew name registration","(contract-call? .bns-v2 name-renewal namespace name)","BNS-V2 contract","Extends lease period"
12
+ 11,javascript,resolve,address-to-name,"Get primary BNS name for address using SDK","const primaryName = await getPrimaryName({ address: 'SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR' network: 'mainnet' }); if (primaryName) { const fullName = `${primaryName.name}.${primaryName.namespace}`; console.log(fullName) }","import { getPrimaryName } from 'bns-v2-sdk'","Returns { name namespace } or null; SDK method for resolving address to BNS"
13
+ 12,api,resolve,name-to-address,"Resolve BNS name to owner address using API","async function fetchAddressByBNS(bns) { try { const url = `https://api.bnsv2.com/names/${bns.toLowerCase()}`; const response = await axios.get(url); return response.data?.data?.owner || null } catch (error) { console.error('BNS resolution failed:' error); return null }}","import axios from 'axios'","REST API method; faster than SDK for name-to-address resolution; returns owner address"
14
+ 13,javascript,lookup,get-name-info,"Get detailed information about a BNS name","const nameInfo = await getNameInfo({ fullyQualifiedName: 'example.btc' network: 'mainnet' }); console.log(nameInfo.owner nameInfo.zonefile)","import { getNameInfo } from 'bns-v2-sdk'","Returns name owner zonefile lease-ending-at and other metadata"
15
+ 14,javascript,lookup,get-token-id,"Get token ID from BNS fully qualified name","const nameId = await getIdFromBns({ fullyQualifiedName: 'example.btc' network: 'mainnet' }); console.log('Token ID:' nameId)","import { getIdFromBns } from 'bns-v2-sdk'","Required for marketplace operations (buy list unlist); returns BigInt token ID"
16
+ 15,javascript,marketplace,buy-name,"Build transaction to buy BNS from marketplace","const buyPayload = await buildBuyInUstxTx({ id: nameId expectedPrice: BigInt(priceInMicroStx) commissionTraitAddress: 'SP...' commissionTraitName: 'commission-trait' senderAddress: userAddress network: 'mainnet' }); await request('stx_callContract' { contract: `${buyPayload.contractAddress}.${buyPayload.contractName}` functionName: buyPayload.functionName functionArgs: buyPayload.functionArgs postConditions: buyPayload.postConditions postConditionMode: 'deny' network: 'mainnet' })","import { buildBuyInUstxTx } from 'bns-v2-sdk'; import { request } from '@stacks/connect'","Price includes 2% marketplace fee; expectedPrice = listedPrice * 1.02; use deny mode for security"
17
+ 16,javascript,marketplace,list-name,"Build transaction to list BNS on marketplace","const priceAfterFee = priceInMicroStx * 0.98; const listPayload = await buildListInUstxTx({ id: BigInt(nameId) price: BigInt(priceAfterFee) commissionTraitAddress: 'SP...' commissionTraitName: 'commission-trait' senderAddress: userAddress network: 'mainnet' }); await request('stx_callContract' { contract: `${listPayload.contractAddress}.${listPayload.contractName}` functionName: listPayload.functionName functionArgs: listPayload.functionArgs postConditions: listPayload.postConditions postConditionMode: 'deny' })","import { buildListInUstxTx } from 'bns-v2-sdk'; import { request } from '@stacks/connect'","List price after 2% fee deduction; seller receives 98% of listed price"
18
+ 17,javascript,marketplace,unlist-name,"Build transaction to remove BNS listing from marketplace","const unlistPayload = await buildUnlistInUstxTx({ id: BigInt(nameId) senderAddress: userAddress network: 'mainnet' }); await request('stx_callContract' { contract: `${unlistPayload.contractAddress}.${unlistPayload.contractName}` functionName: unlistPayload.functionName functionArgs: unlistPayload.functionArgs postConditions: unlistPayload.postConditions postConditionMode: 'deny' })","import { buildUnlistInUstxTx } from 'bns-v2-sdk'; import { request } from '@stacks/connect'","Only the owner can unlist; removes from marketplace but keeps ownership"
19
+ 18,javascript,update,set-primary-name,"Set primary BNS name for wallet","const setPrimaryPayload = await buildSetPrimaryNameTx({ fullyQualifiedName: 'example.btc' senderAddress: userAddress network: 'mainnet' }); await request('stx_callContract' { contract: `${setPrimaryPayload.contractAddress}.${setPrimaryPayload.contractName}` functionName: setPrimaryPayload.functionName functionArgs: setPrimaryPayload.functionArgs postConditions: setPrimaryPayload.postConditions })","import { buildSetPrimaryNameTx } from 'bns-v2-sdk'; import { request } from '@stacks/connect'","Sets default BNS for address; shown in wallets and dApps"
20
+ 19,javascript,transfer,transfer-name,"Build transaction to transfer BNS to another address","const transferPayload = await buildTransferNameTx({ fullyQualifiedName: 'example.btc' newOwnerAddress: 'SP...' senderAddress: currentOwnerAddress network: 'mainnet' }); await request('stx_callContract' { contract: `${transferPayload.contractAddress}.${transferPayload.contractName}` functionName: transferPayload.functionName functionArgs: transferPayload.functionArgs postConditions: transferPayload.postConditions })","import { buildTransferNameTx } from 'bns-v2-sdk'; import { request } from '@stacks/connect'","Transfers full ownership; cannot be reversed; removes any active listings"
21
+ 20,javascript,caching,caching-pattern,"Production BNS caching with circuit breaker and multi-layer cache","import NodeCache from 'node-cache'; const memCache = new NodeCache({ stdTTL: 3600 }); const pendingRequests = new Map(); async function getCachedBNS(address) { const cached = memCache.get(address); if (cached !== undefined) return cached; const pending = pendingRequests.get(address); if (pending) return pending; const promise = (async () => { try { const primaryName = await getPrimaryName({ address network: 'mainnet' }); const result = primaryName ? `${primaryName.name}.${primaryName.namespace}` : null; memCache.set(address result); return result } finally { pendingRequests.delete(address) }})(); pendingRequests.set(address promise); return promise }","import { getPrimaryName } from 'bns-v2-sdk'; import NodeCache from 'node-cache'","Prevents duplicate API calls; 1-hour TTL; request deduplication; production-ready pattern from stx.city"
@@ -0,0 +1,31 @@
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,javascript,create,txid-chainhook,"Create chainhook for specific transaction","const chainhookTemplate = { name: 'my-chainhook', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'txid', equals: txId }, then_that: { http_post: { url: 'https://myapp.com/api/hook', authorization_header: `Bearer ${SECRET}` } }, start_block: startBlock, decode_clarity_values: true } } }; await fetch(`https://api.platform.hiro.so/v1/ext/${API_KEY}/chainhooks`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(chainhookTemplate) })","import { v4 as uuidv4 } from 'uuid'","Transaction-based hook; fires when specific tx_id is confirmed; good for order tracking"
3
+ 2,javascript,create,contract-call-chainhook,"Create chainhook for contract function calls","const chainhookTemplate = { name: 'swap-monitor', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'contract_call', contract_identifier: 'SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.alex-vault', method: 'swap-helper' }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: currentBlock } } }","import { v4 as uuidv4 } from 'uuid'","Monitor specific contract function; fires on every call to method; use for DEX swaps tracking"
4
+ 3,javascript,create,print-event-chainhook,"Create chainhook for Clarity print events","const chainhookTemplate = { name: 'event-listener', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'print_event', contract_identifier: 'SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.nft-marketplace', contains: 'sale-complete' }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: startBlock } } }","import { v4 as uuidv4 } from 'uuid'","Listen for Clarity print statements; useful for custom events; 'contains' filters by event name"
5
+ 4,javascript,create,ft-event-chainhook,"Create chainhook for fungible token events","const chainhookTemplate = { name: 'token-monitor', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'ft_event', asset_identifier: 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-abtc::abtc', actions: ['mint', 'transfer', 'burn'] }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: currentBlock } } }","import { v4 as uuidv4 } from 'uuid'","Track FT events (mint/transfer/burn); monitors specific token contract; good for token analytics"
6
+ 5,javascript,create,nft-event-chainhook,"Create chainhook for NFT events","const chainhookTemplate = { name: 'nft-tracker', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'nft_event', asset_identifier: 'SP2X0TZ59D5SZ8ACQ6YMCHHNR2ZN51Z32E2CJ173.bitcoin-monkeys::bitcoin-monkeys', actions: ['mint', 'transfer', 'burn'] }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: currentBlock } } }","import { v4 as uuidv4 } from 'uuid'","Monitor NFT collection events; tracks mints and transfers; useful for marketplace indexing"
7
+ 6,javascript,create,stx-event-chainhook,"Create chainhook for STX transfer events","const chainhookTemplate = { name: 'stx-transfers', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'stx_event', actions: ['transfer', 'mint', 'lock'] }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: currentBlock } } }","import { v4 as uuidv4 } from 'uuid'","Track all STX transfers; monitor stacking locks; use sparingly (high volume)"
8
+ 7,javascript,webhook,chainhook-handler,"Handle chainhook webhook POST","export async function POST(req: NextRequest) { const authHeader = req.headers.get('authorization'); if (authHeader !== `Bearer ${CHAINHOOK_BEARER}`) { return new NextResponse('Unauthorized', { status: 401 }); } const body = await req.json(); const txId = body.chainhook.predicate.equals; const chainhookUuid = body.chainhook.uuid; // Process transaction... return new NextResponse(JSON.stringify({ success: true }), { status: 200 }) }","import { NextRequest, NextResponse } from 'next/server'","Webhook handler pattern; verify bearer token; extract tx_id from payload; always return 200"
9
+ 8,javascript,webhook,verify-tx-status,"Verify transaction status in webhook","const txId = body.chainhook.predicate.equals; const txResponse = await fetch(`https://api.mainnet.hiro.so/extended/v1/tx/${txId}`); const txData = await txResponse.json(); if (txData.tx_status === 'success') { // Update database... console.log('Transaction confirmed') }","fetch","Fetch full tx details; check tx_status; handle success vs failed vs pending"
10
+ 9,javascript,webhook,delete-chainhook,"Delete chainhook after processing","const chainhookUuid = body.chainhook.uuid; const deleteResponse = await fetch(`https://api.platform.hiro.so/v1/ext/${CHAINHOOK_API}/chainhooks/${chainhookUuid}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' } }); if (deleteResponse.ok) { console.log('Chainhook deleted') }","fetch","Clean up one-time hooks; prevents duplicate webhook calls; good for order confirmations"
11
+ 10,javascript,webhook,parse-contract-source,"Parse smart contract source code","const contractId = txData.smart_contract?.contract_id; const sourceCode = txData.smart_contract?.source_code; const stxTransferPattern = /\(try!\s*\(stx-transfer\?\s+u(\d+)\s+tx-sender\s+'([^']+)\)\)/g; const matches = [...sourceCode.matchAll(stxTransferPattern)]; matches.forEach(match => { const amount = parseInt(match[1]); const recipient = match[2]; console.log(`Transfer: ${amount} to ${recipient}`) })","None","Extract data from deployed contracts; parse Clarity code with regex; useful for airdrop analysis"
12
+ 11,javascript,webhook,send-notification,"Send Telegram notification from webhook","const message = `New transaction confirmed: ${txId}`; await fetch(`https://api.telegram.org/bot${TELEGRAM_API}/sendMessage`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ chat_id: CHAT_ID, text: message, parse_mode: 'HTML' }) })","fetch","Push notifications on blockchain events; use Telegram, Discord, etc; HTML formatting supported"
13
+ 12,javascript,management,list-chainhooks,"List all active chainhooks","const response = await fetch(`https://api.platform.hiro.so/v1/ext/${CHAINHOOK_API}/chainhooks`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); const chainhooks = await response.json(); console.log('Active chainhooks:', chainhooks.length)","fetch","Retrieve all registered hooks; check status; useful for debugging"
14
+ 13,javascript,management,get-chainhook,"Get specific chainhook details","const response = await fetch(`https://api.platform.hiro.so/v1/ext/${CHAINHOOK_API}/chainhooks/${uuid}`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); const chainhook = await response.json(); console.log('Chainhook:', chainhook.name)","fetch","Fetch single hook by UUID; check configuration; verify it's running"
15
+ 14,javascript,management,update-chainhook,"Update existing chainhook","const updatedTemplate = { ...existingChainhook, networks: { mainnet: { ...existingChainhook.networks.mainnet, end_block: currentBlock + 1000 } } }; await fetch(`https://api.platform.hiro.so/v1/ext/${CHAINHOOK_API}/chainhooks/${uuid}`, { method: 'PUT', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(updatedTemplate) })","fetch","Modify hook configuration; change end_block; update webhook URL"
16
+ 15,javascript,management,delete-chainhook-by-uuid,"Delete chainhook by UUID","await fetch(`https://api.platform.hiro.so/v1/ext/${CHAINHOOK_API}/chainhooks/${uuid}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' } })","fetch","Manual cleanup; remove unused hooks; prevents webhook spam"
17
+ 16,javascript,advanced,chainhook-with-end-block,"Create chainhook with expiration","const chainhookTemplate = { name: 'limited-hook', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'txid', equals: txId }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: startBlock, end_block: startBlock + 100, decode_clarity_values: true } } }","import { v4 as uuidv4 } from 'uuid'","Auto-expires after end_block; prevents orphaned hooks; good for time-limited campaigns"
18
+ 17,javascript,advanced,chainhook-expire-after-occurrence,"Create one-time chainhook","const chainhookTemplate = { name: 'one-time-hook', uuid: uuidv4(), chain: 'stacks', version: 1, networks: { mainnet: { if_this: { scope: 'txid', equals: txId }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: startBlock, expire_after_occurrence: 1 } } }","import { v4 as uuidv4 } from 'uuid'","Auto-deletes after first trigger; perfect for order confirmations; set to null for persistent hooks"
19
+ 18,javascript,advanced,decode-clarity-values,"Enable Clarity value decoding","const chainhookTemplate = { ...baseTemplate, networks: { mainnet: { ...networkConfig, decode_clarity_values: true } } }","None","Decode Clarity responses; get human-readable values; recommended for all hooks"
20
+ 19,javascript,patterns,ngrok-development,"Use ngrok for local development","let webhookUrl = 'https://myapp.com/api/hook'; if (process.env.NODE_ENV === 'development') { webhookUrl = 'https://abc123.ngrok-free.app/api/hook' }","None","Test webhooks locally; ngrok tunnels to localhost; remember to update for production"
21
+ 20,javascript,patterns,bearer-auth,"Secure webhook with bearer token","const CHAINHOOK_BEARER = process.env.CHAINHOOK_SECRET; export async function POST(req: NextRequest) { const authHeader = req.headers.get('authorization'); if (authHeader !== `Bearer ${CHAINHOOK_BEARER}`) { return new NextResponse('Unauthorized', { status: 401 }) } // Process webhook... }","import { NextRequest, NextResponse } from 'next/server'","Always verify bearer token; prevents unauthorized access; use strong secrets"
22
+ 21,javascript,patterns,handle-webhook-payload,"Extract data from webhook payload","const body = await req.json(); const txId = body.chainhook?.predicate?.equals; const chainhookUuid = body.chainhook?.uuid; const transactions = body.apply?.[0]?.metadata?.transactions || []; const txSuccess = transactions[0]?.metadata?.success; const sender = transactions[0]?.metadata?.sender","None","Webhook payload structure; apply[0] contains block data; check nested properties safely"
23
+ 22,javascript,patterns,tx-format-0x,"Handle 0x transaction prefix","const txCorrectFormat = tx_id.startsWith('0x') ? tx_id : `0x${tx_id}`","None","Some APIs require 0x prefix; normalize tx_ids; prevents lookup failures"
24
+ 23,javascript,patterns,database-update-on-confirm,"Update database on tx confirmation","if (txData.tx_status === 'success') { await db.update(orders).set({ status: 'confirmed', confirmed_at: new Date() }).where(eq(orders.tx_id, txId)) }","import { db } from '@/lib/db'; import { eq } from 'drizzle-orm'","Update order status; mark as confirmed; only on success status"
25
+ 24,javascript,patterns,chainhook-naming,"Generate unique chainhook names","const chainhookName = `${eventType}-${contractName}-${txId.slice(-8)}`","None","Include event type + identifier + tx suffix; makes hooks identifiable; easier debugging"
26
+ 25,javascript,bitcoin,bitcoin-chainhook,"Create Bitcoin chainhook","const chainhookTemplate = { name: 'btc-deposits', uuid: uuidv4(), chain: 'bitcoin', version: 1, networks: { mainnet: { if_this: { scope: 'outputs', descriptor: { type: 'p2pkh', address: 'bc1q...' } }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: 800000 } } }","import { v4 as uuidv4 } from 'uuid'","Monitor Bitcoin addresses; track deposits; use descriptor for address patterns"
27
+ 26,javascript,bitcoin,ordinals-chainhook,"Monitor Ordinals inscriptions","const chainhookTemplate = { name: 'ordinals-tracker', uuid: uuidv4(), chain: 'bitcoin', version: 1, networks: { mainnet: { if_this: { scope: 'ordinals_protocol', operation: 'inscription_feed' }, then_that: { http_post: { url: hookUrl, authorization_header: `Bearer ${SECRET}` } }, start_block: 767430 } } }","import { v4 as uuidv4 } from 'uuid'","Track Ordinals inscriptions; Bitcoin NFTs; start_block must be >= 767430 (Ordinals activation)"
28
+ 27,javascript,patterns,multi-contract-monitoring,"Monitor multiple contracts","const contracts = ['SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR.alex-vault', 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.velar-swap']; for (const contract of contracts) { const template = { ...baseTemplate, name: `swap-${contract.split('.')[1]}`, networks: { mainnet: { if_this: { scope: 'contract_call', contract_identifier: contract, method: 'swap' }, ...rest } } }; await createChainhook(template) }","None","Monitor multiple DEXs; create hooks in loop; track all swap activity"
29
+ 28,javascript,patterns,historical-evaluation,"Test chainhook against past blocks","const chainhookTemplate = { ...baseTemplate, networks: { mainnet: { ...config, start_block: pastBlock, end_block: pastBlock + 100 } } }","None","Backfill historical data; test hook logic; useful for debugging predicates"
30
+ 29,javascript,patterns,webhook-retry-logic,"Handle webhook delivery failures","export async function POST(req: NextRequest) { try { const body = await req.json(); await processWebhook(body); return new NextResponse(JSON.stringify({ success: true }), { status: 200 }) } catch (error) { console.error('Webhook processing failed:', error); return new NextResponse(JSON.stringify({ error: 'Processing failed' }), { status: 500 }) } }","import { NextRequest, NextResponse } from 'next/server'","Always return 200 on success; Chainhooks retries on non-200; idempotent handlers recommended"
31
+ 30,javascript,patterns,idempotent-webhook,"Make webhook handler idempotent","const existingRecord = await db.query.orders.findFirst({ where: eq(orders.tx_id, txId) }); if (existingRecord?.status === 'confirmed') { console.log('Already processed'); return new NextResponse(JSON.stringify({ success: true }), { status: 200 }) } // Process webhook...","import { db } from '@/lib/db'; import { eq } from 'drizzle-orm'","Check if already processed; prevent duplicate actions; handle retries safely"
@@ -1,16 +1,26 @@
1
- id,protocol,category,name,description,contract_address,function_signature,example,docs_url
2
- 1,alex,swap,swap-helper,"Swap tokens via Alex","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","(swap-helper token-x token-y factor-x factor-y dx min-dy)","(contract-call? .amm-swap-pool-v1-1 swap-helper .token-wstx .age000-governance-token u100000000 u100000000 u1000000 u1)","https://docs.alexlab.co"
3
- 2,alex,pool,get-pool-details,"Get pool info","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","(get-pool-details token-x token-y)","(contract-call? .amm-swap-pool-v1-1 get-pool-details .token-wstx .age000-governance-token)","https://docs.alexlab.co"
4
- 3,alex,liquidity,add-to-position,"Add liquidity to Alex","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","(add-to-position token-x token-y factor-x factor-y dx)","(contract-call? .amm-swap-pool-v1-1 add-to-position .token-wstx .age000-governance-token u100000000 u100000000 u1000000)","https://docs.alexlab.co"
5
- 4,velar,swap,swap-exact-tokens,"Swap on Velar","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","(swap-exact-tokens-for-tokens amount-in min-out path)","(contract-call? .univ2-router swap-exact-tokens-for-tokens u1000000 u950000 (list .token-a .token-b))","https://docs.velar.co"
6
- 5,velar,liquidity,add-liquidity,"Add liquidity to Velar","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","(add-liquidity token-a token-b amount-a amount-b min-a min-b)","(contract-call? .univ2-router add-liquidity .token-a .token-b u1000000 u1000000 u900000 u900000)","https://docs.velar.co"
7
- 6,velar,liquidity,remove-liquidity,"Remove liquidity from Velar","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","(remove-liquidity token-a token-b liquidity min-a min-b)","(contract-call? .univ2-router remove-liquidity .token-a .token-b u1000000 u900000 u900000)","https://docs.velar.co"
8
- 7,bitflow,swap,swap-stx-for-token,"Swap STX for tokens","SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.swap-helper-v1-03","(swap-helper token-in token-out amt-in min-out)","(contract-call? .swap-helper-v1-03 swap-helper .wstx .token-out u1000000 u950000)","https://docs.bitflow.finance"
9
- 8,bitflow,swap,swap-token-for-stx,"Swap tokens for STX","SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.swap-helper-v1-03","(swap-helper token-in token-out amt-in min-out)","(contract-call? .swap-helper-v1-03 swap-helper .token-in .wstx u1000000 u950000)","https://docs.bitflow.finance"
10
- 9,zest,supply,supply-asset,"Supply collateral to Zest","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","(add-asset pool-id asset amount)","(contract-call? .pool-v1-0 add-asset u0 .sbtc u1000000)","https://docs.zestprotocol.com"
11
- 10,zest,borrow,borrow-asset,"Borrow from Zest","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","(drawdown pool-id lp-token amount)","(contract-call? .pool-v1-0 drawdown u0 .lp-token u500000)","https://docs.zestprotocol.com"
12
- 11,zest,info,get-pool-data,"Get Zest pool info","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","(get-pool pool-id)","(contract-call? .pool-v1-0 get-pool u0)","https://docs.zestprotocol.com"
13
- 12,stackingdao,stake,deposit,"Stake STX for stSTX","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","(deposit amount)","(contract-call? .stacking-dao-core-v1 deposit u100000000)","https://docs.stackingdao.com"
14
- 13,stackingdao,unstake,withdraw,"Unstake stSTX for STX","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","(withdraw amount)","(contract-call? .stacking-dao-core-v1 withdraw u100000000)","https://docs.stackingdao.com"
15
- 14,boost,boost,boost-stx,"Boost STX earnings","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pox-fast-pool-v2","(delegate-stx amount pox-addr)","(contract-call? .pox-fast-pool-v2 delegate-stx u100000000 pox-addr)","https://boost.stacks.co"
16
- 15,faktory,swap,swap-tokens,"Swap on Faktory","SPTF1TGKT2AF5EJ0ZN56T87J14XSRFR9JFPFG2QV.faktory-v2-01","(swap token-in token-out amt-in min-out)","(contract-call? .faktory-v2-01 swap .token-in .token-out u1000000 u950000)","https://fak.fun"
1
+ id,language,protocol,category,name,description,code,imports_or_contract,notes
2
+ 1,clarity,alex,swap,swap-helper,"Swap tokens via Alex","(contract-call? .amm-swap-pool-v1-1 swap-helper .token-wstx .age000-governance-token u100000000 u100000000 u1000000 u1)","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","Use factors to maintain price ratios; dx is input amount; min-dy is minimum output"
3
+ 2,clarity,alex,pool,get-pool-details,"Get pool info","(contract-call? .amm-swap-pool-v1-1 get-pool-details .token-wstx .age000-governance-token)","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","Returns balance-x balance-y pool-token total-supply"
4
+ 3,clarity,alex,liquidity,add-to-position,"Add liquidity to Alex","(contract-call? .amm-swap-pool-v1-1 add-to-position .token-wstx .age000-governance-token u100000000 u100000000 u1000000)","SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-swap-pool-v1-1","Factors determine price impact; returns LP tokens"
5
+ 4,clarity,velar,swap,swap-exact-tokens,"Swap on Velar","(contract-call? .univ2-router swap-exact-tokens-for-tokens u1000000 u950000 (list .token-a .token-b))","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","Path can include multiple hops; min-out protects against slippage"
6
+ 5,clarity,velar,liquidity,add-liquidity,"Add liquidity to Velar","(contract-call? .univ2-router add-liquidity .token-a .token-b u1000000 u1000000 u900000 u900000)","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","Min amounts protect against front-running; returns LP tokens"
7
+ 6,clarity,velar,liquidity,remove-liquidity,"Remove liquidity from Velar","(contract-call? .univ2-router remove-liquidity .token-a .token-b u1000000 u900000 u900000)","SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1.univ2-router","Burns LP tokens; returns underlying tokens"
8
+ 7,clarity,bitflow,swap,swap-stx-for-token,"Swap STX for tokens","(contract-call? .swap-helper-v1-03 swap-helper .wstx .token-out u1000000 u950000)","SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.swap-helper-v1-03","Helper contract simplifies multi-hop swaps"
9
+ 8,clarity,bitflow,swap,swap-token-for-stx,"Swap tokens for STX","(contract-call? .swap-helper-v1-03 swap-helper .token-in .wstx u1000000 u950000)","SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.swap-helper-v1-03","Automatically finds best route"
10
+ 9,clarity,zest,supply,supply-asset,"Supply collateral to Zest","(contract-call? .pool-v1-0 add-asset u0 .sbtc u1000000)","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","Pool ID 0 is main pool; receives interest-bearing tokens"
11
+ 10,clarity,zest,borrow,borrow-asset,"Borrow from Zest","(contract-call? .pool-v1-0 drawdown u0 .lp-token u500000)","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","Requires collateral; interest accrues per block"
12
+ 11,clarity,zest,info,get-pool-data,"Get Zest pool info","(contract-call? .pool-v1-0 get-pool u0)","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pool-v1-0","Returns total-supplied total-borrowed interest-rate"
13
+ 12,clarity,stackingdao,stake,deposit,"Stake STX for stSTX","(contract-call? .stacking-dao-core-v1 deposit u100000000)","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","Liquid stacking; stSTX auto-compounds rewards"
14
+ 13,clarity,stackingdao,unstake,withdraw,"Unstake stSTX for STX","(contract-call? .stacking-dao-core-v1 withdraw u100000000)","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","Burns stSTX; may have cooldown period"
15
+ 14,clarity,boost,boost,boost-stx,"Boost STX earnings","(contract-call? .pox-fast-pool-v2 delegate-stx u100000000 pox-addr)","SP2VCQJGH7PHP2DJK7Z0V48AGBHQAW3R3ZW1QF4N.pox-fast-pool-v2","Fast Pool variant with higher APY"
16
+ 15,clarity,faktory,swap,swap-tokens,"Swap on Faktory","(contract-call? .faktory-v2-01 swap .token-in .token-out u1000000 u950000)","SPTF1TGKT2AF5EJ0ZN56T87J14XSRFR9JFPFG2QV.faktory-v2-01","Meme token DEX; high slippage possible"
17
+ 16,javascript,alex,swap,alex-swap-tx,"Build Alex swap transaction","const txOptions = { contractAddress: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM' contractName: 'amm-swap-pool-v1-1' functionName: 'swap-helper' functionArgs: [contractPrincipalCV(tokenXAddress tokenXName) contractPrincipalCV(tokenYAddress tokenYName) uintCV(100000000) uintCV(100000000) uintCV(amountIn) uintCV(minAmountOut)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall contractPrincipalCV uintCV } from '@stacks/transactions'","Factors are pool-specific; query pool details first"
18
+ 17,javascript,velar,swap,velar-swap-tx,"Build Velar swap transaction","const path = [contractPrincipalCV('SP...', 'token-a') contractPrincipalCV('SP...', 'token-b')]; const txOptions = { contractAddress: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1' contractName: 'univ2-router' functionName: 'swap-exact-tokens-for-tokens' functionArgs: [uintCV(amountIn) uintCV(minAmountOut) listCV(path)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV listCV contractPrincipalCV } from '@stacks/transactions'","Path supports multi-hop swaps; calculate min-out with slippage tolerance"
19
+ 18,javascript,velar,liquidity,velar-add-liquidity-tx,"Add liquidity to Velar via SDK","const txOptions = { contractAddress: 'SP1Y5YSTAHZ88XYK1VPDH24GY0HPX5J4JECTMY4A1' contractName: 'univ2-router' functionName: 'add-liquidity' functionArgs: [contractPrincipalCV(tokenAAddr tokenAName) contractPrincipalCV(tokenBAddr tokenBName) uintCV(amountA) uintCV(amountB) uintCV(minA) uintCV(minB)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV contractPrincipalCV } from '@stacks/transactions'","Set min amounts to ~2% less to handle price movements"
20
+ 19,api,alex,info,alex-pool-info,"Get Alex pool info via API","const response = await fetch('https://api.alexlab.co/v1/pool_tokens'); const pools = await response.json(); const pool = pools.find(p => p.token0 === tokenX && p.token1 === tokenY)","fetch or axios","Returns reserve0 reserve1 totalSupply volume24h"
21
+ 20,api,velar,info,velar-pool-info,"Get Velar pool info via API","const response = await fetch('https://api.velar.co/v1/pools'); const pools = await response.json(); const pool = pools.find(p => p.pair === `${token0}-${token1}`)","fetch or axios","Returns liquidity volume24h priceChange24h"
22
+ 21,javascript,bitflow,swap,bitflow-swap-tx,"Build Bitflow swap transaction","const txOptions = { contractAddress: 'SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9' contractName: 'swap-helper-v1-03' functionName: 'swap-helper' functionArgs: [contractPrincipalCV(tokenInAddr tokenInName) contractPrincipalCV(tokenOutAddr tokenOutName) uintCV(amountIn) uintCV(minAmountOut)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV contractPrincipalCV } from '@stacks/transactions'","Helper auto-routes through best pools"
23
+ 22,javascript,stackingdao,stake,stackingdao-deposit-sdk,"Deposit to StackingDAO via SDK","const txOptions = { contractAddress: 'SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG' contractName: 'stacking-dao-core-v1' functionName: 'deposit' functionArgs: [uintCV(amountMicroStx)] network }; const tx = await makeContractCall(txOptions); const broadcast = await broadcastTransaction({ transaction: tx network })","import { makeContractCall uintCV broadcastTransaction } from '@stacks/transactions'","Receive stSTX at 1:1 ratio; stSTX value increases over time from rewards"
24
+ 23,api,stackingdao,info,stackingdao-exchange-rate,"Get stSTX exchange rate","const response = await fetch('https://api.stackingdao.com/v1/info'); const info = await response.json(); const exchangeRate = info.stx_per_ststx","fetch or axios","Returns current STX/stSTX exchange rate and APY"
25
+ 24,javascript,slippage,calculate-min-amount-out,"Calculate minimum output with slippage","function calculateMinOut(expectedAmount slippagePercent) { return Math.floor(expectedAmount * (1 - slippagePercent / 100)) }","None","Common slippage: 0.5-2%; use higher for volatile pairs"
26
+ 25,api,aggregator,get-best-route,"Find best swap route across DEXs","const response = await fetch(`https://api.stacksswap.xyz/v1/route?from=${tokenIn}&to=${tokenOut}&amount=${amount}`); const route = await response.json(); console.log(route.path route.expectedOutput route.priceImpact)","fetch or axios","Aggregator finds optimal path across Alex Velar Bitflow"
@@ -0,0 +1,41 @@
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,clarity,trait,sip010-trait,"SIP-010 fungible token trait","(define-trait sip010-trait ((transfer (uint principal principal (optional (buff 34))) (response bool uint)) (get-name () (response (string-ascii 32) uint)) (get-symbol () (response (string-ascii 32) uint)) (get-decimals () (response uint uint)) (get-balance (principal) (response uint uint)) (get-total-supply () (response uint uint)) (get-token-uri () (response (optional (string-utf8 256)) uint))))","SIP-010 standard","Standard fungible token trait for Stacks"
3
+ 2,clarity,read,get-balance,"Get token balance","(ok (ft-get-balance token-name account))","SIP-010 function","Returns balance in base units (microTokens)"
4
+ 3,clarity,read,get-total-supply,"Get total token supply","(ok (ft-get-supply token-name))","SIP-010 function","Returns total minted tokens minus burned"
5
+ 4,clarity,read,get-decimals,"Get token decimals","(ok u6)","SIP-010 function","Standard: 6 decimals (1 token = 1000000 microTokens)"
6
+ 5,clarity,read,get-name,"Get token name","(ok token-name)","SIP-010 function","Human-readable token name"
7
+ 6,clarity,read,get-symbol,"Get token symbol","(ok token-symbol)","SIP-010 function","Token ticker symbol (3-5 chars)"
8
+ 7,clarity,read,get-token-uri,"Get token metadata URI","(ok (some token-uri))","SIP-010 function","Optional URI to token metadata JSON"
9
+ 8,clarity,transfer,transfer-token,"Transfer tokens","(begin (asserts! (> amount u0) err-invalid-amount) (try! (ft-transfer? token-name amount sender recipient)) (ok true))","SIP-010 function","Sender must have sufficient balance"
10
+ 9,clarity,mint,mint-tokens,"Mint new tokens","(begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (try! (ft-mint? token-name amount recipient)) (ok true))","Custom function","Only authorized minter can create tokens"
11
+ 10,clarity,burn,burn-tokens,"Burn (destroy) tokens","(begin (asserts! (is-eq tx-sender owner) err-not-authorized) (try! (ft-burn? token-name amount owner)) (ok true))","Custom function","Reduces total supply; irreversible"
12
+ 11,clarity,allowance,set-allowance,"Approve spender allowance","(ok (map-set allowances { owner: tx-sender spender: spender } { amount: amount }))","ERC-20 pattern","Allows spender to transfer tokens on behalf of owner"
13
+ 12,clarity,allowance,get-allowance,"Get spender allowance","(ok (default-to u0 (get amount (map-get? allowances { owner: owner spender: spender }))))","ERC-20 pattern","Returns approved amount for spender"
14
+ 13,clarity,allowance,transfer-from,"Transfer tokens using allowance","(let ((allowance (unwrap! (get-allowance owner spender) err-no-allowance))) (asserts! (>= allowance amount) err-insufficient-allowance) (try! (ft-transfer? token-name amount owner recipient)) (map-set allowances { owner: owner spender: spender } { amount: (- allowance amount) }) (ok true))","ERC-20 pattern","Spender transfers from owner's balance; reduces allowance"
15
+ 14,clarity,access,set-minter,"Set authorized minter","(begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (ok (map-set minters { minter: new-minter } { authorized: authorized })))","Access control","Manage who can mint tokens"
16
+ 15,clarity,pause,pause-transfers,"Pause token transfers","(begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (ok (var-set paused true)))","Emergency function","Temporarily disable all transfers"
17
+ 16,clarity,pause,unpause-transfers,"Resume token transfers","(begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (ok (var-set paused false)))","Emergency function","Re-enable transfers after pause"
18
+ 17,clarity,vesting,create-vesting-schedule,"Create token vesting schedule","(map-set vesting-schedules { recipient: recipient } { total-amount: amount start-time: start-block cliff-duration: cliff-blocks vesting-duration: total-blocks released: u0 })","Vesting function","Lock tokens with gradual release schedule"
19
+ 18,clarity,vesting,calculate-vested-amount,"Calculate vested tokens","(let ((schedule (unwrap! (map-get? vesting-schedules { recipient: recipient }) err-no-schedule)) (elapsed (- block-height (get start-time schedule)))) (if (< elapsed (get cliff-duration schedule)) u0 (min (/ (* (get total-amount schedule) elapsed) (get vesting-duration schedule)) (get total-amount schedule))))","Vesting function","Linear vesting after cliff period"
20
+ 19,clarity,vesting,release-vested-tokens,"Release vested tokens","(let ((vested (try! (calculate-vested-amount recipient))) (schedule (unwrap! (map-get? vesting-schedules { recipient: recipient }) err-no-schedule)) (released (get released schedule)) (releasable (- vested released))) (try! (ft-transfer? token-name releasable contract-principal recipient)) (map-set vesting-schedules { recipient: recipient } (merge schedule { released: vested })) (ok releasable))","Vesting function","Transfer available vested tokens to recipient"
21
+ 20,clarity,snapshot,take-balance-snapshot,"Take balance snapshot for voting","(map-set snapshots { snapshot-id: snapshot-id account: account } { balance: (ft-get-balance token-name account) })","Governance function","Record balances at specific block for voting"
22
+ 21,javascript,read,get-token-balance,"Get token balance via SDK","const response = await fetch(`https://api.hiro.so/extended/v1/address/${address}/balances`); const balances = await response.json(); const token = balances.fungible_tokens[`${contractAddress}.${contractName}::${tokenName}`]; return token ? token.balance : '0'","fetch or axios","Returns balance string in base units"
23
+ 22,javascript,read,get-token-info,"Get token metadata","const response = await fetch(`https://api.hiro.so/extended/v1/contract/${contractAddress}.${contractName}`); const contract = await response.json(); const metadata = { name: contract.name symbol: contract.symbol decimals: 6 }","fetch or axios","Parse from contract or metadata endpoint"
24
+ 23,javascript,transfer,transfer-token-tx,"Build token transfer transaction","const txOptions = { contractAddress contractName functionName: 'transfer' functionArgs: [uintCV(amountInBase) principalCV(sender) principalCV(recipient) noneCV()] network postConditions: [Pc.principal(sender).willSendLte(amountInBase).ft(contractAddress contractName tokenName)] }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV principalCV noneCV Pc } from '@stacks/transactions'","Amount in base units (microTokens); post-condition protects sender"
25
+ 24,javascript,mint,mint-token-tx,"Build mint transaction","const txOptions = { contractAddress contractName functionName: 'mint' functionArgs: [uintCV(amount) principalCV(recipient)] senderKey: minterPrivateKey network }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV principalCV } from '@stacks/transactions'","Only authorized minter can call; requires private key"
26
+ 25,javascript,allowance,approve-spender-tx,"Build approve allowance transaction","const txOptions = { contractAddress contractName functionName: 'approve' functionArgs: [principalCV(spender) uintCV(amount)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall principalCV uintCV } from '@stacks/transactions'","Allows spender to transfer tokens on behalf of sender"
27
+ 26,javascript,allowance,transfer-from-tx,"Build transfer-from transaction","const txOptions = { contractAddress contractName functionName: 'transfer-from' functionArgs: [principalCV(owner) principalCV(recipient) uintCV(amount)] network postConditions: [Pc.principal(owner).willSendLte(amount).ft(contractAddress contractName tokenName)] }; const tx = await makeContractCall(txOptions)","import { makeContractCall principalCV uintCV Pc } from '@stacks/transactions'","Spender transfers from owner's balance using allowance"
28
+ 27,javascript,utils,convert-decimals,"Convert between display and base units","function toBaseUnits(displayAmount decimals = 6) { return Math.floor(displayAmount * Math.pow(10 decimals)) } function toDisplayUnits(baseAmount decimals = 6) { return baseAmount / Math.pow(10 decimals) }","None","Display: 1.5 tokens; Base: 1500000 microTokens (6 decimals)"
29
+ 28,javascript,utils,format-token-amount,"Format token amount with symbol","function formatTokenAmount(baseAmount symbol decimals = 6) { const display = (baseAmount / Math.pow(10 decimals)).toFixed(decimals); return `${parseFloat(display).toLocaleString()} ${symbol}`}","None","Returns formatted string like '1,234.56 DIKO'"
30
+ 29,javascript,multicall,batch-token-transfers,"Batch transfer to multiple recipients","const transfers = recipients.map(({ address amount }) => ({ contractAddress contractName functionName: 'transfer' functionArgs: [uintCV(amount) principalCV(sender) principalCV(address) noneCV()] })); const txs = await Promise.all(transfers.map(opts => makeContractCall({ ...opts network })))","import { makeContractCall uintCV principalCV noneCV } from '@stacks/transactions'","Each transfer is separate transaction; consider gas costs"
31
+ 30,api,price,get-token-price,"Get token price from DEX","const response = await fetch(`https://api.alexlab.co/v1/price/${tokenSymbol}`); const data = await response.json(); return data.price_usd","fetch","Returns current USD price from Alex DEX"
32
+ 31,api,holders,get-token-holders,"Get list of token holders","const response = await fetch(`https://api.hiro.so/extended/v1/tokens/ft/metadata?contract_id=${contractAddress}.${contractName}::${tokenName}`); const data = await response.json(); return data.total_supply","fetch or axios","Returns holder count and distribution data"
33
+ 32,javascript,validation,validate-token-address,"Validate token contract exists","async function isValidToken(contractAddress contractName) { try { const response = await fetch(`https://api.hiro.so/v2/contracts/interface/${contractAddress}/${contractName}`); const data = await response.json(); return data.functions.some(f => f.name === 'transfer' || f.name === 'get-balance') } catch { return false }}","fetch","Checks if contract implements token interface"
34
+ 33,javascript,airdrop,calculate-airdrop-amounts,"Calculate proportional airdrop amounts","function calculateAirdrop(holders totalAirdrop) { const totalSupply = holders.reduce((sum h) => sum + h.balance 0); return holders.map(holder => ({ address: holder.address amount: Math.floor((holder.balance / totalSupply) * totalAirdrop) }))}","None","Distribute tokens proportionally to existing holders"
35
+ 34,javascript,liquidity,calculate-liquidity-value,"Calculate LP token value","function calculateLPValue(lpBalance reserve0 reserve1 totalLpSupply) { const share = lpBalance / totalLpSupply; return { token0Amount: reserve0 * share token1Amount: reserve1 * share }}","None","Calculate underlying assets for LP tokens"
36
+ 35,clarity,staking,stake-tokens,"Stake tokens for rewards","(begin (try! (ft-transfer? token-name amount tx-sender contract-principal)) (map-set stakes { staker: tx-sender } { amount: (+ (get-stake tx-sender) amount) staked-at: block-height }) (ok true))","Staking function","Lock tokens in contract for reward eligibility"
37
+ 36,clarity,staking,unstake-tokens,"Unstake tokens","(let ((stake (unwrap! (map-get? stakes { staker: tx-sender }) err-no-stake)) (amount (get amount stake))) (try! (ft-transfer? token-name amount contract-principal tx-sender)) (map-delete stakes { staker: tx-sender }) (ok amount))","Staking function","Withdraw staked tokens; may have cooldown period"
38
+ 37,clarity,staking,calculate-rewards,"Calculate staking rewards","(let ((stake (unwrap! (map-get? stakes { staker: staker }) err-no-stake)) (blocks-staked (- block-height (get staked-at stake))) (stake-amount (get amount stake))) (ok (/ (* stake-amount blocks-staked reward-rate) u1000000)))","Staking function","Linear rewards based on time and amount staked"
39
+ 38,javascript,defi,add-token-liquidity,"Add token to liquidity pool","const txOptions = { contractAddress: dexAddress contractName: dexName functionName: 'add-liquidity' functionArgs: [contractPrincipalCV(tokenAddress tokenName) uintCV(tokenAmount) uintCV(stxAmount) uintCV(minTokenAmount) uintCV(minStxAmount)] network postConditions: [Pc.principal(userAddress).willSendLte(tokenAmount).ft(tokenAddress tokenName token) Pc.principal(userAddress).willSendLte(stxAmount).ustx()] }; const tx = await makeContractCall(txOptions)","import { makeContractCall contractPrincipalCV uintCV Pc } from '@stacks/transactions'","Provide token and STX to pool; receive LP tokens"
40
+ 39,javascript,defi,remove-token-liquidity,"Remove token from liquidity pool","const txOptions = { contractAddress: dexAddress contractName: dexName functionName: 'remove-liquidity' functionArgs: [contractPrincipalCV(tokenAddress tokenName) uintCV(lpTokenAmount) uintCV(minTokenAmount) uintCV(minStxAmount)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall contractPrincipalCV uintCV } from '@stacks/transactions'","Burn LP tokens; receive underlying token and STX"
41
+ 40,javascript,governance,create-token-vote,"Create governance proposal","const txOptions = { contractAddress: governanceAddress contractName: governanceName functionName: 'propose' functionArgs: [stringUtf8CV(proposalTitle) stringUtf8CV(proposalDescription) contractPrincipalCV(targetContract targetFunction)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall stringUtf8CV contractPrincipalCV } from '@stacks/transactions'","Token holders can create and vote on proposals"
@@ -0,0 +1,31 @@
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,clarity,trait,sip009-trait,"SIP-009 NFT trait definition","(define-trait nft-trait ((get-last-token-id () (response uint uint)) (get-token-uri (uint) (response (optional (string-ascii 256)) uint)) (get-owner (uint) (response (optional principal) uint)) (transfer (uint principal principal) (response bool uint))))","SIP-009 standard","Required functions for NFT standard compliance"
3
+ 2,clarity,read,get-owner,"Get NFT owner","(map-get? nft-owners { token-id: token-id })","Internal map","Returns (optional principal); none if not minted"
4
+ 3,clarity,read,get-token-uri,"Get NFT metadata URI","(ok (some (concat base-uri (uint-to-ascii token-id))))","SIP-009 function","Returns IPFS or HTTP URL to metadata JSON"
5
+ 4,clarity,read,get-last-token-id,"Get last minted token ID","(ok (var-get last-token-id))","SIP-009 function","Used to determine next token ID for minting"
6
+ 5,clarity,mint,mint-nft,"Mint new NFT","(begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (let ((token-id (+ (var-get last-token-id) u1))) (try! (nft-mint? nft-asset token-id recipient)) (map-set nft-owners { token-id: token-id } recipient) (var-set last-token-id token-id) (ok token-id)))","Custom function","Only owner can mint; auto-increments token ID"
7
+ 6,clarity,transfer,transfer-nft,"Transfer NFT ownership","(begin (asserts! (is-eq tx-sender sender) err-not-authorized) (try! (nft-transfer? nft-asset token-id sender recipient)) (map-set nft-owners { token-id: token-id } recipient) (ok true))","SIP-009 function","Sender must be current owner; updates ownership map"
8
+ 7,clarity,burn,burn-nft,"Burn (destroy) NFT","(begin (asserts! (is-eq (unwrap! (get-owner token-id) err-not-found) tx-sender) err-not-authorized) (try! (nft-burn? nft-asset token-id tx-sender)) (map-delete nft-owners { token-id: token-id }) (ok true))","Custom function","Only owner can burn; permanently removes NFT"
9
+ 8,clarity,marketplace,list-nft,"List NFT for sale","(begin (asserts! (is-eq (unwrap! (get-owner token-id) err-not-found) tx-sender) err-not-authorized) (map-set listings { token-id: token-id } { seller: tx-sender price: price }) (ok true))","Marketplace function","Creates listing; NFT stays in owner wallet"
10
+ 9,clarity,marketplace,buy-nft,"Buy listed NFT","(let ((listing (unwrap! (map-get? listings { token-id: token-id }) err-not-listed)) (seller (get seller listing)) (price (get price listing))) (try! (stx-transfer? price tx-sender seller)) (try! (nft-transfer? nft-asset token-id seller tx-sender)) (map-delete listings { token-id: token-id }) (ok true))","Marketplace function","Transfers STX payment and NFT ownership atomically"
11
+ 10,clarity,marketplace,unlist-nft,"Remove NFT listing","(begin (asserts! (is-eq (get seller (unwrap! (map-get? listings { token-id: token-id }) err-not-listed)) tx-sender) err-not-authorized) (map-delete listings { token-id: token-id }) (ok true))","Marketplace function","Only seller can unlist; NFT ownership unchanged"
12
+ 11,clarity,royalty,set-royalty,"Set NFT royalty percentage","(define-data-var royalty-percent uint u5) (define-public (set-royalty (new-royalty uint)) (begin (asserts! (is-eq tx-sender contract-owner) err-not-authorized) (asserts! (<= new-royalty u100) err-invalid-royalty) (ok (var-set royalty-percent new-royalty))))","Custom function","Typical royalty: 2.5-10%; enforced on secondary sales"
13
+ 12,clarity,royalty,calculate-royalty,"Calculate royalty amount","(define-read-only (calculate-royalty (sale-price uint)) (/ (* sale-price (var-get royalty-percent)) u100))","Custom function","Returns royalty amount in microSTX"
14
+ 13,clarity,collection,get-total-supply,"Get total NFTs minted","(ok (var-get last-token-id))","Common read function","Returns total number of minted tokens"
15
+ 14,clarity,collection,get-collection-info,"Get collection metadata","(ok { name: collection-name symbol: collection-symbol total-supply: (var-get last-token-id) base-uri: base-uri })","Custom function","Returns collection-level metadata"
16
+ 15,clarity,batch,batch-mint,"Mint multiple NFTs","(fold mint-single recipients (ok (list)))","Custom function","Gas-efficient bulk minting for drops"
17
+ 16,javascript,read,get-nft-owner,"Get NFT owner via API","const response = await fetch(`https://api.hiro.so/extended/v1/tokens/nft/holdings?principal=${contractAddress}.${contractName}&token_id=${tokenId}`); const data = await response.json(); return data.results[0]?.owner","fetch or axios","Returns owner address or null if not minted"
18
+ 17,javascript,read,get-nft-metadata,"Fetch NFT metadata from URI","const response = await fetch(tokenUri); const metadata = await response.json(); console.log(metadata.name metadata.image metadata.attributes)","fetch","Standard metadata: name image description attributes"
19
+ 18,javascript,read,get-collection-nfts,"Get all NFTs in collection","const response = await fetch(`https://api.hiro.so/extended/v1/tokens/nft/holdings?principal=${contractAddress}.${contractName}`); const nfts = await response.json(); return nfts.results","fetch or axios","Returns array of token IDs and owners"
20
+ 19,javascript,mint,mint-nft-tx,"Build mint NFT transaction","const txOptions = { contractAddress contractName functionName: 'mint' functionArgs: [principalCV(recipientAddress)] network postConditions: [Pc.principal(userAddress).willSendAsset().nft(contractAddress contractName tokenId)] }; const tx = await makeContractCall(txOptions)","import { makeContractCall principalCV Pc } from '@stacks/transactions'","Post-condition protects against unexpected transfers"
21
+ 20,javascript,transfer,transfer-nft-tx,"Build transfer NFT transaction","const txOptions = { contractAddress contractName functionName: 'transfer' functionArgs: [uintCV(tokenId) principalCV(senderAddress) principalCV(recipientAddress)] network postConditions: [Pc.principal(senderAddress).willSendAsset().nft(contractAddress contractName tokenId)] }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV principalCV Pc } from '@stacks/transactions'","Sender must own NFT; use deny mode for security"
22
+ 21,javascript,marketplace,list-nft-tx,"Build list NFT transaction","const txOptions = { contractAddress: marketplaceAddress contractName: marketplaceName functionName: 'list-nft' functionArgs: [contractPrincipalCV(nftContract nftName) uintCV(tokenId) uintCV(priceInMicroStx)] network }; const tx = await makeContractCall(txOptions)","import { makeContractCall contractPrincipalCV uintCV } from '@stacks/transactions'","NFT stays in seller wallet until sold"
23
+ 22,javascript,marketplace,buy-nft-tx,"Build buy NFT transaction","const txOptions = { contractAddress: marketplaceAddress contractName: marketplaceName functionName: 'buy-nft' functionArgs: [contractPrincipalCV(nftContract nftName) uintCV(tokenId)] network postConditions: [Pc.principal(buyerAddress).willSendLte(priceInMicroStx).ustx() Pc.principal(sellerAddress).willReceiveGte(priceInMicroStx * 0.95).ustx()] }; const tx = await makeContractCall(txOptions)","import { makeContractCall contractPrincipalCV uintCV Pc } from '@stacks/transactions'","Post-conditions protect buyer and seller; account for fees"
24
+ 23,javascript,metadata,upload-metadata-ipfs,"Upload NFT metadata to IPFS","const metadata = { name: 'NFT Name' description: 'Description' image: 'ipfs://...' attributes: [{ trait_type: 'Background' value: 'Blue' }] }; const response = await fetch('https://api.pinata.cloud/pinning/pinJSONToIPFS' { method: 'POST' headers: { 'Content-Type': 'application/json' 'Authorization': `Bearer ${pinataJWT}` } body: JSON.stringify(metadata) }); const result = await response.json(); const tokenUri = `ipfs://${result.IpfsHash}`","fetch and Pinata API","Standard ERC-721 metadata format; store image on IPFS first"
25
+ 24,javascript,batch,batch-transfer-nfts,"Batch transfer multiple NFTs","const transfers = tokenIds.map(tokenId => ({ contractAddress contractName functionName: 'transfer' functionArgs: [uintCV(tokenId) principalCV(sender) principalCV(recipient)] })); const txs = await Promise.all(transfers.map(opts => makeContractCall({ ...opts network })))","import { makeContractCall uintCV principalCV } from '@stacks/transactions'","Each transfer is separate transaction; consider gas costs"
26
+ 25,api,marketplace,get-nft-listings,"Get NFT marketplace listings","const response = await fetch(`https://api.gamma.io/api/v1/collections/${contractId}/tokens`); const listings = await response.json(); const listed = listings.filter(nft => nft.listed)","fetch","Returns price seller token_id for listed NFTs"
27
+ 26,api,analytics,get-nft-sales-history,"Get NFT sales history","const response = await fetch(`https://api.gamma.io/api/v1/tokens/${contractId}/${tokenId}/sales`); const sales = await response.json(); console.log(sales.map(s => ({ price: s.price_stx buyer: s.buyer seller: s.seller date: s.timestamp })))","fetch","Returns historical sales data for price discovery"
28
+ 27,javascript,validation,validate-nft-ownership,"Verify user owns NFT","async function ownsNFT(userAddress contractAddress contractName tokenId) { const response = await fetch(`https://api.hiro.so/extended/v1/tokens/nft/holdings?principal=${contractAddress}.${contractName}&token_id=${tokenId}`); const data = await response.json(); return data.results[0]?.owner === userAddress }","fetch","Used for gating features or verifying ownership"
29
+ 28,javascript,traits,parse-nft-attributes,"Parse and filter NFT attributes","function parseTraits(attributes) { return attributes.reduce((acc trait) => { acc[trait.trait_type] = trait.value; return acc }, {}) }; function filterByTrait(nfts traitType traitValue) { return nfts.filter(nft => nft.metadata.attributes.some(attr => attr.trait_type === traitType && attr.value === traitValue)) }","None","Useful for rarity analysis and collection filtering"
30
+ 29,javascript,rarity,calculate-trait-rarity,"Calculate NFT trait rarity","function calculateRarity(collection trait) { const traitCount = collection.filter(nft => nft.attributes.some(a => a.trait_type === trait.trait_type && a.value === trait.value)).length; const rarity = (traitCount / collection.length) * 100; return { trait rarity percentage: rarity.toFixed(2) }","None","Lower percentage = rarer trait; sum trait rarities for overall rarity score"
31
+ 30,api,collection,get-collection-stats,"Get collection floor price and volume","const response = await fetch(`https://api.gamma.io/api/v1/collections/${contractId}/stats`); const stats = await response.json(); console.log({ floor_price: stats.floor_price volume_24h: stats.volume_24h total_volume: stats.total_volume holders: stats.unique_holders })","fetch","Real-time collection analytics from Gamma marketplace"
@@ -1,16 +1,26 @@
1
- id,category,name,description,code,contract,notes
2
- 1,info,get-pox-info,"Get current PoX cycle info","(contract-call? .pox-4 get-pox-info)","SP000000000000000000002Q6VF78.pox-4","Returns cycle number reward-cycle-length prepare-cycle-length min-threshold"
3
- 2,info,get-stacker-info,"Get stacker status","(contract-call? .pox-4 get-stacker-info stacker)","SP000000000000000000002Q6VF78.pox-4","Returns lock-period pox-addr start-burn-ht unlock-burn-ht"
4
- 3,stack,stack-stx,"Stack STX directly","(contract-call? .pox-4 stack-stx amount-ustx pox-addr start-burn-ht lock-period)","SP000000000000000000002Q6VF78.pox-4","Minimum 100000 STX (100000000000 microSTX)"
5
- 4,stack,stack-increase,"Increase stacked amount","(contract-call? .pox-4 stack-increase increase-by)","SP000000000000000000002Q6VF78.pox-4","Add more STX to existing stack"
6
- 5,stack,stack-extend,"Extend stacking period","(contract-call? .pox-4 stack-extend extend-count pox-addr)","SP000000000000000000002Q6VF78.pox-4","Extend lock period by cycles"
7
- 6,delegate,delegate-stx,"Delegate to pool operator","(contract-call? .pox-4 delegate-stx amount-ustx delegate-to until-burn-ht pox-addr)","SP000000000000000000002Q6VF78.pox-4","Pool will stack on your behalf"
8
- 7,delegate,revoke-delegate,"Revoke delegation","(contract-call? .pox-4 revoke-delegate-stx)","SP000000000000000000002Q6VF78.pox-4","Cancel delegation after unlock"
9
- 8,pool,fast-pool-delegate,"Delegate to Fast Pool","(contract-call? 'SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP.pox4-fast-pool-v3 delegate-stx amount)","SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP.pox4-fast-pool-v3","Popular community pool ~8% APY"
10
- 9,pool,planbetter-pool,"Delegate to PlanBetter Pool","(contract-call? 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.pox4-pools delegate amount)","SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.pox4-pools","Community pool variable APY"
11
- 10,pool,stackingdao-deposit,"Deposit to StackingDAO","(contract-call? 'SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1 deposit amount)","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","Get stSTX liquid stacking token"
12
- 11,rewards,get-reward-info,"Get stacking rewards","(contract-call? .pox-4 get-stacking-minimum)","SP000000000000000000002Q6VF78.pox-4","Returns minimum STX to stack"
13
- 12,address,create-pox-address,"Create PoX BTC address","{ version: (buff 1) hashbytes: (buff 32) }","N/A","Tuple for BTC reward address (version 0x00-0x06)"
14
- 13,cycle,get-current-cycle,"Get current reward cycle","(contract-call? .pox-4 current-pox-reward-cycle)","SP000000000000000000002Q6VF78.pox-4","Returns current cycle number"
15
- 14,cycle,burn-height-to-cycle,"Convert block to cycle","(contract-call? .pox-4 burn-height-to-reward-cycle height)","SP000000000000000000002Q6VF78.pox-4","Get cycle number from block height"
16
- 15,status,check-delegation,"Check delegation status","(contract-call? .pox-4 get-delegation-info stacker)","SP000000000000000000002Q6VF78.pox-4","Returns amount-ustx delegated-to until-burn-ht pox-addr"
1
+ id,language,category,name,description,code,imports_or_contract,notes
2
+ 1,clarity,info,get-pox-info,"Get current PoX cycle info","(contract-call? .pox-4 get-pox-info)","SP000000000000000000002Q6VF78.pox-4","Returns cycle number reward-cycle-length prepare-cycle-length min-threshold"
3
+ 2,clarity,info,get-stacker-info,"Get stacker status","(contract-call? .pox-4 get-stacker-info stacker)","SP000000000000000000002Q6VF78.pox-4","Returns lock-period pox-addr start-burn-ht unlock-burn-ht"
4
+ 3,clarity,stack,stack-stx,"Stack STX directly","(contract-call? .pox-4 stack-stx amount-ustx pox-addr start-burn-ht lock-period)","SP000000000000000000002Q6VF78.pox-4","Minimum 100000 STX (100000000000 microSTX)"
5
+ 4,clarity,stack,stack-increase,"Increase stacked amount","(contract-call? .pox-4 stack-increase increase-by)","SP000000000000000000002Q6VF78.pox-4","Add more STX to existing stack"
6
+ 5,clarity,stack,stack-extend,"Extend stacking period","(contract-call? .pox-4 stack-extend extend-count pox-addr)","SP000000000000000000002Q6VF78.pox-4","Extend lock period by cycles"
7
+ 6,clarity,delegate,delegate-stx,"Delegate to pool operator","(contract-call? .pox-4 delegate-stx amount-ustx delegate-to until-burn-ht pox-addr)","SP000000000000000000002Q6VF78.pox-4","Pool will stack on your behalf"
8
+ 7,clarity,delegate,revoke-delegate,"Revoke delegation","(contract-call? .pox-4 revoke-delegate-stx)","SP000000000000000000002Q6VF78.pox-4","Cancel delegation after unlock"
9
+ 8,clarity,pool,fast-pool-delegate,"Delegate to Fast Pool","(contract-call? 'SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP.pox4-fast-pool-v3 delegate-stx amount)","SP21YTSM60CAY6D011EZVEVNKXVW8FVZE198XEFFP.pox4-fast-pool-v3","Popular community pool ~8% APY"
10
+ 9,clarity,pool,planbetter-pool,"Delegate to PlanBetter Pool","(contract-call? 'SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.pox4-pools delegate amount)","SP1K1A1PMGW2ZJCNF46NWZWHG8TS1D23EGH1KNK60.pox4-pools","Community pool variable APY"
11
+ 10,clarity,pool,stackingdao-deposit,"Deposit to StackingDAO","(contract-call? 'SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1 deposit amount)","SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG.stacking-dao-core-v1","Get stSTX liquid stacking token"
12
+ 11,clarity,rewards,get-reward-info,"Get stacking rewards","(contract-call? .pox-4 get-stacking-minimum)","SP000000000000000000002Q6VF78.pox-4","Returns minimum STX to stack"
13
+ 12,clarity,address,create-pox-address,"Create PoX BTC address","{ version: (buff 1) hashbytes: (buff 32) }","N/A","Tuple for BTC reward address (version 0x00-0x06)"
14
+ 13,clarity,cycle,get-current-cycle,"Get current reward cycle","(contract-call? .pox-4 current-pox-reward-cycle)","SP000000000000000000002Q6VF78.pox-4","Returns current cycle number"
15
+ 14,clarity,cycle,burn-height-to-cycle,"Convert block to cycle","(contract-call? .pox-4 burn-height-to-reward-cycle height)","SP000000000000000000002Q6VF78.pox-4","Get cycle number from block height"
16
+ 15,clarity,status,check-delegation,"Check delegation status","(contract-call? .pox-4 get-delegation-info stacker)","SP000000000000000000002Q6VF78.pox-4","Returns amount-ustx delegated-to until-burn-ht pox-addr"
17
+ 16,api,info,get-pox-info-api,"Get PoX info via API","const response = await fetch('https://api.hiro.so/v2/pox'); const poxInfo = await response.json(); console.log(poxInfo.current_cycle)","fetch or axios","Returns current_cycle min_threshold prepare_length reward_slots"
18
+ 17,api,info,get-stacker-status,"Get stacker status via API","const response = await fetch(`https://api.hiro.so/extended/v1/address/${address}/stacking`); const status = await response.json()","fetch or axios","Returns stacked amount locked unlock_height pox_address"
19
+ 18,javascript,address,create-pox-address-js,"Create PoX address tuple in JavaScript","import { bufferCV tupleCV } from '@stacks/transactions'; const poxAddr = tupleCV({ version: bufferCV(Buffer.from([0x00])) hashbytes: bufferCV(Buffer.from('bitcoin_pubkey_hash' 'hex')) })","import { bufferCV tupleCV } from '@stacks/transactions'","Version: 0x00=P2PKH 0x01=P2SH 0x04=P2WPKH 0x05=P2WSH"
20
+ 19,javascript,stack,stack-stx-tx,"Build stack STX transaction","const txOptions = { contractAddress: 'SP000000000000000000002Q6VF78' contractName: 'pox-4' functionName: 'stack-stx' functionArgs: [uintCV(amountMicroStx) poxAddrCV uintCV(startBurnHeight) uintCV(lockPeriod)] senderKey: privateKey network anchorMode: AnchorMode.Any }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV AnchorMode } from '@stacks/transactions'","Lock period: 1-12 cycles; amount must meet minimum threshold"
21
+ 20,javascript,delegate,delegate-stx-tx,"Build delegate STX transaction","const txOptions = { contractAddress: 'SP000000000000000000002Q6VF78' contractName: 'pox-4' functionName: 'delegate-stx' functionArgs: [uintCV(amountMicroStx) principalCV(delegateAddress) noneCV() someCV(poxAddrCV)] senderKey: privateKey network }; const tx = await makeContractCall(txOptions)","import { makeContractCall uintCV principalCV noneCV someCV } from '@stacks/transactions'","Delegate to pool operator; use noneCV() for until-burn-ht to delegate indefinitely"
22
+ 21,javascript,pool,stackingdao-deposit-tx,"Deposit to StackingDAO via SDK","const txOptions = { contractAddress: 'SP4SZE494VC2YC5JYG7AYFQ44F5Q4PYV7DVMDPBG' contractName: 'stacking-dao-core-v1' functionName: 'deposit' functionArgs: [uintCV(amountMicroStx)] senderKey: privateKey network }; const tx = await makeContractCall(txOptions); await broadcastTransaction({ transaction: tx network })","import { makeContractCall uintCV broadcastTransaction } from '@stacks/transactions'","Receive stSTX liquid stacking token; auto-compounds rewards"
23
+ 22,javascript,cycle,get-current-cycle-js,"Calculate current PoX cycle from block height","function getCurrentCycle(blockHeight) { const FIRST_BURNCHAIN_BLOCK = 666050; const REWARD_CYCLE_LENGTH = 2100; return Math.floor((blockHeight - FIRST_BURNCHAIN_BLOCK) / REWARD_CYCLE_LENGTH) }","None","Mainnet constants; testnet uses different values"
24
+ 23,javascript,rewards,estimate-stacking-rewards,"Estimate stacking rewards","async function estimateRewards(amountStx durationCycles) { const res = await fetch('https://api.hiro.so/v2/pox'); const poxInfo = await res.json(); const totalStacked = poxInfo.total_liquid_supply_ustx * 0.25; const yourShare = amountStx / (totalStacked / 1000000); const btcPerCycle = 1000; return btcPerCycle * yourShare * durationCycles }","fetch","Approximate estimation; actual rewards vary based on Bitcoin block rewards"
25
+ 24,api,pool,get-pool-info,"Get stacking pool information","const response = await fetch('https://api.hiro.so/extended/v1/pox/cycles/${cycleNumber}/signers'); const poolData = await response.json()","fetch or axios","Returns signers weight signing_key pool_address for cycle"
26
+ 25,javascript,validation,validate-stacking-eligibility,"Check if address can stack","async function canStack(address amount) { const poxRes = await fetch('https://api.hiro.so/v2/pox'); const poxInfo = await poxRes.json(); const minThreshold = poxInfo.min_threshold_ustx; const balanceRes = await fetch(`https://api.hiro.so/extended/v1/address/${address}/balances`); const balance = await balanceRes.json(); return balance.stx.balance >= amount && amount >= minThreshold }","fetch","Validates balance and minimum threshold; returns boolean"
@@ -0,0 +1,76 @@
1
+ id,category,name,description,code,imports,notes
2
+ 1,wallet,connect-wallet,"Connect to Leather/Xverse wallet","const userData = await connect(); console.log('Connected:' userData.addresses.stx[0].address)","import { connect } from '@stacks/connect'","Returns userData with addresses.stx[0].address for STX and addresses.btc[0].address for BTC"
3
+ 2,wallet,get-address,"Get user's STX address from connected wallet","const { isConnected getLocalStorage } = await import('@stacks/connect'); if (!isConnected()) return null; const data = getLocalStorage(); return data?.addresses?.stx?.[0]?.address || null","import { isConnected getLocalStorage } from '@stacks/connect'","Use getLocalStorage() to access stored wallet data; check isConnected() first"
4
+ 3,wallet,disconnect,"Disconnect wallet","await disconnect(); localStorage.removeItem('walletAddress')","import { disconnect } from '@stacks/connect'","Disconnects wallet and clears session; also clear localStorage"
5
+ 4,wallet,check-connection,"Check if wallet is already connected","if (isConnected()) { console.log('Already authenticated'); return }","import { isConnected } from '@stacks/connect'","Check connection status before calling connect(); prevents duplicate connection prompts"
6
+ 5,wallet,connect-wallet-helper,"Complete connect wallet helper with isConnected check","async function connectWallet() { const { connect isConnected getLocalStorage } = await import('@stacks/connect'); if (isConnected()) { return getLocalStorage() }; return connect() }","import { connect isConnected getLocalStorage } from '@stacks/connect'","Production pattern: check if already connected before calling connect(); uses lazy import"
7
+ 6,wallet,connect-wallet-button,"Wallet connect button with loading states","function ConnectButton({ onConnect }) { const [connecting setConnecting] = useState(false); const handleConnect = async () => { setConnecting(true); try { const userData = await connect(); const address = userData.addresses.stx[0].address; localStorage.setItem('walletAddress' address); onConnect?.(address); setConnecting(false) } catch(e) { setConnecting(false) }}; return <button onClick={handleConnect} disabled={connecting}>{connecting ? 'Connecting...' : 'Connect Wallet'}</button> }","import { connect } from '@stacks/connect'; import { useState } from 'react'","React component; uses correct connect() API with userData.addresses.stx[0].address"
8
+ 7,wallet,use-wallet-hook,"Complete React hook for wallet connection management","function useWallet() { const [address setAddress] = useState(null); const [connected setConnected] = useState(false); useEffect(() => { const saved = localStorage.getItem('walletAddress'); if (saved) { setAddress(saved); setConnected(true) }}, []); const connectWallet = async () => { const userData = await connect(); const addr = userData.addresses.stx[0].address; setAddress(addr); setConnected(true); localStorage.setItem('walletAddress' addr); return userData }; const disconnectWallet = async () => { await disconnect(); setAddress(null); setConnected(false); localStorage.removeItem('walletAddress') }; return { address connected connect: connectWallet disconnect: disconnectWallet }}","import { connect disconnect } from '@stacks/connect'; import { useState useEffect } from 'react'","Complete wallet management with correct userData.addresses.stx[0].address pattern"
9
+ 8,wallet,disconnect-wallet-helper,"Complete disconnect helper with cleanup","async function disconnectWallet() { const { disconnect } = await import('@stacks/connect'); disconnect(); localStorage.clear() }","import { disconnect } from '@stacks/connect'","Disconnect and clear all localStorage; use localStorage.clear() or removeItem"
10
+ 9,wallet,disconnect-button,"Disconnect wallet with UI feedback and cleanup","function DisconnectButton({ onDisconnect }) { const handleDisconnect = async () => { const { disconnect } = await import('@stacks/connect'); await disconnect(); localStorage.removeItem('walletAddress'); localStorage.removeItem('stacks_wallet'); onDisconnect(); }; return <button onClick={handleDisconnect}>Disconnect</button> }","import { disconnect } from '@stacks/connect'","Cleans up both localStorage and @stacks/connect session"
11
+ 10,wallet,is-wallet-connected,"Check wallet connection status","async function isWalletConnected() { const { isConnected } = await import('@stacks/connect'); return isConnected() }","import { isConnected } from '@stacks/connect'","Returns boolean; call before attempting to access wallet data"
12
+ 11,wallet,get-wallet-addresses,"Get all wallet addresses (STX BTC) from connected wallet","async function getWalletAddresses() { const { isConnected getLocalStorage } = await import('@stacks/connect'); if (!isConnected()) return null; return getLocalStorage()?.addresses || null }","import { isConnected getLocalStorage } from '@stacks/connect'","Returns addresses object with stx and btc arrays; null if not connected"
13
+ 12,wallet,get-btc-address,"Get Bitcoin address from connected wallet","const { isConnected getLocalStorage } = await import('@stacks/connect'); if (!isConnected()) return null; const data = getLocalStorage(); return data?.addresses?.btc?.[0]?.address || null","import { isConnected getLocalStorage } from '@stacks/connect'","Returns BTC address string from addresses.btc[0].address"
14
+ 13,wallet,get-stx-and-btc-addresses,"Get both STX and BTC addresses","const { isConnected getLocalStorage } = await import('@stacks/connect'); if (!isConnected()) return null; const data = getLocalStorage(); const stxAddress = data?.addresses?.stx?.[0]?.address; const btcAddress = data?.addresses?.btc?.[0]?.address; return { stx: stxAddress btc: btcAddress }","import { isConnected getLocalStorage } from '@stacks/connect'","Returns object with both addresses; addresses are from first element of arrays"
15
+ 14,wallet,resolve-stx-address-helper,"Helper to resolve STX address from connected wallet","async function resolveStxAddress() { const { isConnected getLocalStorage } = await import('@stacks/connect'); if (!isConnected()) return null; const data = getLocalStorage(); return data?.addresses?.stx?.[0]?.address || null }","import { isConnected getLocalStorage } from '@stacks/connect'","Production helper matching sBTC Market pattern; returns STX address string or null"
16
+ 15,wallet,addresses-structure,"Understanding getLocalStorage addresses structure","const data = getLocalStorage(); // Returns: { addresses: { stx: [{ address: 'SP...' }] btc: [{ address: 'bc1...' }] } }","import { getLocalStorage } from '@stacks/connect'","Addresses are arrays; stx[0].address for STX, btc[0].address for BTC"
17
+ 16,wallet,display-wallet-address,"Display connected wallet with truncated address","function WalletDisplay({ address }) { const truncated = address ? `${address.slice(0 6)}...${address.slice(-4)}` : ''; const handleCopy = () => navigator.clipboard.writeText(address); return <div onClick={handleCopy}>{truncated}</div> }","import { useState } from 'react'","Shows first 6 and last 4 characters; click to copy full address"
18
+ 17,wallet,connection-status-badge,"Visual connection status indicator","function ConnectionStatus({ connected }) { return <div style={{ display: 'flex' alignItems: 'center' gap: '8px' }}><div style={{ width: 8 height: 8 borderRadius: '50%' background: connected ? '#10b981' : '#ef4444' }} /><span>{connected ? 'Connected' : 'Disconnected'}</span></div> }","import { React } from 'react'","Green dot for connected, red for disconnected; customizable styling"
19
+ 18,wallet,wallet-info-display,"Complete wallet info display with balance","function WalletInfo({ address }) { const [balance setBalance] = useState('0'); useEffect(() => { if (!address) return; fetch(`https://api.hiro.so/extended/v1/address/${address}/balances`).then(r => r.json()).then(data => setBalance((Number(data.stx.balance) / 1000000).toFixed(2))) }, [address]); return <div><div>{formatAddress(address)}</div><div>{balance} STX</div></div> }","import { useState useEffect } from 'react'","Fetches and displays STX balance; combines address display with balance"
20
+ 19,transaction,stx-transfer,"Transfer STX","await makeSTXTokenTransfer({ recipient amount senderKey network anchorMode: AnchorMode.Any })","import { makeSTXTokenTransfer AnchorMode } from '@stacks/transactions'","Amount in microSTX (1 STX = 1000000 microSTX)"
21
+ 20,transaction,contract-call,"Call contract function","await makeContractCall({ contractAddress contractName functionName functionArgs senderKey network anchorMode: AnchorMode.Any })","import { makeContractCall AnchorMode } from '@stacks/transactions'","Use cv.* constructors for functionArgs"
22
+ 21,transaction,deploy-contract,"Deploy Clarity contract","await makeContractDeploy({ contractName codeBody senderKey network anchorMode: AnchorMode.Any })","import { makeContractDeploy AnchorMode } from '@stacks/transactions'","codeBody is Clarity code as string"
23
+ 22,transaction,broadcast-tx,"Broadcast transaction","const txid = await broadcastTransaction(transaction network)","import { broadcastTransaction } from '@stacks/transactions'","Returns transaction ID"
24
+ 23,clarity-values,uint,"Create Clarity uint","uintCV(100)","import { uintCV } from '@stacks/transactions'","For uint function arguments"
25
+ 24,clarity-values,int,"Create Clarity int","intCV(-100)","import { intCV } from '@stacks/transactions'","For int function arguments"
26
+ 25,clarity-values,principal,"Create Clarity principal","principalCV('SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR')","import { principalCV } from '@stacks/transactions'","Standard or contract principal"
27
+ 26,clarity-values,string-ascii,"Create Clarity ASCII string","stringAsciiCV('hello world')","import { stringAsciiCV } from '@stacks/transactions'","ASCII characters only"
28
+ 27,clarity-values,string-utf8,"Create Clarity UTF-8 string","stringUtf8CV('hello 世界')","import { stringUtf8CV } from '@stacks/transactions'","Supports Unicode characters"
29
+ 28,clarity-values,buffer,"Create Clarity buffer","bufferCV(Buffer.from('data'))","import { bufferCV } from '@stacks/transactions'","Node.js Buffer or Uint8Array"
30
+ 29,clarity-values,tuple,"Create Clarity tuple","tupleCV({ name: stringAsciiCV('test') value: uintCV(100) })","import { tupleCV stringAsciiCV uintCV } from '@stacks/transactions'","Object with CV values"
31
+ 30,clarity-values,list,"Create Clarity list","listCV([uintCV(1) uintCV(2) uintCV(3)])","import { listCV uintCV } from '@stacks/transactions'","Array of CV values of same type"
32
+ 31,clarity-values,some,"Create Clarity some value","someCV(uintCV(100))","import { someCV uintCV } from '@stacks/transactions'","Optional value present"
33
+ 32,clarity-values,none,"Create Clarity none value","noneCV()","import { noneCV } from '@stacks/transactions'","Optional value absent"
34
+ 33,clarity-values,ok-response,"Create Clarity ok response","responseOkCV(uintCV(100))","import { responseOkCV uintCV } from '@stacks/transactions'","Success response"
35
+ 34,clarity-values,err-response,"Create Clarity err response","responseErrorCV(uintCV(404))","import { responseErrorCV uintCV } from '@stacks/transactions'","Error response"
36
+ 35,api,get-balance,"Get STX balance","const response = await fetch(`https://api.hiro.so/extended/v1/address/${address}/balances`)","fetch or axios","Returns STX balance and all token balances"
37
+ 36,api,get-transactions,"Get address transactions","const response = await fetch(`https://api.hiro.so/extended/v1/address/${address}/transactions`)","fetch or axios","Paginated results with limit and offset"
38
+ 37,api,get-contract-info,"Get contract info","const response = await fetch(`https://api.hiro.so/v2/contracts/interface/${address}/${contractName}`)","fetch or axios","Returns ABI and source code"
39
+ 38,api,call-read-only,"Call read-only function","const result = await callReadOnlyFunction({ contractAddress contractName functionName functionArgs senderAddress network })","import { callReadOnlyFunction } from '@stacks/transactions'","No transaction needed for read-only calls"
40
+ 39,api,get-transaction,"Get transaction by ID","const response = await fetch(`https://api.hiro.so/extended/v1/tx/${txid}`)","fetch or axios","Returns transaction details and status"
41
+ 40,network,mainnet,"Mainnet config","new StacksMainnet()","import { StacksMainnet } from '@stacks/network'","Production network"
42
+ 41,network,testnet,"Testnet config","new StacksTestnet()","import { StacksTestnet } from '@stacks/network'","Testing network"
43
+ 42,network,devnet,"Devnet config","new StacksDevnet()","import { StacksDevnet } from '@stacks/network'","Local development"
44
+ 43,post-conditions,stx-postcondition,"STX transfer post-condition","makeStandardSTXPostCondition(address FungibleConditionCode.Equal amount)","import { makeStandardSTXPostCondition FungibleConditionCode } from '@stacks/transactions'","Ensures exact STX amount transferred"
45
+ 44,post-conditions,ft-postcondition,"FT transfer post-condition","makeStandardFungiblePostCondition(address FungibleConditionCode.Equal amount assetInfo)","import { makeStandardFungiblePostCondition FungibleConditionCode createAssetInfo } from '@stacks/transactions'","Ensures exact token amount transferred"
46
+ 45,post-conditions,nft-postcondition,"NFT transfer post-condition","makeStandardNonFungiblePostCondition(address NonFungibleConditionCode.Sends assetInfo tokenId)","import { makeStandardNonFungiblePostCondition NonFungibleConditionCode createAssetInfo } from '@stacks/transactions'","Ensures NFT ownership transfer"
47
+ 46,state-management,react-context-provider,"Create React Context for wallet state with persistence","const Context = createContext(undefined); function Provider({ children }) { const [state setState] = useState(defaultState); useEffect(() => { localStorage.setItem(KEY JSON.stringify(state)) } [state]); return <Context.Provider value={state}>{children}</Context.Provider> }","import { createContext useState useEffect } from 'react'","React-specific; includes localStorage persistence and hydration"
48
+ 47,authentication,sign-message,"Sign message to prove wallet ownership","const { request } = await import('@stacks/connect'); const response = await request('stx_signMessage' { message: 'Sign to verify ownership' }); return { signature: response.signature publicKey: response.publicKey }","import { request } from '@stacks/connect'","Used for authentication without transfers; returns signature and publicKey"
49
+ 48,server-side,server-transaction,"Build and broadcast transaction from server","const tx = await makeContractCall({ contractAddress contractName functionName functionArgs senderKey network nonce anchorMode: AnchorMode.Any }); const result = await broadcastTransaction({ transaction: tx network })","import { makeContractCall broadcastTransaction AnchorMode } from '@stacks/transactions'","Requires senderKey (private key) and nonce management"
50
+ 49,server-side,fetch-nonce,"Get current nonce for server-side transactions","const response = await fetch(`https://api.hiro.so/extended/v1/address/${address}/nonces`); const data = await response.json(); return data.possible_next_nonce","fetch or axios","Essential for server-side transaction sequencing"
51
+ 50,server-side,wallet-sdk,"Generate wallet from seed phrase for server-side transactions","const wallet = await generateWallet({ secretKey: seedPhrase password }); const account = generateNewAccount(wallet); const address = getStxAddress(account.accounts[0] networkKey)","import { generateWallet generateNewAccount getStxAddress } from '@stacks/wallet-sdk'","For server-side automation; keep seed phrases secure"
52
+ 51,transaction,complex-contract-call,"Contract call with multiple arguments and types","const args = [stringUtf8CV(question) uintCV(BigInt(block)) bufferCV(hexToBuff(id)) intCV(BigInt(price)) tupleCV({ field: valueCV })]; await openContractCall(functionName args)","import { stringUtf8CV uintCV bufferCV intCV tupleCV } from '@stacks/transactions'","Shows proper type conversion for complex arguments"
53
+ 52,utilities,hex-to-buffer,"Convert hex string to buffer for Clarity","function hexToBuff(hex) { const clean = hex.replace(/^0x/ ''); return Buffer.from(clean 'hex') }","Node.js Buffer or @stacks/common","Essential for buffer arguments like feed IDs"
54
+ 53,advanced-api,fetch-readonly,"Call read-only function with fetchCallReadOnlyFunction","const result = await fetchCallReadOnlyFunction({ contractAddress contractName functionName functionArgs: [uintCV(id)] network senderAddress }); const json = cvToJSON(result)","import { fetchCallReadOnlyFunction uintCV cvToJSON } from '@stacks/transactions'","No transaction fee; use for queries"
55
+ 54,utilities,unwrap-response,"Unwrap (ok) response from read-only calls","function unwrapResponseOk(cvJson) { if (cvJson.type === 'responseOk') return cvJson.value; if (cvJson.success) return cvJson.value; return null }","None (utility function)","Handles different response formats from cvToJSON"
56
+ 55,utilities,parse-cv-response,"Parse and extract values from ClarityValue JSON","const json = cvToJSON(result); const ok = unwrapResponseOk(json); if (!ok) return null; const value = BigInt(ok.value)","import { cvToJSON } from '@stacks/transactions'","Common pattern for processing read-only responses"
57
+ 56,utilities,lazy-import,"Lazy load Stacks.js to reduce bundle size","let modulePromise = null; async function getModule() { if (!modulePromise) modulePromise = import('@stacks/connect'); return modulePromise }","Dynamic import()","Reduces initial bundle; cache promise for reuse"
58
+ 57,network,custom-fetch-network,"Create network with custom fetch for headers","const customFetch = async (input init) => { const headers = { ...init?.headers 'x-hiro-api-key': key }; return fetch(input { ...init headers }) }; createNetwork({ network: 'mainnet' client: { baseUrl: url fetch: customFetch }})","import { createNetwork } from '@stacks/network'","Useful for API key management and request customization"
59
+ 58,hooks,use-price-hook,"React hook for fetching external price data","function useBtcPrice() { const [price setPrice] = useState(0); useEffect(() => { const fetchPrice = async () => { const res = await fetch(url); setPrice(await res.json()) }; fetchPrice(); const interval = setInterval(fetchPrice 60000); return () => clearInterval(interval) } []); return price }","import { useState useEffect } from 'react'","React-specific; shows interval cleanup pattern"
60
+ 59,advanced-api,parallel-reads,"Execute multiple read-only calls in parallel","const promises = ids.map(id => fetchCallReadOnlyFunction({ contractAddress contractName functionName functionArgs: [uintCV(id)] network senderAddress })); const results = await Promise.all(promises)","import { fetchCallReadOnlyFunction uintCV } from '@stacks/transactions'","More efficient than sequential calls"
61
+ 60,clarity-values,contract-principal,"Create contract principal ClarityValue","const [address name] = contractId.split('.'); contractPrincipalCV(address name)","import { contractPrincipalCV } from '@stacks/transactions'","For passing contract references as arguments"
62
+ 61,clarity-values,boolean-cv,"Create boolean ClarityValue from JavaScript boolean","function boolCV(value) { return value ? trueCV() : falseCV() }","import { trueCV falseCV } from '@stacks/transactions'","Helper for converting JS boolean to Clarity"
63
+ 62,utilities,cv-to-hex,"Encode ClarityValue to hex for request","const hexArgs = functionArgs.map(arg => cvToHex(arg))","import { cvToHex } from '@stacks/transactions'","Used with request('stx_callContract') for Stacks Connect"
64
+ 63,utilities,parse-tuple-response,"Parse tuple fields from read-only response","const json = cvToJSON(result); const ok = unwrapResponseOk(json); const fields = ok.value; return { name: fields.name.value count: BigInt(fields.count.value) }","import { cvToJSON } from '@stacks/transactions'","Common for contract data structures"
65
+ 64,network,env-network-config,"Network configuration based on environment","const networkKey = process.env.NETWORK === 'mainnet' ? 'mainnet' : 'testnet'; const rpcUrl = process.env.RPC_URL || defaultRpc[networkKey]; const network = createNetwork({ network: networkKey client: { baseUrl: rpcUrl }})","import { createNetwork } from '@stacks/network'","Standard pattern for multi-environment apps"
66
+ 65,transaction,post-condition-mode,"Set post-condition mode for transactions","await makeContractCall({ ...options postConditionMode: PostConditionMode.Allow })","import { makeContractCall PostConditionMode } from '@stacks/transactions'","Allow or Deny; Allow skips post-condition validation"
67
+ 66,state-management,vanilla-state-persist,"Persist wallet state with vanilla JavaScript (no React)","function saveWallet(data) { localStorage.setItem('wallet' JSON.stringify(data)) }; function loadWallet() { const raw = localStorage.getItem('wallet'); return raw ? JSON.parse(raw) : null }","None (native browser API)","Framework-agnostic alternative to React Context; works in any JavaScript environment"
68
+ 67,utilities,poll-tx-status,"Poll transaction status until confirmed or failed","async function pollTxStatus(txid) { while (true) { const res = await fetch(`https://api.hiro.so/extended/v1/tx/${txid}`); const tx = await res.json(); if (tx.tx_status === 'success' || tx.tx_status === 'abort_by_response') return tx; await new Promise(r => setTimeout(r 3000)) }}","fetch","Polls every 3 seconds; returns when transaction confirms or fails"
69
+ 68,transaction,sequential-calls,"Execute multiple contract calls in sequence","async function callSequence(calls network senderKey) { let nonce = await getNonce(address); for (const call of calls) { const tx = await makeContractCall({ ...call senderKey network nonce: nonce++ }); await broadcastTransaction({ transaction: tx network }) }}","import { makeContractCall broadcastTransaction } from '@stacks/transactions'","Manages nonce increments for sequential transactions"
70
+ 69,transaction,custom-tx-options,"Override transaction fee and nonce manually","await makeContractCall({ contractAddress contractName functionName functionArgs senderKey network nonce: customNonce fee: BigInt(10000) anchorMode: AnchorMode.Any })","import { makeContractCall AnchorMode } from '@stacks/transactions'","Fee in microSTX; useful for batch transactions or custom nonce management"
71
+ 70,utilities,hiro-headers,"Add randomized Hiro API headers for rate limiting","function getHiroHeaders() { const keys = ['key1' 'key2' 'key3']; const randomKey = keys[Math.floor(Math.random() * keys.length)]; return { 'x-hiro-api-key': randomKey 'Content-Type': 'application/json' }}","None","Rotates API keys to distribute rate limits across multiple keys"
72
+ 71,utilities,format-balance,"Format STX balance from microSTX to STX with decimals","function formatStx(microStx decimals = 6) { const stx = Number(microStx) / 1000000; return stx.toFixed(decimals) }","None","1 STX = 1,000,000 microSTX; default to 6 decimal places"
73
+ 72,transaction,tx-error-handling,"Comprehensive error handling for transaction failures","try { const result = await broadcastTransaction(tx network); return result } catch (error) { if (error.message.includes('ConflictingNonceInMempool')) throw new Error('Nonce conflict wait and retry'); if (error.message.includes('NotEnoughFunds')) throw new Error('Insufficient balance'); throw error }","None (error handling pattern)","Handles common transaction errors with user-friendly messages"
74
+ 73,network,switch-network,"Dynamically switch between networks at runtime","function getNetwork(networkName) { const networks = { mainnet: new StacksMainnet() testnet: new StacksTestnet() devnet: new StacksDevnet() }; return networks[networkName] || networks.testnet }","import { StacksMainnet StacksTestnet StacksDevnet } from '@stacks/network'","Factory pattern for network switching; defaults to testnet if unknown"
75
+ 74,state-management,persist-wallet-connection,"Save wallet connection state to localStorage","function saveWalletState(address network connected) { const state = { address network connected timestamp: Date.now() }; localStorage.setItem('stacks_wallet' JSON.stringify(state)) }; function loadWalletState() { const raw = localStorage.getItem('stacks_wallet'); if (!raw) return null; const state = JSON.parse(raw); const hourAgo = Date.now() - 3600000; if (state.timestamp < hourAgo) return null; return state }","None (native browser API)","Includes timestamp expiry (1 hour); prevents stale connections"
76
+ 75,utilities,format-wallet-address,"Format wallet address for display (truncated)","function formatAddress(address maxLength = 12) { if (!address) return ''; if (address.length <= maxLength) return address; const start = Math.floor((maxLength - 3) / 2); const end = address.length - (maxLength - 3 - start); return `${address.slice(0 start)}...${address.slice(end)}` }","None","Configurable truncation; default shows ~6 chars + ... + ~3 chars"
@@ -15,10 +15,15 @@ DOMAINS = {
15
15
  'templates': 'contract-templates.csv',
16
16
  'security': 'security-patterns.csv',
17
17
  'defi': 'defi-protocols.csv',
18
- 'stacksjs': 'stacks-js.csv',
18
+ 'stacksjs': 'stacks-js-core.csv',
19
19
  'bns': 'bns.csv',
20
20
  'stacking': 'stacking.csv',
21
- 'deployment': 'deployment.csv'
21
+ 'deployment': 'deployment.csv',
22
+ 'nfts': 'nfts.csv',
23
+ 'tokens': 'fungible-tokens.csv',
24
+ 'auth': 'authentication.csv',
25
+ 'advanced': 'advanced-patterns.csv',
26
+ 'chainhooks': 'chainhooks.csv'
22
27
  }
23
28
 
24
29
  # Auto-detection keywords
@@ -30,7 +35,12 @@ DOMAIN_KEYWORDS = {
30
35
  'stacksjs': ['javascript', 'stacks.js', 'connect', 'wallet', 'frontend', 'react', 'typescript'],
31
36
  'bns': ['bns', 'name', 'domain', '.btc', 'resolve', 'register'],
32
37
  'stacking': ['stacking', 'pox', 'delegate', 'pool', 'reward', 'cycle', 'bitcoin'],
33
- 'deployment': ['deploy', 'mainnet', 'testnet', 'clarinet', 'devnet']
38
+ 'deployment': ['deploy', 'mainnet', 'testnet', 'clarinet', 'devnet'],
39
+ 'nfts': ['nft', 'sip-009', 'mint', 'transfer', 'metadata', 'collection', 'marketplace', 'gamma'],
40
+ 'tokens': ['sip-010', 'fungible', 'token', 'balance', 'allowance', 'transfer-from', 'decimals'],
41
+ 'auth': ['authentication', 'session', 'sign', 'verify', 'profile', 'encrypt', 'jwt', 'oauth', 'webhook'],
42
+ 'advanced': ['pagination', 'swr', 'activity', 'presale', 'lottery', 'portfolio', 'wizard', 'launchpad', 'template', 'milestone', 'vesting', 'export', 'csv', 'modal', 'confirmation'],
43
+ 'chainhooks': ['chainhook', 'webhook', 'txid', 'contract-call', 'print-event', 'ft-event', 'nft-event', 'stx-event', 'predicate', 'hiro', 'indexing', 'ordinals']
34
44
  }
35
45
 
36
46
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stacksagent",
3
- "version": "1.2.3",
3
+ "version": "1.3.0",
4
4
  "description": "AI Skill for building Stacks blockchain applications - CLI installer",
5
5
  "bin": {
6
6
  "stacksagent": "./dist/index.js"