stacksagent 1.0.1 → 1.1.2
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.
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
id,category,name,description,code,imports,notes
|
|
2
|
-
1,wallet,connect-wallet,"Connect to Leather/Xverse","const
|
|
3
|
-
2,wallet,get-address,"Get user's STX address","const
|
|
4
|
-
3,wallet,disconnect,"Disconnect wallet","
|
|
2
|
+
1,wallet,connect-wallet,"Connect to Leather/Xverse wallet","const response = await connect(); console.log('Connected:' response.addresses.mainnet)","import { connect } from '@stacks/connect'","Returns response with addresses object containing mainnet and testnet addresses"
|
|
3
|
+
2,wallet,get-address,"Get user's STX address after connecting","const response = await connect(); const mainnetAddress = response.addresses.mainnet; const testnetAddress = response.addresses.testnet","import { connect } from '@stacks/connect'","Response contains both mainnet and testnet addresses"
|
|
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
5
|
4,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)"
|
|
6
6
|
5,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"
|
|
7
7
|
6,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"
|
|
@@ -29,3 +29,40 @@ id,category,name,description,code,imports,notes
|
|
|
29
29
|
28,post-conditions,stx-postcondition,"STX transfer post-condition","makeStandardSTXPostCondition(address FungibleConditionCode.Equal amount)","import { makeStandardSTXPostCondition FungibleConditionCode } from '@stacks/transactions'","Ensures exact STX amount transferred"
|
|
30
30
|
29,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"
|
|
31
31
|
30,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"
|
|
32
|
+
32,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"
|
|
33
|
+
33,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"
|
|
34
|
+
34,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"
|
|
35
|
+
35,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"
|
|
36
|
+
36,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"
|
|
37
|
+
37,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"
|
|
38
|
+
38,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"
|
|
39
|
+
39,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"
|
|
40
|
+
40,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"
|
|
41
|
+
41,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"
|
|
42
|
+
42,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"
|
|
43
|
+
43,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"
|
|
44
|
+
44,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"
|
|
45
|
+
45,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"
|
|
46
|
+
46,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"
|
|
47
|
+
47,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"
|
|
48
|
+
48,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"
|
|
49
|
+
49,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"
|
|
50
|
+
50,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"
|
|
51
|
+
51,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"
|
|
52
|
+
52,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"
|
|
53
|
+
53,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"
|
|
54
|
+
54,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"
|
|
55
|
+
55,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"
|
|
56
|
+
56,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"
|
|
57
|
+
57,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"
|
|
58
|
+
58,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"
|
|
59
|
+
59,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"
|
|
60
|
+
60,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 response = await connect(); localStorage.setItem('walletAddress' response.addresses.mainnet); onConnect?.(response.addresses.mainnet); 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 new connect() API and saves address to localStorage"
|
|
61
|
+
61,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"
|
|
62
|
+
62,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 response = await connect(); const addr = response.addresses.mainnet; setAddress(addr); setConnected(true); localStorage.setItem('walletAddress' addr); return response }; 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 new connect() API and localStorage persistence"
|
|
63
|
+
63,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"
|
|
64
|
+
64,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"
|
|
65
|
+
65,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"
|
|
66
|
+
66,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"
|
|
67
|
+
67,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"
|
|
68
|
+
68,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"
|