Skip to main content

Public Functions

Public functions modify blockchain state and require a signed transaction. Users must pay gas fees (STX) to execute these functions.

set-risk-profile

Save or update user’s risk tolerance level on-chain.
contracts/staxiq-user-profile.clar:70
(define-public (set-risk-profile (risk-level uint))
  (begin
    (asserts! (is-valid-risk-level risk-level) ERR-INVALID-RISK)
    ;; ...
    (ok risk-level)
  )
)
risk-level
uint
required
User’s risk tolerance: u1 (Conservative), u2 (Balanced), or u3 (Aggressive)
Returns
response

Behavior

  • If profile exists: Updates risk-level and updated-at, preserves created-at and strategy-count
  • If profile doesn’t exist: Creates new profile with created-at set to current block height
  • Validates risk level is 1, 2, or 3 before writing
  • Transaction must be signed by the user (tx-sender)

Example Usage

import { makeContractCall, uintCV, AnchorMode } from '@stacks/transactions';

const txOptions = {
  contractAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  contractName: 'staxiq-user-profile',
  functionName: 'set-risk-profile',
  functionArgs: [uintCV(2)], // Set to Balanced
  network: STACKS_TESTNET,
  anchorMode: AnchorMode.Any,
};

const transaction = await makeContractCall(txOptions);
const result = await broadcastTransaction({ transaction, network });

save-strategy

Anchor an AI-generated strategy recommendation to the blockchain.
contracts/staxiq-user-profile.clar:99
(define-public (save-strategy
  (strategy-hash (string-ascii 64))
  (protocol (string-ascii 32))
)
  (let (
    (profile (map-get? user-profiles tx-sender))
    (current-count (default-to u0 (map-get? user-strategy-count tx-sender)))
    (new-count (+ current-count u1))
  )
    (asserts! (is-some profile) ERR-NOT-FOUND)
    ;; ...
    (ok new-count)
  )
)
strategy-hash
string-ascii
required
SHA-256 hash (hex string) of the complete strategy details. Should be 64 characters.
protocol
string-ascii
required
Name of the target DeFi protocol (e.g., “ALEX”, “Velar”, “StackSwap”). Max 32 characters.
Returns
response

Behavior

  • Requires user to have an existing risk profile (call set-risk-profile first)
  • Increments strategy counter and assigns new strategy ID
  • Stores strategy with user’s current risk level
  • Updates profile’s strategy-count and updated-at fields
  • Each strategy is permanently stored and cannot be modified

Example Usage

import { makeContractCall, stringAsciiCV, AnchorMode } from '@stacks/transactions';
import crypto from 'crypto';

// Hash the strategy
const strategy = { protocol: 'ALEX', actions: [...], apy: 12.5 };
const hash = crypto
  .createHash('sha256')
  .update(JSON.stringify(strategy))
  .digest('hex');

const txOptions = {
  contractAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  contractName: 'staxiq-user-profile',
  functionName: 'save-strategy',
  functionArgs: [
    stringAsciiCV(hash.slice(0, 64)),
    stringAsciiCV('ALEX')
  ],
  network: STACKS_TESTNET,
  anchorMode: AnchorMode.Any,
};

const transaction = await makeContractCall(txOptions);
const result = await broadcastTransaction({ transaction, network });

Read-Only Functions

Read-only functions query blockchain data without modifying state. They are free to call (no gas fees) and return data instantly.

get-user-profile

Retrieve complete profile information for a user.
contracts/staxiq-user-profile.clar:142
(define-read-only (get-user-profile (user principal))
  (match (map-get? user-profiles user)
    profile (ok profile)
    ERR-NOT-FOUND
  )
)
user
principal
required
Stacks wallet address (e.g., ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ)
Returns
response

Example Usage

import { fetchCallReadOnlyFunction, cvToJSON } from '@stacks/blockchain-api-client';
import { principalCV } from '@stacks/transactions';

const result = await fetchCallReadOnlyFunction({
  contractAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  contractName: 'staxiq-user-profile',
  functionName: 'get-user-profile',
  functionArgs: [principalCV('ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ')],
  senderAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  network: STACKS_TESTNET
});

const profile = cvToJSON(result);
console.log(profile);
// { risk_level: 2, created_at: 150000, updated_at: 150500, strategy_count: 3 }

get-strategy

Retrieve a specific strategy from user’s history.
contracts/staxiq-user-profile.clar:150
(define-read-only (get-strategy
  (user principal)
  (strategy-id uint)
)
  (match (map-get? strategy-history { user: user, strategy-id: strategy-id })
    strategy (ok strategy)
    ERR-NOT-FOUND
  )
)
user
principal
required
Stacks wallet address of the user
strategy-id
uint
required
Strategy ID number (starting from 1)
Returns
response

Example Usage

import { fetchCallReadOnlyFunction, cvToJSON } from '@stacks/blockchain-api-client';
import { principalCV, uintCV } from '@stacks/transactions';

const result = await fetchCallReadOnlyFunction({
  contractAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  contractName: 'staxiq-user-profile',
  functionName: 'get-strategy',
  functionArgs: [
    principalCV(userAddress),
    uintCV(1) // Get first strategy
  ],
  senderAddress: userAddress,
  network: STACKS_TESTNET
});

const strategy = cvToJSON(result);
console.log(strategy);
// { risk_level: 2, strategy_hash: "a1b2c3...", protocol: "ALEX", timestamp: 150000 }

get-strategy-count

Get total number of strategies saved by a user.
contracts/staxiq-user-profile.clar:161
(define-read-only (get-strategy-count (user principal))
  (ok (default-to u0 (map-get? user-strategy-count user)))
)
user
principal
required
Stacks wallet address
Returns
response
ok
uint
Total number of strategies (returns u0 if user has no strategies)

Example Usage

import { getStrategyCount } from './services/contractService';

const count = await getStrategyCount(userAddress);
console.log(`User has ${count} strategies`);

has-profile

Check if a user has created a risk profile.
contracts/staxiq-user-profile.clar:166
(define-read-only (has-profile (user principal))
  (is-some (map-get? user-profiles user))
)
user
principal
required
Stacks wallet address
Returns
bool
true if user has a profile, false otherwise

Example Usage

import { checkHasProfile } from './services/contractService';

const hasProfile = await checkHasProfile(userAddress);
if (!hasProfile) {
  console.log('Please set your risk profile first');
}

get-risk-label

Get user’s risk level as a human-readable string.
contracts/staxiq-user-profile.clar:171
(define-read-only (get-risk-label (user principal))
  (match (map-get? user-profiles user)
    profile (ok
      (if (is-eq (get risk-level profile) RISK-CONSERVATIVE)
        "Conservative"
        (if (is-eq (get risk-level profile) RISK-BALANCED)
          "Balanced"
          "Aggressive"
        )
      )
    )
    ERR-NOT-FOUND
  )
)
user
principal
required
Stacks wallet address
Returns
response

Example Usage

import { fetchCallReadOnlyFunction, cvToJSON } from '@stacks/blockchain-api-client';
import { principalCV } from '@stacks/transactions';

const result = await fetchCallReadOnlyFunction({
  contractAddress: 'ST9ZZEP9M6VZ9YJA0P69H313CRPV0HQ1ZNPVS8NZ',
  contractName: 'staxiq-user-profile',
  functionName: 'get-risk-label',
  functionArgs: [principalCV(userAddress)],
  senderAddress: userAddress,
  network: STACKS_TESTNET
});

const label = cvToJSON(result);
console.log('Risk profile:', label); // "Balanced"

Function Summary

Public Functions (Require Transaction)

FunctionParametersReturnsDescription
set-risk-profilerisk-level: uint(ok uint)Set/update user risk tolerance (1, 2, or 3)
save-strategystrategy-hash: string-ascii(64)
protocol: string-ascii(32)
(ok uint)Anchor AI strategy to blockchain, returns strategy ID

Read-Only Functions (Free)

FunctionParametersReturnsDescription
get-user-profileuser: principal(ok profile)Get complete user profile
get-strategyuser: principal
strategy-id: uint
(ok strategy)Get specific strategy details
get-strategy-countuser: principal(ok uint)Get total strategy count
has-profileuser: principalboolCheck if user has profile
get-risk-labeluser: principal(ok string)Get risk level as readable string

Next Steps

Integration Guide

Learn how to call these functions from your app

Testing

Test contract functions locally

Build docs developers (and LLMs) love