All files / src/api/read-only call-read-only-function.ts

61.53% Statements 16/26
11.11% Branches 1/9
100% Functions 2/2
64% Lines 16/25

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75  9x 9x 9x   9x                           9x                   1x   1x 1x                     1x   1x 1x       1x   1x     1x             1x                   1x    
import type { ClarityValue } from 'micro-stacks/clarity';
import { cvToHex } from 'micro-stacks/clarity';
import { StacksMainnet, StacksTestnet } from 'micro-stacks/network';
import { fetchPrivate } from 'micro-stacks/common';
 
import { isMainnetAddress, parseReadOnlyResponse } from './utils';
 
import type { ReadOnlyFunctionOptions, ReadOnlyFunctionResponse } from './types';
 
/**
 * Calls a read only function from a contract interface
 *
 * @param  {ReadOnlyFunctionOptions} options - the options object
 *
 * Returns an object with a status bool (okay) and a result string that is a serialized clarity value in hex format.
 *
 * @see https://docs.micro-stacks.dev/modules/core/api/smart-contracts#fetchreadonlyfunction
 * @return {ClarityValue}
 */
export async function callReadOnlyFunction<T extends ClarityValue>(
  options: ReadOnlyFunctionOptions
): Promise<T> {
  const {
    contractName,
    contractAddress,
    functionName,
    functionArgs,
    senderAddress = contractAddress,
    tip,
  } = options;
 
  let network = options.network;
  Iif (!options.network) {
    try {
      network = isMainnetAddress(contractAddress) ? new StacksMainnet() : new StacksTestnet();
    } catch (e) {
      console.error(e);
      throw new Error(
        '[micro-stacks] callReadOnlyFunction -> Incorrect Stacks addressed passed to contractAddress'
      );
    }
  }
 
  Iif (!network) throw Error('[micro-stacks] callReadOnlyFunction -> no network defined');
 
  let url = network.getReadOnlyFunctionCallApiUrl(contractAddress, contractName, functionName);
  Iif (tip) {
    url += `?tip=${tip}`;
  }
 
  const body = JSON.stringify({
    sender: senderAddress,
    arguments: functionArgs.map(arg => (typeof arg === 'string' ? arg : cvToHex(arg))),
  });
 
  const response = await fetchPrivate(url, {
    method: 'POST',
    body,
    headers: {
      'Content-Type': 'application/json',
    },
  });
  Iif (!response.ok) {
    let msg = '';
    try {
      msg = await response.text();
    } catch (error) {}
    throw new Error(
      `Error calling read-only function. Response ${response.status}: ${response.statusText}. Attempted to fetch ${url} and failed with the message: "${msg}"`
    );
  }
 
  return parseReadOnlyResponse((await response.json()) as ReadOnlyFunctionResponse) as T;
}