Skip to content

Instantly share code, notes, and snippets.

@zed-wong
Last active January 9, 2024 01:51
Show Gist options
  • Save zed-wong/436be65cff5da61c0aa0a0de8f0f18e3 to your computer and use it in GitHub Desktop.
Save zed-wong/436be65cff5da61c0aa0a0de8f0f18e3 to your computer and use it in GitHub Desktop.
mixin safe get user balance
import axios from "axios";
import { hashMembers } from "@mixin.dev/mixin-node-sdk";
export const mixinAsset = async (asset_id: string) => {
const result = await axios
.get(MIXIN_API_BASE_URL + `/network/assets/${asset_id}`);
return result.data ? result.data.data : {};
}
export const mixinSafeOutputs = async (members: string[], token: string, spent: boolean = false)=> {
let config = {
headers: {
Authorization: `Bearer ${token}`,
},
};
const result = await axios
.get(MIXIN_API_BASE_URL + `/safe/outputs?members=${hashMembers(members)}&threshold=1&offset=0&limit=1000&state=${spent?"spent":"unspent"}&order=ASC`, config);
return result.data ? result.data.data : {};
}
async function fetchTopAssetsCache() {
const topAssets = await mixinTopAssets();
// This is a svelte store, replace it with your implementation
let topCache = get(topAssetsCache)
topAssets.forEach(asset => {
topCache[asset.asset_id] = asset;
});
topAssetsCache.set(topCache)
return topCache
}
async function getAssetDetails(asset_id: string, topAssetsCache: any) {
if (topAssetsCache && topAssetsCache[asset_id]) {
return topAssetsCache[asset_id];
} else {
// If not in cache, fetch the asset details
return await mixinAsset(asset_id);
}
}
// Step 2: Group UTXOs by asset_id and sum the amounts
function groupAndSumUTXOs(outputs) {
const balances = outputs.reduce((acc, output) => {
const { asset_id, amount } = output;
if (!acc[asset_id]) {
acc[asset_id] = { balance: 0, asset_id };
}
acc[asset_id].balance += parseFloat(amount);
return acc;
}, {});
return balances;
}
async function calculateAndSortUSDBalances(balances, topAssetsCache) {
for (const asset_id in balances) {
const assetDetails = await getAssetDetails(asset_id, topAssetsCache);
balances[asset_id].usdBalance = balances[asset_id].balance * parseFloat(assetDetails.price_usd);
balances[asset_id].details = assetDetails;
}
// Sort the balances by USD balance
const sortedBalancesArray = Object.values(balances).sort((a, b) => b.usdBalance - a.usdBalance);
return sortedBalancesArray; // You can keep it as an array since it's already sorted
}
// Step 5: Calculate total USD balance
function calculateTotalUSDBalance(balances) {
return Object.values(balances).reduce((acc, { usdBalance }) => acc + usdBalance, 0);
}
// Step 6: Calculate total BTC balance
async function calculateTotalBTCBalance(totalUSDBalance, token: string) {
const btcDetails = await getAssetDetails(BTC_UUID, get(topAssetsCache))
return totalUSDBalance / parseFloat(btcDetails.price_usd);
}
async function getUserBalances(user_id: string, token: string) {
const topAssetsCache = await fetchTopAssetsCache();
const outputs = await mixinSafeOutputs([user_id], token)
let balances = groupAndSumUTXOs(outputs);
balances = await calculateAndSortUSDBalances(balances, topAssetsCache);
const totalUSDBalance = calculateTotalUSDBalance(balances);
const totalBTCBalance = await calculateTotalBTCBalance(totalUSDBalance, token);
userAssets.set({balances, totalUSDBalance, totalBTCBalance})
return { balances, totalUSDBalance, totalBTCBalance}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment