Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion projects/helper/coreAssets.json
Original file line number Diff line number Diff line change
Expand Up @@ -1602,7 +1602,8 @@
"aeUSDC": "SP3Y2ZSH8P7D50B0VBTSX11S7XSG24M1VB9YFQA4K.token-aeusdc",
"aBTC": "SP3K8BC0PPEVCV7NZ6QSRWPQ2JE9E5B6N3PA0KBR9.token-abtc::bridged-btc",
"USDCx": "SP120SBRBQJ00MCWS7TM5R8WJNTTKD5K0HFRC2CNE.usdcx",
"USDh": "SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1"
"USDh": "SPN5AKG35QZSK2M8GAMR4AFX45659RJHDW353HSG.usdh-token-v1",
"hBTC": "SP1S1HSFH0SQQGWKB69EYFNY0B1MHRMGXR3J1FH4D.token-hbtc"
},
"neon_evm": {
"WNEON": "0xb14760c064a1b9eaf9ec5a8a421971e40a51b59c"
Expand Down
24 changes: 24 additions & 0 deletions projects/hermetica-hbtc/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
const ADDRESSES = require('../helper/coreAssets.json')
const { makeReadOnlyContractCall } = require('../hermetica/stacks-call')

const hBTCContract = ADDRESSES.stacks.hBTC;
const hBTCStateContract = 'SP1S1HSFH0SQQGWKB69EYFNY0B1MHRMGXR3J1FH4D.state-hbtc-v1';

module.exports = {
methodology: 'Counts the number of hBTC tokens on Stacks.',
timetravel: false,
stacks: {
tvl: async () => {
const [microhBTCSupplyStacks, microSharePrice] = await Promise.all([
makeReadOnlyContractCall({ contract: hBTCContract, function_name: 'get-total-supply' }),
makeReadOnlyContractCall({ contract: hBTCStateContract, function_name: 'get-share-price' })
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please share the bitcoin addresses where hBTC collateral is held? The docs mention using the sBTC bridge, is there a way to track the btc deposited for hBTC specifically?

Copy link
Copy Markdown
Contributor Author

@anch09 anch09 Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi, sure thing. sBTC is a 1:1 BTC backed token.

You can see the docs here.
The amount of sBTC circulating on-chain here.
The multisig address on Bitcoin here.

]);

const sharePrice = microSharePrice / (10 ** 8);
const hBTCSupplyStacks = microhBTCSupplyStacks / (10 ** 8);

return { bitcoin: hBTCSupplyStacks * sharePrice };
}
},
misrepresentedTokens: false
}
55 changes: 13 additions & 42 deletions projects/hermetica/index.js
Original file line number Diff line number Diff line change
@@ -1,64 +1,35 @@
const ADDRESSES = require('../helper/coreAssets.json')
const { get, post } = require('../helper/http')
const { get } = require('../helper/http')
const { makeReadOnlyContractCall } = require('./stacks-call')

const USDhContract = ADDRESSES.stacks.USDh;

function parseClarityInt(hexString) {
// Remove "0x" prefix
let hex = hexString.startsWith("0x") ? hexString.slice(2) : hexString;

// Skip the first two bytes (Clarity type and metadata)
let numberHex = hex.slice(4); // Remove first 2 bytes (4 hex characters)

// Convert hex to BigInt
let bigIntValue = BigInt("0x" + numberHex);

// Handle two’s complement for negative numbers
if (bigIntValue > BigInt("0x7ffffffffffffffffffffffffffffffff")) {
bigIntValue = bigIntValue - BigInt("0x100000000000000000000000000000000");
}

return bigIntValue.toString(); // Return as a readable decimal string
}

module.exports = {
methodology: 'Counts the number of USDh tokens on Stacks and Bitcoin (Runes).',
timetravel: false,
bitcoin: {
tvl: async () => {
const { result: totalSupply } = await get('https://app.hermetica.fi/api/v1/usdh/supply');

const [contract_address, contract_name] = USDhContract.split('.');
const supplyResponse = await post(`https://api.mainnet.hiro.so/v2/contracts/call-read/${contract_address}/${contract_name}/get-total-supply`,
{
sender: contract_address,
arguments: []
}
);
const uUSDhSupplyStacks = Number(parseClarityInt(supplyResponse.result));

const cleanUsdhSupply = totalSupply.replace(/[^\d.]/g, '');
const totalUsdhSupply = Number(cleanUsdhSupply);
const totaluUSDhSupply = totalUsdhSupply * (10 ** 8);
const [supply, uUSDhSupplyStacks] = await Promise.all([
get('https://app.hermetica.fi/api/v1/usdh/supply'),
makeReadOnlyContractCall({ contract: USDhContract, function_name: 'get-total-supply' })
]);

const cleanUsdhSupply = supply.result.replace(/[^\d.]/g, '');
const totaluUSDhSupply = Number(cleanUsdhSupply) * (10 ** 8);
const sUSDhSupplyRunes = totaluUSDhSupply - uUSDhSupplyStacks;

return { 'hermetica-usdh': sUSDhSupplyRunes / (10 ** 8) }
}
},
stacks: {
tvl: async () => {
const [contract_address, contract_name] = USDhContract.split('.');
const supplyResponse = await post(`https://api.mainnet.hiro.so/v2/contracts/call-read/${contract_address}/${contract_name}/get-total-supply`,
{
sender: contract_address,
arguments: []
}
);
const supplyOnStacksuUsdh = Number(parseClarityInt(supplyResponse.result));
const supplyOnStacksuUsdh = await makeReadOnlyContractCall({
contract: USDhContract,
function_name: 'get-total-supply'
});

return { 'hermetica-usdh': supplyOnStacksuUsdh / (10 ** 8) }
}
},
misrepresentedTokens: true
}
}
22 changes: 22 additions & 0 deletions projects/hermetica/stacks-call.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { post } = require('../helper/http')

function parseClarityInt(hexString) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of using this new function, could you use the existing call helper, I tested it here and got the same output

Copy link
Copy Markdown
Contributor Author

@anch09 anch09 Mar 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi,
I didn't use the call helper because when running the test it was throwing me Error loading module: Error: Cannot find module '@stacks/transactions' with MODULE_NOT_FOUND. And even after running npm install, seems that the module is not in the package.json file

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why after the changes the bot doesn't display the TVL comments?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hello, Im not sure why it wasnt working for you, but I tested your changes locally and it looked good to me (except the .value for microSharePrice)

let hex = hexString.startsWith("0x") ? hexString.slice(2) : hexString;
let numberHex = hex.slice(4);
let bigIntValue = BigInt("0x" + numberHex);
if (bigIntValue > BigInt("0x7ffffffffffffffffffffffffffffffff")) {
bigIntValue = bigIntValue - BigInt("0x100000000000000000000000000000000");
}
return bigIntValue.toString();
}

async function makeReadOnlyContractCall({ contract, function_name }) {
const [contract_address, contract_name] = contract.split('.');
const response = await post(
`https://api.mainnet.hiro.so/v2/contracts/call-read/${contract_address}/${contract_name}/${function_name}`,
{ sender: contract_address, arguments: [] }
);
return Number(parseClarityInt(response.result));
}

module.exports = { makeReadOnlyContractCall }
Loading