From 65142c67c6aa7fb36eac58dfab8a379867f00a13 Mon Sep 17 00:00:00 2001 From: Joey Date: Sun, 5 Jan 2025 00:40:02 +0100 Subject: [PATCH] upd: reworked runes portfolio to also show 24h change as well as the total value sum --- .../src/actions/runes/portfolio.ts | 28 +++++++++++++--- .../src/actions/runes/transfer.ts | 32 ++++--------------- packages/plugin-ordinals/src/types/index.ts | 11 +++++++ packages/plugin-ordinals/src/utils/api.ts | 9 +++--- packages/plugin-ordinals/src/utils/index.ts | 29 +++++++++++++++++ 5 files changed, 74 insertions(+), 35 deletions(-) diff --git a/packages/plugin-ordinals/src/actions/runes/portfolio.ts b/packages/plugin-ordinals/src/actions/runes/portfolio.ts index c136f28fcc..9cdd250bca 100644 --- a/packages/plugin-ordinals/src/actions/runes/portfolio.ts +++ b/packages/plugin-ordinals/src/actions/runes/portfolio.ts @@ -14,7 +14,9 @@ import { WalletProvider, walletProvider } from "../../providers/wallet"; import API from "../../utils/api"; import { z } from "zod"; import { balanceTemplate } from "../../templates"; -import { handleError } from "../../utils"; +import { dollarFormatter, handleError } from "../../utils"; +import { formatUnits } from "viem"; +import BigNumber from "bignumber.js"; export const addressSchema = z.object({ address: z.string(), @@ -62,13 +64,29 @@ export default { ? addresses.taprootAddress : derivedAddress; - const ordiscan = new API(runtime.getSetting("ORDISCAN_API_KEY")); - const portfolio = await ordiscan.getRunesPortfolio(taprootAddress); + const api = new API(); - const balances = portfolio?.results; + const balances = await api.getRunesPortfolio(taprootAddress); + let balanceText = ""; + for (const balance of balances) { + const formattedBalance = formatUnits( + BigInt(balance.amount), + balance.divisibility + ); + + const totalValue = new BigNumber(balance.currentPrice) + .multipliedBy(new BigNumber(formattedBalance)) + .toNumber(); + + const pastDayChange = + balance.priceChangePercentage24h.toFixed(2); + const pastDayPositive = Number(pastDayChange) > 0; + + balanceText += `${balance.symbol} ${balance?.runeName}: ${formattedBalance} [Value: ${dollarFormatter.format(totalValue)}] (${pastDayPositive ? "+" : ""}${pastDayChange}%)\n`; + } callback({ - text: `Runes portfolio for address ${taprootAddress}:\n${balances?.map((item, idx) => `${idx + 1}: ${item?.rune?.spaced_name} - ${item.balance}\n`)}`, + text: `Runes portfolio for address ${taprootAddress}:\n\n${balanceText}`, }); return true; diff --git a/packages/plugin-ordinals/src/actions/runes/transfer.ts b/packages/plugin-ordinals/src/actions/runes/transfer.ts index 6a9af25e87..3069ab0048 100644 --- a/packages/plugin-ordinals/src/actions/runes/transfer.ts +++ b/packages/plugin-ordinals/src/actions/runes/transfer.ts @@ -29,7 +29,11 @@ import { Range, Etching, } from "runelib"; -import { getRequiredRuneUtxos, handleError } from "../../utils"; +import { + estimateTransactionSize, + getRequiredRuneUtxos, + handleError, +} from "../../utils"; export const transferSchema = z.object({ rune: z.string(), @@ -208,30 +212,6 @@ export default { psbt.addOutputAddress(addresses.taprootAddress, BigInt(546)); } - const estimateTransactionSize = ( - taprootInputCount: number, - p2shP2wpkhInputCount: number, - outputCounts: { - p2wpkh: number; - taproot: number; - opReturn: number; - } - ) => { - const baseSize = 10; - const taprootInputSize = 57 * taprootInputCount; - const p2shP2wpkhInputSize = 91 * p2shP2wpkhInputCount; - const outputSize = - 31 * outputCounts.p2wpkh + - 43 * outputCounts.taproot + - 43 * outputCounts.opReturn; - return ( - baseSize + - taprootInputSize + - p2shP2wpkhInputSize + - outputSize - ); - }; - const estimatedSize = estimateTransactionSize( toUseRuneUtxos.utxos.length, // The rune utxo's that we are using 1, // One BTC UTXO @@ -241,7 +221,7 @@ export default { opReturn: 1, // Mintstone } ); - + const feerates = await wallet.getFeeRates(); if (!feerates?.fastestFee) { diff --git a/packages/plugin-ordinals/src/types/index.ts b/packages/plugin-ordinals/src/types/index.ts index 0ba3d63dc6..334da960df 100644 --- a/packages/plugin-ordinals/src/types/index.ts +++ b/packages/plugin-ordinals/src/types/index.ts @@ -6,3 +6,14 @@ export interface IAccount { schnorrPublicKey?: any; publicKey?: any; } + +export interface IBalance { + amount: number; + divisibility: number; + symbol: string; + runeName: string; + inscriptionId: string; + id: `${string}:${string}`; + priceChangePercentage24h: number; + currentPrice: number; +} diff --git a/packages/plugin-ordinals/src/utils/api.ts b/packages/plugin-ordinals/src/utils/api.ts index be537266a0..5092950e13 100644 --- a/packages/plugin-ordinals/src/utils/api.ts +++ b/packages/plugin-ordinals/src/utils/api.ts @@ -1,4 +1,5 @@ import { elizaLogger } from "@elizaos/core"; +import { IBalance } from "../types"; const ORDISCAN_BASE_URL = "https://api.ordiscan.com/v1"; const HIRO_BASE_URL = "https://api.hiro.so"; @@ -32,9 +33,9 @@ class API { this.ordiscanApiKey = ordiscanApiKey; } - async getRunesPortfolio(address: string) { - return fetcher( - `${HIRO_BASE_URL}/runes/v1/addresses/${address}/balances?offset=0&limit=20` + async getRunesPortfolio(address: string): Promise { + return await fetcher( + `https://api-3.xverse.app/v2/address/${address}/rune-balance?includeUnconfirmed=true` ); } @@ -48,7 +49,7 @@ class API { ); } - async getRareSats(address: string){ + async getRareSats(address: string) { // return fetcher( // `https://api-3.xverse.app/v1/market/address/${address}/rune/${runeName}/utxos` // ); diff --git a/packages/plugin-ordinals/src/utils/index.ts b/packages/plugin-ordinals/src/utils/index.ts index 91c2e5ac15..13b770c845 100644 --- a/packages/plugin-ordinals/src/utils/index.ts +++ b/packages/plugin-ordinals/src/utils/index.ts @@ -54,3 +54,32 @@ export const getRequiredRuneUtxos = ( insufficientFunds: accumulated < amountNeeded, }; }; + +export const estimateTransactionSize = ( + taprootInputCount: number, + p2shP2wpkhInputCount: number, + outputCounts: { + p2wpkh: number; + taproot: number; + opReturn: number; + } +) => { + const baseSize = 10; + const taprootInputSize = 57 * taprootInputCount; + const p2shP2wpkhInputSize = 91 * p2shP2wpkhInputCount; + const outputSize = + 31 * outputCounts.p2wpkh + + 43 * outputCounts.taproot + + 43 * outputCounts.opReturn; + return ( + baseSize + + taprootInputSize + + p2shP2wpkhInputSize + + outputSize + ); +}; + +export const dollarFormatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', +});