stacksagent 1.1.3 → 1.2.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.
- package/dist/assets/.claude/skills/stacks-agent/SKILL.md +3 -3
- package/dist/assets/.shared/stacks-agent/data/stacks-js.csv +5 -1
- package/dist/commands/init.js +8 -8
- package/dist/commands/init.js.map +1 -1
- package/dist/index.js +0 -0
- package/package.json +1 -1
- package/dist/assets/.claude/skills/stacks-agent/data/bns.csv +0 -11
- package/dist/assets/.claude/skills/stacks-agent/data/clarity-syntax.csv +0 -62
- package/dist/assets/.claude/skills/stacks-agent/data/contract-templates.csv +0 -15
- package/dist/assets/.claude/skills/stacks-agent/data/defi-protocols.csv +0 -16
- package/dist/assets/.claude/skills/stacks-agent/data/deployment.csv +0 -26
- package/dist/assets/.claude/skills/stacks-agent/data/security-patterns.csv +0 -16
- package/dist/assets/.claude/skills/stacks-agent/data/stacking.csv +0 -16
- package/dist/assets/.claude/skills/stacks-agent/data/stacks-js.csv +0 -31
- package/dist/assets/.claude/skills/stacks-agent/scripts/core.py +0 -165
- package/dist/assets/.claude/skills/stacks-agent/scripts/search.py +0 -62
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: stacks-agent
|
|
3
3
|
description: AI-powered intelligence for building Stacks blockchain applications
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.1.4
|
|
5
5
|
author: kai-builder
|
|
6
6
|
triggers:
|
|
7
7
|
- stacks
|
|
@@ -41,7 +41,7 @@ This skill includes searchable databases for:
|
|
|
41
41
|
- **14 Contract templates** - FT, NFT, DAO, Vault, Marketplace, Stacking
|
|
42
42
|
- **15 Security patterns** - Common vulnerabilities and fixes
|
|
43
43
|
- **15 DeFi protocols** - Alex, Velar, Bitflow, Zest, StackingDAO, Boost, Faktory
|
|
44
|
-
- **
|
|
44
|
+
- **72 Stacks.js snippets** - Production wallet patterns (connect, getLocalStorage, isConnected), transactions, API calls, React hooks, server-side patterns
|
|
45
45
|
- **10 BNS operations** - Name registration and resolution
|
|
46
46
|
- **15 Stacking guides** - PoX stacking and delegation
|
|
47
47
|
- **25 Deployment steps** - Testnet, mainnet, and devnet
|
|
@@ -57,7 +57,7 @@ Analyze user request to determine:
|
|
|
57
57
|
|
|
58
58
|
### Step 2: Search Knowledge Base
|
|
59
59
|
```bash
|
|
60
|
-
python3 .
|
|
60
|
+
python3 .shared/stacks-agent/scripts/search.py "<query>" --domain <domain>
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
Available domains:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
id,category,name,description,code,imports,notes
|
|
2
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
|
|
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
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"
|
|
@@ -66,3 +66,7 @@ id,category,name,description,code,imports,notes
|
|
|
66
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
|
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
|
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"
|
|
69
|
+
69,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"
|
|
70
|
+
70,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"
|
|
71
|
+
71,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"
|
|
72
|
+
72,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"
|
package/dist/commands/init.js
CHANGED
|
@@ -8,13 +8,13 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const chalk_1 = __importDefault(require("chalk"));
|
|
10
10
|
const PLATFORMS = {
|
|
11
|
-
claude: ['.claude/skills/stacks-agent'],
|
|
12
|
-
cursor: ['.
|
|
13
|
-
windsurf: ['.
|
|
14
|
-
antigravity: ['.agent
|
|
15
|
-
copilot: ['.
|
|
16
|
-
kiro: ['.
|
|
17
|
-
codex: ['.codex/skills/stacks-agent'],
|
|
11
|
+
claude: ['.shared/stacks-agent', '.claude/skills/stacks-agent'],
|
|
12
|
+
cursor: ['.shared/stacks-agent', '.cursor/commands'],
|
|
13
|
+
windsurf: ['.shared/stacks-agent', '.windsurf/workflows'],
|
|
14
|
+
antigravity: ['.shared/stacks-agent', '.agent/workflows'],
|
|
15
|
+
copilot: ['.shared/stacks-agent', '.github/prompts'],
|
|
16
|
+
kiro: ['.shared/stacks-agent', '.kiro/steering'],
|
|
17
|
+
codex: ['.shared/stacks-agent', '.codex/skills/stacks-agent'],
|
|
18
18
|
all: [] // Special case: all platforms
|
|
19
19
|
};
|
|
20
20
|
async function init(options) {
|
|
@@ -48,6 +48,6 @@ async function init(options) {
|
|
|
48
48
|
console.log(chalk_1.default.gray(' Cursor/Windsurf: Use /stacksagent command'));
|
|
49
49
|
console.log(chalk_1.default.gray(' Copilot: Use @stacksagent in chat\n'));
|
|
50
50
|
console.log(chalk_1.default.gray('Search knowledge base:'));
|
|
51
|
-
console.log(chalk_1.default.gray(' python3 .
|
|
51
|
+
console.log(chalk_1.default.gray(' python3 .shared/stacks-agent/scripts/search.py "query"\n'));
|
|
52
52
|
}
|
|
53
53
|
//# sourceMappingURL=init.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;;;AAeA,oBAsCC;AArDD,wDAA0B;AAC1B,gDAAwB;AACxB,kDAA0B;AAE1B,MAAM,SAAS,GAAG;IAChB,MAAM,EAAE,CAAC,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":";;;;;AAeA,oBAsCC;AArDD,wDAA0B;AAC1B,gDAAwB;AACxB,kDAA0B;AAE1B,MAAM,SAAS,GAAG;IAChB,MAAM,EAAE,CAAC,sBAAsB,EAAE,6BAA6B,CAAC;IAC/D,MAAM,EAAE,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;IACpD,QAAQ,EAAE,CAAC,sBAAsB,EAAE,qBAAqB,CAAC;IACzD,WAAW,EAAE,CAAC,sBAAsB,EAAE,kBAAkB,CAAC;IACzD,OAAO,EAAE,CAAC,sBAAsB,EAAE,iBAAiB,CAAC;IACpD,IAAI,EAAE,CAAC,sBAAsB,EAAE,gBAAgB,CAAC;IAChD,KAAK,EAAE,CAAC,sBAAsB,EAAE,4BAA4B,CAAC;IAC7D,GAAG,EAAE,EAAc,CAAC,8BAA8B;CACnD,CAAC;AAEK,KAAK,UAAU,IAAI,CAAC,OAA0D;IACnF,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE1B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,0CAA0C,EAAE,OAAO,CAAC,CAAC,CAAC;IAE7E,MAAM,SAAS,GAAG,EAAE,KAAK,KAAK;QAC5B,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC;QACjD,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAET,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,OAAO,GAAG,SAAS,CAAC,QAAkC,CAAC,CAAC;QAE9D,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;YAC7B,MAAM,OAAO,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,MAAM,CAAC,CAAC;YAC1D,MAAM,QAAQ,GAAG,cAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAExC,IAAI,kBAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACtC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,MAAM,CAAC,SAAS,MAAM,4CAA4C,CAAC,CAAC,CAAC;gBACvF,SAAS;YACX,CAAC;YAED,IAAI,CAAC;gBACH,MAAM,kBAAE,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;gBACjC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC,CAAC;YACnD,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,GAAG,CAAC,sBAAsB,MAAM,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAC;IAC5E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClC,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,8DAA8D,CAAC,CAAC,CAAC;IACxF,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;IACjE,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,4DAA4D,CAAC,CAAC,CAAC;AACxF,CAAC"}
|
package/dist/index.js
CHANGED
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,11 +0,0 @@
|
|
|
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,62 +0,0 @@
|
|
|
1
|
-
id,category,name,syntax,description,example,notes
|
|
2
|
-
1,types,uint,"uint","Unsigned integer (0 to 2^128-1)","(define-data-var counter uint u0)","Use u prefix for literals"
|
|
3
|
-
2,types,int,"int","Signed integer (-2^127 to 2^127-1)","(define-data-var balance int 0)","Can be negative"
|
|
4
|
-
3,types,bool,"bool","Boolean true/false","(define-data-var active bool true)","true or false only"
|
|
5
|
-
4,types,principal,"principal","Stacks address or contract","tx-sender","SP... or ST... format"
|
|
6
|
-
5,types,buff,"(buff n)","Fixed-length byte buffer","(buff 32)","Max 1MB"
|
|
7
|
-
6,types,string-ascii,"(string-ascii n)","ASCII string","(string-ascii 50)","ASCII chars only"
|
|
8
|
-
7,types,string-utf8,"(string-utf8 n)","UTF-8 string","(string-utf8 100)","Unicode support"
|
|
9
|
-
8,types,list,"(list n type)","Fixed-length list","(list 10 uint)","Homogeneous types"
|
|
10
|
-
9,types,tuple,"{ key: type }","Named fields","{ name: (string-ascii 50), age: uint }","Like struct"
|
|
11
|
-
10,types,optional,"(optional type)","Maybe value","(optional uint)","some/none"
|
|
12
|
-
11,types,response,"(response ok-type err-type)","Result type","(response bool uint)","ok/err"
|
|
13
|
-
12,functions,define-public,"(define-public (name (arg type)) body)","Public function","(define-public (transfer (amount uint)) (ok true))","Callable externally"
|
|
14
|
-
13,functions,define-read-only,"(define-read-only (name) body)","Read-only function","(define-read-only (get-balance) (ok u100))","No state changes"
|
|
15
|
-
14,functions,define-private,"(define-private (name) body)","Private function","(define-private (helper) u1)","Internal only"
|
|
16
|
-
15,functions,define-data-var,"(define-data-var name type value)","State variable","(define-data-var owner principal tx-sender)","Mutable storage"
|
|
17
|
-
16,functions,define-map,"(define-map name key-type value-type)","Key-value map","(define-map balances principal uint)","Persistent storage"
|
|
18
|
-
17,functions,define-constant,"(define-constant name value)","Constant value","(define-constant ERR-UNAUTHORIZED (err u401))","Immutable"
|
|
19
|
-
18,functions,define-fungible-token,"(define-fungible-token name supply?)","Create FT","(define-fungible-token MY-TOKEN u1000000)","SIP-010 base"
|
|
20
|
-
19,functions,define-non-fungible-token,"(define-non-fungible-token name type)","Create NFT","(define-non-fungible-token MY-NFT uint)","SIP-009 base"
|
|
21
|
-
20,control,if,"(if condition then else)","Conditional","(if (> x u0) u1 u0)","Both branches required"
|
|
22
|
-
21,control,match,"(match opt (some val) expr none-expr)","Pattern match","(match (get-user) user (ok user) (err u404))","Optional/response"
|
|
23
|
-
22,control,let,"(let ((var val)) body)","Local binding","(let ((x u1) (y u2)) (+ x y))","Scoped variables"
|
|
24
|
-
23,control,begin,"(begin expr1 expr2 ...)","Sequence","(begin (print ""hi"") (ok true))","Returns last"
|
|
25
|
-
24,control,asserts!,"(asserts! condition error)","Assert or abort","(asserts! (is-eq tx-sender owner) ERR-UNAUTHORIZED)","Stops execution"
|
|
26
|
-
25,control,try!,"(try! response)","Unwrap or propagate","(try! (ft-transfer? token u100 from to))","Early return on err"
|
|
27
|
-
26,control,unwrap!,"(unwrap! opt error)","Unwrap or error","(unwrap! (map-get? users id) ERR-NOT-FOUND)","Must succeed"
|
|
28
|
-
27,control,unwrap-panic,"(unwrap-panic opt)","Unwrap or panic","(unwrap-panic (some u1))","Use carefully"
|
|
29
|
-
28,arithmetic,+,"(+ a b ...)","Addition","(+ u1 u2 u3)","Auto-checks overflow"
|
|
30
|
-
29,arithmetic,-,"(- a b)","Subtraction","(- u10 u5)","Returns uint if uint"
|
|
31
|
-
30,arithmetic,*,"(* a b ...)","Multiplication","(* u5 u3)","Auto-checks overflow"
|
|
32
|
-
31,arithmetic,/,"(/ a b)","Division","(/ u10 u2)","Integer division"
|
|
33
|
-
32,arithmetic,mod,"(mod a b)","Modulo","(mod u10 u3)","Remainder"
|
|
34
|
-
33,comparison,is-eq,"(is-eq a b)","Equality check","(is-eq tx-sender owner)","Works with all types"
|
|
35
|
-
34,comparison,>,"(> a b)","Greater than","(> u5 u3)","true or false"
|
|
36
|
-
35,comparison,<,"(< a b)","Less than","(< u3 u5)","true or false"
|
|
37
|
-
36,comparison,>=,"(>= a b)","Greater than or equal","(>= u5 u5)","true or false"
|
|
38
|
-
37,comparison,<=,"(<= a b)","Less than or equal","(<= u3 u5)","true or false"
|
|
39
|
-
38,logic,and,"(and expr1 expr2 ...)","Logical AND","(and (> x u0) (< x u100))","Short-circuits"
|
|
40
|
-
39,logic,or,"(or expr1 expr2 ...)","Logical OR","(or (is-eq x u1) (is-eq x u2))","Short-circuits"
|
|
41
|
-
40,logic,not,"(not expr)","Logical NOT","(not (is-eq x u0))","Inverts boolean"
|
|
42
|
-
41,map-functions,map-set,"(map-set map key value)","Set map entry","(map-set balances user u100)","Creates or updates"
|
|
43
|
-
42,map-functions,map-get?,"(map-get? map key)","Get map value","(map-get? balances user)","Returns optional"
|
|
44
|
-
43,map-functions,map-delete,"(map-delete map key)","Delete map entry","(map-delete balances user)","Removes key"
|
|
45
|
-
44,map-functions,map-insert,"(map-insert map key value)","Insert if not exists","(map-insert balances user u100)","False if exists"
|
|
46
|
-
45,var-functions,var-get,"(var-get var)","Get variable value","(var-get counter)","Returns current value"
|
|
47
|
-
46,var-functions,var-set,"(var-set var value)","Set variable value","(var-set counter u10)","Updates value"
|
|
48
|
-
47,token-functions,ft-transfer?,"(ft-transfer? token amount from to)","Transfer fungible tokens","(ft-transfer? my-token u100 tx-sender recipient)","Returns response"
|
|
49
|
-
48,token-functions,ft-mint?,"(ft-mint? token amount recipient)","Mint fungible tokens","(ft-mint? my-token u1000 recipient)","Increases supply"
|
|
50
|
-
49,token-functions,ft-burn?,"(ft-burn? token amount sender)","Burn fungible tokens","(ft-burn? my-token u100 tx-sender)","Decreases supply"
|
|
51
|
-
50,token-functions,ft-get-balance,"(ft-get-balance token principal)","Get FT balance","(ft-get-balance my-token user)","Returns uint"
|
|
52
|
-
51,token-functions,ft-get-supply,"(ft-get-supply token)","Get total supply","(ft-get-supply my-token)","Returns uint"
|
|
53
|
-
52,token-functions,nft-transfer?,"(nft-transfer? nft id from to)","Transfer NFT","(nft-transfer? my-nft u1 tx-sender recipient)","Returns response"
|
|
54
|
-
53,token-functions,nft-mint?,"(nft-mint? nft id recipient)","Mint NFT","(nft-mint? my-nft u1 recipient)","Returns response"
|
|
55
|
-
54,token-functions,nft-burn?,"(nft-burn? nft id sender)","Burn NFT","(nft-burn? my-nft u1 tx-sender)","Returns response"
|
|
56
|
-
55,token-functions,nft-get-owner?,"(nft-get-owner? nft id)","Get NFT owner","(nft-get-owner? my-nft u1)","Returns optional principal"
|
|
57
|
-
56,stx-functions,stx-transfer?,"(stx-transfer? amount from to)","Transfer STX","(stx-transfer? u1000000 tx-sender recipient)","Amount in microSTX"
|
|
58
|
-
57,stx-functions,stx-burn?,"(stx-burn? amount sender)","Burn STX","(stx-burn? u1000000 tx-sender)","Destroys STX"
|
|
59
|
-
58,stx-functions,stx-get-balance,"(stx-get-balance principal)","Get STX balance","(stx-get-balance tx-sender)","Returns uint"
|
|
60
|
-
59,contract-functions,contract-call?,"(contract-call? contract function args...)","Call external contract","(contract-call? .other-contract transfer u100)","Returns response"
|
|
61
|
-
60,contract-functions,as-contract,"(as-contract expr)","Execute as contract","(as-contract (stx-transfer? u100 tx-sender recipient))","Contract is tx-sender"
|
|
62
|
-
61,contract-functions,contract-of,"(contract-of trait-ref)","Get contract principal","(contract-of .token-trait)","Returns principal"
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
id,category,name,description,traits,use_case,features
|
|
2
|
-
1,token,sip010-basic,"Basic SIP-010 fungible token","SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard","Meme tokens utility tokens","transfer get-name get-symbol get-decimals get-balance get-total-supply get-token-uri"
|
|
3
|
-
2,token,sip010-mintable,"SIP-010 with mint function","sip-010-trait","Reward tokens inflationary","All SIP-010 functions plus mint (owner-only)"
|
|
4
|
-
3,token,sip010-burnable,"SIP-010 with burn on transfer","sip-010-trait","Deflationary tokens","All SIP-010 functions plus burn mechanism"
|
|
5
|
-
4,token,sip010-capped,"SIP-010 with max supply cap","sip-010-trait","Limited supply tokens","All SIP-010 functions with supply cap check"
|
|
6
|
-
5,nft,sip009-basic,"Basic SIP-009 NFT collection","SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait","PFP collections","transfer get-last-token-id get-token-uri get-owner"
|
|
7
|
-
6,nft,sip009-mintable,"SIP-009 with public mint","nft-trait","Open mints allowlists","All SIP-009 functions plus public mint"
|
|
8
|
-
7,nft,sip009-royalties,"SIP-009 with royalty support","nft-trait","Creator royalties","All SIP-009 functions plus royalty tracking"
|
|
9
|
-
8,defi,vault-basic,"Simple STX vault","none","Savings staking","deposit withdraw get-balance"
|
|
10
|
-
9,defi,vault-timelocked,"Vault with unlock period","none","Vesting lockups","deposit withdraw-after-period get-unlock-time"
|
|
11
|
-
10,defi,pool-basic,"Basic liquidity pool","none","DEX pools","add-liquidity remove-liquidity swap get-reserves"
|
|
12
|
-
11,dao,dao-basic,"Simple DAO with proposals","none","Governance","create-proposal vote execute-proposal"
|
|
13
|
-
12,dao,dao-treasury,"DAO with treasury management","none","Protocol governance","All DAO functions plus treasury management"
|
|
14
|
-
13,marketplace,nft-marketplace,"NFT listing and sales","nft-trait","NFT trading","list-nft unlist-nft buy-nft get-listing"
|
|
15
|
-
14,stacking,stacking-pool,"Stacking pool delegation","none","Pool operators","delegate revoke get-delegation-info claim-rewards"
|
|
@@ -1,16 +0,0 @@
|
|
|
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,26 +0,0 @@
|
|
|
1
|
-
id,network,step,description,command,notes
|
|
2
|
-
1,testnet,faucet,"Get testnet STX","Visit https://explorer.hiro.so/sandbox/faucet?chain=testnet","Free testnet tokens for testing"
|
|
3
|
-
2,testnet,check-syntax,"Check contract syntax","clarinet check","Local validation before deployment"
|
|
4
|
-
3,testnet,deploy-cli,"Deploy via Clarinet CLI","clarinet deployments apply -p deployments/default.testnet-plan.yaml","Requires Clarinet installed"
|
|
5
|
-
4,testnet,deploy-explorer,"Deploy via Hiro Explorer","Visit https://explorer.hiro.so/sandbox/deploy?chain=testnet","Paste contract code in browser"
|
|
6
|
-
5,testnet,verify,"Verify testnet deployment","Visit https://explorer.hiro.so/txid/{txid}?chain=testnet","Check transaction status"
|
|
7
|
-
6,testnet,call-function,"Call function on testnet","clarinet console (contract-call? .contract-name function-name args)","Test contract functionality"
|
|
8
|
-
7,mainnet,check-balance,"Ensure sufficient STX","stacks-cli balance {address}","Need ~0.5 STX for deployment fee"
|
|
9
|
-
8,mainnet,deploy-cli,"Deploy via Clarinet CLI","clarinet deployments apply -p deployments/default.mainnet-plan.yaml","~0.1-0.5 STX fee"
|
|
10
|
-
9,mainnet,deploy-explorer,"Deploy via Hiro Explorer","Visit https://explorer.hiro.so/sandbox/deploy?chain=mainnet","Connect Leather or Xverse wallet"
|
|
11
|
-
10,mainnet,verify,"Verify mainnet deployment","Visit https://explorer.hiro.so/txid/{txid}?chain=mainnet","Wait ~10 minutes for confirmation"
|
|
12
|
-
11,mainnet,contract-address,"Get contract address","SP{address}.{contract-name}","Format: deployer-address.contract-name"
|
|
13
|
-
12,both,clarinet-check,"Validate contract locally","clarinet check","Check syntax and type errors"
|
|
14
|
-
13,both,clarinet-test,"Run contract tests","clarinet test","Execute test suite"
|
|
15
|
-
14,both,clarinet-console,"Interactive REPL","clarinet console","Test functions interactively"
|
|
16
|
-
15,both,format-check,"Check code formatting","clarinet format --check","Ensure proper Clarity formatting"
|
|
17
|
-
16,devnet,start-devnet,"Start local devnet","clarinet integrate","Local blockchain for development"
|
|
18
|
-
17,devnet,deploy-local,"Deploy to local devnet","clarinet deployments apply -p deployments/default.devnet-plan.yaml","Test on local chain"
|
|
19
|
-
18,tools,install-clarinet,"Install Clarinet CLI","brew install clarinet (macOS) or visit https://github.com/hirosystems/clarinet","Required for local development"
|
|
20
|
-
19,tools,install-stacks-cli,"Install Stacks CLI","npm install -g @stacks/cli","Command-line tool for Stacks"
|
|
21
|
-
20,verification,read-contract,"Read deployed contract","https://api.hiro.so/v2/contracts/interface/{address}/{name}","Get contract ABI and source"
|
|
22
|
-
21,verification,call-read-only,"Test read-only function","curl https://api.hiro.so/v2/contracts/call-read/{address}/{name}/{function}","Call without transaction"
|
|
23
|
-
22,security,audit-checklist,"Security audit checklist","Review access controls input validation error handling reentrancy","Pre-deployment security review"
|
|
24
|
-
23,security,testnet-first,"Always test on testnet first","Deploy to testnet -> test thoroughly -> then deploy to mainnet","Prevent costly mainnet mistakes"
|
|
25
|
-
24,monitoring,setup-alerts,"Monitor contract activity","Use Hiro Platform or custom indexer","Track contract calls and events"
|
|
26
|
-
25,post-deployment,verify-source,"Publish verified source","Submit to Hiro Explorer or blockchain explorers","Increase contract transparency and trust"
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
id,severity,category,name,description,vulnerable_code,secure_code,explanation
|
|
2
|
-
1,critical,access,missing-sender-check,"No tx-sender validation","(define-public (withdraw (amount uint)) (stx-transfer? amount (as-contract tx-sender) recipient))","(define-public (withdraw (amount uint)) (begin (asserts! (is-eq tx-sender owner) ERR-UNAUTHORIZED) (stx-transfer? amount (as-contract tx-sender) tx-sender)))","Always verify tx-sender for sensitive operations"
|
|
3
|
-
2,critical,access,missing-owner-check,"Owner-only function not protected","(define-public (set-fee (new-fee uint)) (ok (var-set fee new-fee)))","(define-public (set-fee (new-fee uint)) (begin (asserts! (is-eq tx-sender (var-get owner)) ERR-UNAUTHORIZED) (ok (var-set fee new-fee))))","Admin functions must check ownership"
|
|
4
|
-
3,critical,errors,unchecked-transfer,"Transfer without error handling","(stx-transfer? amount tx-sender recipient)","(try! (stx-transfer? amount tx-sender recipient))","Always check transfer return values with try! or unwrap!"
|
|
5
|
-
4,high,reentrancy,state-after-call,"State updated after external call","(begin (contract-call? .other transfer) (var-set balance u0))","(begin (var-set balance u0) (contract-call? .other transfer))","Update state before external calls to prevent reentrancy"
|
|
6
|
-
5,high,arithmetic,unchecked-subtraction,"Subtraction can underflow","(- balance amount)","(if (>= balance amount) (- balance amount) u0)","Check before subtracting uints to prevent underflow"
|
|
7
|
-
6,high,arithmetic,division-by-zero,"No zero divisor check","(/ total count)","(if (> count u0) (/ total count) u0)","Always check divisor > 0 before division"
|
|
8
|
-
7,high,validation,missing-amount-check,"Zero amount not validated","(define-public (transfer (amount uint)) ...)","(begin (asserts! (> amount u0) ERR-INVALID-AMOUNT) ...)","Reject zero amounts to prevent useless transactions"
|
|
9
|
-
8,medium,validation,missing-address-check,"Self-transfer not prevented","(ft-transfer? token amount sender recipient)","(begin (asserts! (not (is-eq sender recipient)) ERR-SELF-TRANSFER) (ft-transfer? token amount sender recipient))","Prevent sender = recipient to avoid bugs"
|
|
10
|
-
9,medium,access,unprotected-mint,"Anyone can mint tokens","(define-public (mint (amount uint)) (ft-mint? token amount tx-sender))","(define-public (mint (amount uint)) (begin (asserts! (is-eq tx-sender minter) ERR-UNAUTHORIZED) (ft-mint? token amount tx-sender)))","Restrict minting to authorized addresses only"
|
|
11
|
-
10,medium,access,tx-sender-vs-caller,"Wrong sender check","(asserts! (is-eq contract-caller owner) ERR-UNAUTHORIZED)","(asserts! (is-eq tx-sender owner) ERR-UNAUTHORIZED)","Use tx-sender for auth not contract-caller"
|
|
12
|
-
11,low,gas,unbounded-loop,"Loop without size limit","(map process-item (list-get items))","(begin (asserts! (<= (len items) u100) ERR-TOO-MANY) (map process-item items))","Limit iteration count to prevent excessive gas"
|
|
13
|
-
12,low,clarity,magic-numbers,"Hardcoded values","(if (> fee u100) ...)","(define-constant MAX-FEE u100) (if (> fee MAX-FEE) ...)","Use named constants for clarity and maintainability"
|
|
14
|
-
13,low,style,missing-error-constant,"Inline error codes","(err u100)","(define-constant ERR-UNAUTHORIZED (err u100))","Define error codes as named constants"
|
|
15
|
-
14,informational,docs,missing-comments,"No function documentation","(define-public (transfer (amount uint)) ...)",";;@desc Transfer tokens\n(define-public (transfer (amount uint)) ...)","Add comments to explain function purpose"
|
|
16
|
-
15,informational,naming,non-kebab-case,"Wrong naming convention","(define-public (transferTokens ...)","(define-public (transfer-tokens ...)","Use kebab-case for all identifiers"
|
|
@@ -1,16 +0,0 @@
|
|
|
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,31 +0,0 @@
|
|
|
1
|
-
id,category,name,description,code,imports,notes
|
|
2
|
-
1,wallet,connect-wallet,"Connect to Leather/Xverse","const userData = await showConnect({ appDetails onFinish: (data) => setUser(data) userSession })","import { showConnect } from '@stacks/connect'","Returns user session with address and profile"
|
|
3
|
-
2,wallet,get-address,"Get user's STX address","const address = userSession.loadUserData().profile.stxAddress.mainnet","import { AppConfig UserSession } from '@stacks/auth'","mainnet or testnet property"
|
|
4
|
-
3,wallet,disconnect,"Disconnect wallet","userSession.signUserOut()","import { UserSession } from '@stacks/auth'","Clears local session data"
|
|
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
|
-
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
|
-
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"
|
|
8
|
-
7,transaction,broadcast-tx,"Broadcast transaction","const txid = await broadcastTransaction(transaction network)","import { broadcastTransaction } from '@stacks/transactions'","Returns transaction ID"
|
|
9
|
-
8,clarity-values,uint,"Create Clarity uint","uintCV(100)","import { uintCV } from '@stacks/transactions'","For uint function arguments"
|
|
10
|
-
9,clarity-values,int,"Create Clarity int","intCV(-100)","import { intCV } from '@stacks/transactions'","For int function arguments"
|
|
11
|
-
10,clarity-values,principal,"Create Clarity principal","principalCV('SP2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR')","import { principalCV } from '@stacks/transactions'","Standard or contract principal"
|
|
12
|
-
11,clarity-values,string-ascii,"Create Clarity ASCII string","stringAsciiCV('hello world')","import { stringAsciiCV } from '@stacks/transactions'","ASCII characters only"
|
|
13
|
-
12,clarity-values,string-utf8,"Create Clarity UTF-8 string","stringUtf8CV('hello 世界')","import { stringUtf8CV } from '@stacks/transactions'","Supports Unicode characters"
|
|
14
|
-
13,clarity-values,buffer,"Create Clarity buffer","bufferCV(Buffer.from('data'))","import { bufferCV } from '@stacks/transactions'","Node.js Buffer or Uint8Array"
|
|
15
|
-
14,clarity-values,tuple,"Create Clarity tuple","tupleCV({ name: stringAsciiCV('test') value: uintCV(100) })","import { tupleCV stringAsciiCV uintCV } from '@stacks/transactions'","Object with CV values"
|
|
16
|
-
15,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"
|
|
17
|
-
16,clarity-values,some,"Create Clarity some value","someCV(uintCV(100))","import { someCV uintCV } from '@stacks/transactions'","Optional value present"
|
|
18
|
-
17,clarity-values,none,"Create Clarity none value","noneCV()","import { noneCV } from '@stacks/transactions'","Optional value absent"
|
|
19
|
-
18,clarity-values,ok-response,"Create Clarity ok response","responseOkCV(uintCV(100))","import { responseOkCV uintCV } from '@stacks/transactions'","Success response"
|
|
20
|
-
19,clarity-values,err-response,"Create Clarity err response","responseErrorCV(uintCV(404))","import { responseErrorCV uintCV } from '@stacks/transactions'","Error response"
|
|
21
|
-
20,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"
|
|
22
|
-
21,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"
|
|
23
|
-
22,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"
|
|
24
|
-
23,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"
|
|
25
|
-
24,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"
|
|
26
|
-
25,network,mainnet,"Mainnet config","new StacksMainnet()","import { StacksMainnet } from '@stacks/network'","Production network"
|
|
27
|
-
26,network,testnet,"Testnet config","new StacksTestnet()","import { StacksTestnet } from '@stacks/network'","Testing network"
|
|
28
|
-
27,network,devnet,"Devnet config","new StacksDevnet()","import { StacksDevnet } from '@stacks/network'","Local development"
|
|
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
|
-
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
|
-
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"
|
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Core search engine using BM25 ranking with regex matching
|
|
3
|
-
"""
|
|
4
|
-
|
|
5
|
-
import csv
|
|
6
|
-
import re
|
|
7
|
-
import math
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
from typing import List, Dict, Any, Optional
|
|
10
|
-
from collections import defaultdict
|
|
11
|
-
|
|
12
|
-
# Domain to CSV file mapping
|
|
13
|
-
DOMAINS = {
|
|
14
|
-
'clarity': 'clarity-syntax.csv',
|
|
15
|
-
'templates': 'contract-templates.csv',
|
|
16
|
-
'security': 'security-patterns.csv',
|
|
17
|
-
'defi': 'defi-protocols.csv',
|
|
18
|
-
'stacksjs': 'stacks-js.csv',
|
|
19
|
-
'bns': 'bns.csv',
|
|
20
|
-
'stacking': 'stacking.csv',
|
|
21
|
-
'deployment': 'deployment.csv'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
# Auto-detection keywords
|
|
25
|
-
DOMAIN_KEYWORDS = {
|
|
26
|
-
'clarity': ['define', 'uint', 'principal', 'let', 'begin', 'asserts', 'unwrap', 'function', 'type', 'syntax'],
|
|
27
|
-
'templates': ['token', 'nft', 'sip-010', 'sip-009', 'vault', 'dao', 'template', 'contract'],
|
|
28
|
-
'security': ['vulnerability', 'security', 'audit', 'attack', 'safe', 'check', 'exploit'],
|
|
29
|
-
'defi': ['swap', 'pool', 'liquidity', 'alex', 'velar', 'bitflow', 'zest', 'borrow', 'lend', 'boost'],
|
|
30
|
-
'stacksjs': ['javascript', 'stacks.js', 'connect', 'wallet', 'frontend', 'react', 'typescript'],
|
|
31
|
-
'bns': ['bns', 'name', 'domain', '.btc', 'resolve', 'register'],
|
|
32
|
-
'stacking': ['stacking', 'pox', 'delegate', 'pool', 'reward', 'cycle', 'bitcoin'],
|
|
33
|
-
'deployment': ['deploy', 'mainnet', 'testnet', 'clarinet', 'devnet']
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
class BM25:
|
|
38
|
-
"""BM25 ranking algorithm"""
|
|
39
|
-
|
|
40
|
-
def __init__(self, documents: List[str], k1: float = 1.5, b: float = 0.75):
|
|
41
|
-
self.k1 = k1
|
|
42
|
-
self.b = b
|
|
43
|
-
self.documents = documents
|
|
44
|
-
self.doc_len = [len(doc.split()) for doc in documents]
|
|
45
|
-
self.avgdl = sum(self.doc_len) / len(documents) if documents else 0
|
|
46
|
-
self.doc_freqs = self._calc_doc_freqs()
|
|
47
|
-
self.idf = self._calc_idf()
|
|
48
|
-
|
|
49
|
-
def _calc_doc_freqs(self) -> Dict[str, int]:
|
|
50
|
-
freqs = defaultdict(int)
|
|
51
|
-
for doc in self.documents:
|
|
52
|
-
for term in set(doc.lower().split()):
|
|
53
|
-
freqs[term] += 1
|
|
54
|
-
return freqs
|
|
55
|
-
|
|
56
|
-
def _calc_idf(self) -> Dict[str, float]:
|
|
57
|
-
idf = {}
|
|
58
|
-
n = len(self.documents)
|
|
59
|
-
for term, df in self.doc_freqs.items():
|
|
60
|
-
idf[term] = math.log((n - df + 0.5) / (df + 0.5) + 1)
|
|
61
|
-
return idf
|
|
62
|
-
|
|
63
|
-
def score(self, query: str, doc_idx: int) -> float:
|
|
64
|
-
score = 0.0
|
|
65
|
-
doc = self.documents[doc_idx].lower()
|
|
66
|
-
doc_terms = doc.split()
|
|
67
|
-
term_freqs = defaultdict(int)
|
|
68
|
-
for term in doc_terms:
|
|
69
|
-
term_freqs[term] += 1
|
|
70
|
-
|
|
71
|
-
for term in query.lower().split():
|
|
72
|
-
if term not in self.idf:
|
|
73
|
-
continue
|
|
74
|
-
tf = term_freqs[term]
|
|
75
|
-
idf = self.idf[term]
|
|
76
|
-
dl = self.doc_len[doc_idx]
|
|
77
|
-
score += idf * (tf * (self.k1 + 1)) / (tf + self.k1 * (1 - self.b + self.b * dl / self.avgdl))
|
|
78
|
-
|
|
79
|
-
return score
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
def detect_domain(query: str) -> str:
|
|
83
|
-
"""Auto-detect domain based on query keywords"""
|
|
84
|
-
query_lower = query.lower()
|
|
85
|
-
scores = {}
|
|
86
|
-
|
|
87
|
-
for domain, keywords in DOMAIN_KEYWORDS.items():
|
|
88
|
-
score = sum(1 for kw in keywords if kw in query_lower)
|
|
89
|
-
if score > 0:
|
|
90
|
-
scores[domain] = score
|
|
91
|
-
|
|
92
|
-
if scores:
|
|
93
|
-
return max(scores, key=scores.get)
|
|
94
|
-
return 'templates' # Default to templates
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def load_data(domain: str) -> List[Dict[str, Any]]:
|
|
98
|
-
"""Load CSV data for a domain"""
|
|
99
|
-
data_dir = Path(__file__).parent.parent / 'data'
|
|
100
|
-
csv_file = data_dir / DOMAINS[domain]
|
|
101
|
-
|
|
102
|
-
if not csv_file.exists():
|
|
103
|
-
return []
|
|
104
|
-
|
|
105
|
-
with open(csv_file, 'r', encoding='utf-8') as f:
|
|
106
|
-
reader = csv.DictReader(f)
|
|
107
|
-
return list(reader)
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def search(
|
|
111
|
-
query: str,
|
|
112
|
-
domain: str = 'auto',
|
|
113
|
-
max_results: int = 5
|
|
114
|
-
) -> List[Dict[str, Any]]:
|
|
115
|
-
"""
|
|
116
|
-
Search knowledge base using BM25 + regex
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
query: Search query
|
|
120
|
-
domain: Domain to search or 'auto' for auto-detection
|
|
121
|
-
max_results: Maximum results to return
|
|
122
|
-
|
|
123
|
-
Returns:
|
|
124
|
-
List of matching records
|
|
125
|
-
"""
|
|
126
|
-
# Auto-detect domain if needed
|
|
127
|
-
if domain == 'auto':
|
|
128
|
-
domain = detect_domain(query)
|
|
129
|
-
|
|
130
|
-
# Load data
|
|
131
|
-
data = load_data(domain)
|
|
132
|
-
if not data:
|
|
133
|
-
return []
|
|
134
|
-
|
|
135
|
-
# Create searchable text for each record
|
|
136
|
-
def record_to_text(record: Dict) -> str:
|
|
137
|
-
return ' '.join(str(v) for v in record.values())
|
|
138
|
-
|
|
139
|
-
documents = [record_to_text(r) for r in data]
|
|
140
|
-
|
|
141
|
-
# BM25 scoring
|
|
142
|
-
bm25 = BM25(documents)
|
|
143
|
-
scores = [(i, bm25.score(query, i)) for i in range(len(documents))]
|
|
144
|
-
|
|
145
|
-
# Regex boost for exact matches
|
|
146
|
-
try:
|
|
147
|
-
query_pattern = re.compile(re.escape(query), re.IGNORECASE)
|
|
148
|
-
for i, (idx, score) in enumerate(scores):
|
|
149
|
-
if query_pattern.search(documents[idx]):
|
|
150
|
-
scores[i] = (idx, score * 2) # Boost exact matches
|
|
151
|
-
except re.error:
|
|
152
|
-
pass # Skip regex boost if pattern is invalid
|
|
153
|
-
|
|
154
|
-
# Sort by score and return top results
|
|
155
|
-
scores.sort(key=lambda x: x[1], reverse=True)
|
|
156
|
-
|
|
157
|
-
results = []
|
|
158
|
-
for idx, score in scores[:max_results]:
|
|
159
|
-
if score > 0:
|
|
160
|
-
result = data[idx].copy()
|
|
161
|
-
result['_score'] = round(score, 3)
|
|
162
|
-
result['_domain'] = domain
|
|
163
|
-
results.append(result)
|
|
164
|
-
|
|
165
|
-
return results
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Stacks Agent Skill - Search Engine
|
|
4
|
-
BM25 + regex hybrid search across knowledge databases
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import argparse
|
|
8
|
-
import sys
|
|
9
|
-
from pathlib import Path
|
|
10
|
-
|
|
11
|
-
# Add parent directory to path for imports
|
|
12
|
-
sys.path.insert(0, str(Path(__file__).parent))
|
|
13
|
-
|
|
14
|
-
from core import search, DOMAINS
|
|
15
|
-
|
|
16
|
-
def main():
|
|
17
|
-
parser = argparse.ArgumentParser(
|
|
18
|
-
description='Search Stacks Agent knowledge base'
|
|
19
|
-
)
|
|
20
|
-
parser.add_argument('query', help='Search query')
|
|
21
|
-
parser.add_argument(
|
|
22
|
-
'--domain', '-d',
|
|
23
|
-
choices=list(DOMAINS.keys()) + ['auto'],
|
|
24
|
-
default='auto',
|
|
25
|
-
help='Domain to search (default: auto-detect)'
|
|
26
|
-
)
|
|
27
|
-
parser.add_argument(
|
|
28
|
-
'--max-results', '-n',
|
|
29
|
-
type=int,
|
|
30
|
-
default=5,
|
|
31
|
-
help='Maximum results to return (default: 5)'
|
|
32
|
-
)
|
|
33
|
-
parser.add_argument(
|
|
34
|
-
'--format', '-f',
|
|
35
|
-
choices=['text', 'json'],
|
|
36
|
-
default='text',
|
|
37
|
-
help='Output format (default: text)'
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
args = parser.parse_args()
|
|
41
|
-
|
|
42
|
-
results = search(
|
|
43
|
-
query=args.query,
|
|
44
|
-
domain=args.domain,
|
|
45
|
-
max_results=args.max_results
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
if args.format == 'json':
|
|
49
|
-
import json
|
|
50
|
-
print(json.dumps(results, indent=2))
|
|
51
|
-
else:
|
|
52
|
-
if not results:
|
|
53
|
-
print(f"No results found for: {args.query}")
|
|
54
|
-
else:
|
|
55
|
-
for i, result in enumerate(results, 1):
|
|
56
|
-
print(f"\n--- Result {i} (Score: {result.get('_score', 0)}) ---")
|
|
57
|
-
for key, value in result.items():
|
|
58
|
-
if not key.startswith('_'):
|
|
59
|
-
print(f"{key}: {value}")
|
|
60
|
-
|
|
61
|
-
if __name__ == '__main__':
|
|
62
|
-
main()
|