diff --git a/assets/svg/icon_token_fire.svg b/assets/svg/icon_token_fire.svg
new file mode 100644
index 0000000000..07e0b707b9
--- /dev/null
+++ b/assets/svg/icon_token_fire.svg
@@ -0,0 +1,22 @@
+
diff --git a/lib/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart b/lib/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart
index 178459afdb..257b4cca02 100644
--- a/lib/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart
+++ b/lib/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart
@@ -105,6 +105,12 @@ Future tradeCommunityTokenService(
);
}
+@riverpod
+Future bondingCurveAddress(Ref ref) async {
+ final repository = await ref.watch(tradeCommunityTokenRepositoryProvider.future);
+ return repository.fetchBondingCurveAddress();
+}
+
@riverpod
Future> supportedSwapTokens(Ref ref) async {
final api = await ref.watch(tradeCommunityTokenApiProvider.future);
diff --git a/lib/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart b/lib/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart
index a2d573d3be..d109646f0d 100644
--- a/lib/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart
+++ b/lib/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart
@@ -10,6 +10,12 @@ import 'package:ion/app/utils/num.dart';
import 'package:ion/generated/assets.gen.dart';
import 'package:ion_token_analytics/ion_token_analytics.dart';
+enum RankBadgeType {
+ regular,
+ burning,
+ bondingCurve,
+}
+
class BondingCurveHolderTile extends StatelessWidget {
const BondingCurveHolderTile({
required this.holder,
@@ -25,7 +31,32 @@ class BondingCurveHolderTile extends StatelessWidget {
amountText: formatAmountCompactFromRaw(holder.position.amount),
displayName: context.i18n.tokenized_community_bonding_curve,
supplyShare: holder.position.supplyShare,
- avatarUrl: Assets.svg.iconBondingCurveAvatar,
+ avatarUrl: holder.position.holder?.avatar,
+ badgeType: RankBadgeType.bondingCurve,
+ );
+ }
+}
+
+class BurningHolderTile extends StatelessWidget {
+ const BurningHolderTile({
+ required this.holder,
+ super.key,
+ });
+
+ final TopHolder holder;
+
+ @override
+ Widget build(BuildContext context) {
+ final holderAddress = holder.position.holder?.addresses?.ionConnect ?? '';
+
+ return HolderTile(
+ rank: holder.position.rank,
+ amountText: formatAmountCompactFromRaw(holder.position.amount),
+ displayName: holder.position.holder?.display ?? context.i18n.tokenized_community_burned,
+ supplyShare: holder.position.supplyShare,
+ avatarUrl: holder.position.holder?.avatar,
+ badgeType: RankBadgeType.burning,
+ address: holderAddress,
);
}
}
@@ -77,6 +108,8 @@ class HolderTile extends StatelessWidget {
this.avatarUrl,
this.holderAddress,
this.isXUser = false,
+ this.badgeType = RankBadgeType.regular,
+ this.address,
super.key,
});
@@ -90,6 +123,8 @@ class HolderTile extends StatelessWidget {
final String? avatarUrl;
final String? holderAddress;
final bool isXUser;
+ final RankBadgeType badgeType;
+ final String? address;
@override
Widget build(BuildContext context) {
@@ -111,7 +146,7 @@ class HolderTile extends StatelessWidget {
Expanded(
child: Row(
children: [
- _RankBadge(rank: rank),
+ _RankBadge(rank: rank, type: badgeType),
SizedBox(width: 12.0.s),
HolderAvatar(
imageUrl: avatarUrl,
@@ -123,6 +158,7 @@ class HolderTile extends StatelessWidget {
child: _NameAndAmount(
name: displayName,
handle: username,
+ address: address,
isCreator: isCreator,
verified: verified,
amountText: amountText,
@@ -150,22 +186,30 @@ class HolderTile extends StatelessWidget {
}
}
-///
-/// rank 1 -> bonding curve
-/// rank 2 -> 1st medal badge
-/// rank 3 -> 2nd medal badge
-/// rank 4 -> 3rd medal badge
-/// rank n -> n-1 text badge
-///
class _RankBadge extends StatelessWidget {
- const _RankBadge({required this.rank});
+ const _RankBadge({
+ required this.rank,
+ required this.type,
+ });
final int rank;
+ final RankBadgeType type;
@override
Widget build(BuildContext context) {
final colors = context.theme.appColors;
- final isMedal = rank <= 4;
+
+ final child = switch (type) {
+ RankBadgeType.burning => Assets.svg.iconTokenFire.icon(),
+ RankBadgeType.bondingCurve => Assets.svg.iconMemeBondingcurve.icon(),
+ RankBadgeType.regular => rank <= 3
+ ? _MedalIcon(rank: rank)
+ : Text(
+ '$rank',
+ style: context.theme.appTextThemes.body.copyWith(color: colors.primaryAccent),
+ ),
+ };
+
return Container(
width: 30.0.s,
height: 30.0.s,
@@ -174,12 +218,7 @@ class _RankBadge extends StatelessWidget {
borderRadius: BorderRadius.circular(10.0.s),
),
alignment: Alignment.center,
- child: isMedal
- ? _MedalIcon(rank: rank)
- : Text(
- '${rank - 1}',
- style: context.theme.appTextThemes.body.copyWith(color: colors.primaryAccent),
- ),
+ child: child,
);
}
}
@@ -192,10 +231,9 @@ class _MedalIcon extends StatelessWidget {
@override
Widget build(BuildContext context) {
return switch (rank) {
- 1 => Assets.svg.iconMemeBondingcurve,
- 2 => Assets.svg.iconMeme1stplace,
- 3 => Assets.svg.iconMeme2ndtplace,
- 4 => Assets.svg.iconMeme3rdplace,
+ 1 => Assets.svg.iconMeme1stplace,
+ 2 => Assets.svg.iconMeme2ndtplace,
+ 3 => Assets.svg.iconMeme3rdplace,
_ => throw UnimplementedError(),
}
.icon();
@@ -205,15 +243,17 @@ class _MedalIcon extends StatelessWidget {
class _NameAndAmount extends StatelessWidget {
const _NameAndAmount({
required this.name,
- required this.handle,
required this.amountText,
required this.verified,
required this.isCreator,
+ this.handle,
+ this.address,
this.isXUser = true,
});
final String name;
final String? handle;
+ final String? address;
final String amountText;
final bool verified;
final bool isCreator;
@@ -256,7 +296,11 @@ class _NameAndAmount extends StatelessWidget {
],
),
Text(
- handle != null ? '$handle • $amountText' : amountText,
+ address != null
+ ? shortenAddress(address!)
+ : handle != null
+ ? '$handle • $amountText'
+ : amountText,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: texts.caption.copyWith(color: colors.quaternaryText),
diff --git a/lib/app/features/tokenized_communities/views/pages/holders/components/top_holders/top_holders.dart b/lib/app/features/tokenized_communities/views/pages/holders/components/top_holders/top_holders.dart
index d18148448f..46464fac4d 100644
--- a/lib/app/features/tokenized_communities/views/pages/holders/components/top_holders/top_holders.dart
+++ b/lib/app/features/tokenized_communities/views/pages/holders/components/top_holders/top_holders.dart
@@ -3,12 +3,14 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:ion/app/extensions/extensions.dart';
+import 'package:ion/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/components/top_holders/components/top_holders_empty.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/components/top_holders/components/top_holders_skeleton.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart';
import 'package:ion/app/router/app_routes.gr.dart';
import 'package:ion/generated/assets.gen.dart';
+import 'package:ion_token_analytics/ion_token_analytics.dart';
const int holdersCountLimit = 5;
@@ -141,6 +143,7 @@ class _TopHolderList extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final holdersAsync =
ref.watch(tokenTopHoldersProvider(externalAddress, limit: holdersCountLimit));
+ final boundingCurveAddress = ref.watch(bondingCurveAddressProvider).valueOrNull;
return holdersAsync.when(
data: (holders) {
if (holders.isEmpty) {
@@ -153,13 +156,18 @@ class _TopHolderList extends ConsumerWidget {
padding: EdgeInsets.zero,
itemCount: holders.length,
itemBuilder: (context, index) {
- if (index == 0) {
+ final holder = holders[index];
+
+ if (boundingCurveAddress != null && holder.isBoundingCurve(boundingCurveAddress)) {
return BondingCurveHolderTile(
- holder: holders[index],
+ holder: holder,
);
}
- final holder = holders[index];
+ if (holder.isBurning) {
+ return BurningHolderTile(holder: holder);
+ }
+
return TopHolderTile(holder: holder);
},
separatorBuilder: (context, index) => SizedBox(height: 4.0.s),
diff --git a/lib/app/features/tokenized_communities/views/pages/holders/pages/holders_page.dart b/lib/app/features/tokenized_communities/views/pages/holders/pages/holders_page.dart
index 161f8b94db..0642014587 100644
--- a/lib/app/features/tokenized_communities/views/pages/holders/pages/holders_page.dart
+++ b/lib/app/features/tokenized_communities/views/pages/holders/pages/holders_page.dart
@@ -8,6 +8,7 @@ import 'package:ion/app/components/scroll_view/load_more_builder.dart';
import 'package:ion/app/components/scroll_view/pull_to_refresh_builder.dart';
import 'package:ion/app/components/separated/separator.dart';
import 'package:ion/app/extensions/extensions.dart';
+import 'package:ion/app/features/tokenized_communities/providers/trade_infrastructure_providers.r.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/components/holder_tile.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/components/top_holders/components/top_holders_skeleton.dart';
import 'package:ion/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart';
@@ -28,7 +29,7 @@ class HoldersPage extends HookConsumerWidget {
final topHoldersProvider = tokenTopHoldersProvider(externalAddress, limit: 20);
final topHoldersAsync = ref.watch(topHoldersProvider);
final topHolders = topHoldersAsync.valueOrNull ?? const [];
-
+ final boundingCurveAddress = ref.watch(bondingCurveAddressProvider).valueOrNull;
return Scaffold(
appBar: NavigationAppBar.screen(
title: Text(context.i18n.holders, style: context.theme.appTextThemes.subtitle2),
@@ -53,22 +54,32 @@ class HoldersPage extends HookConsumerWidget {
itemBuilder: (context, index) {
final topPadding = index == 0 ? 12.s : 7.s;
final bottomPadding = 7.s;
+ final holder = topHolders[index];
- if (index == 0) {
+ if (boundingCurveAddress != null &&
+ holder.isBoundingCurve(boundingCurveAddress)) {
return _HoldersListPadding(
topPadding: topPadding,
bottomPadding: bottomPadding,
child: BondingCurveHolderTile(
- holder: topHolders[index],
+ holder: holder,
),
);
}
+ if (holder.isBurning) {
+ return _HoldersListPadding(
+ topPadding: topPadding,
+ bottomPadding: bottomPadding,
+ child: BurningHolderTile(holder: holder),
+ );
+ }
+
return _HoldersListPadding(
topPadding: topPadding,
bottomPadding: bottomPadding,
child: TopHolderTile(
- holder: topHolders[index],
+ holder: holder,
),
);
},
diff --git a/lib/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart b/lib/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart
index 3c9e32d9be..2ee6b3b10e 100644
--- a/lib/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart
+++ b/lib/app/features/tokenized_communities/views/pages/holders/providers/token_top_holders_provider.r.dart
@@ -223,21 +223,16 @@ class TokenTopHolders extends _$TokenTopHolders {
}
final rank = item.position.rank;
- final insertAt = (rank - 1).clamp(0, list.length);
- list.insert(insertAt, item);
- _normalizeRanks(list);
- }
-
- void _normalizeRanks(List list) {
- for (var i = 0; i < list.length; i++) {
- final desiredRank = i + 1;
- final current = list[i];
- if (current.position.rank != desiredRank) {
- list[i] = current.copyWith(
- position: current.position.copyWith(rank: desiredRank),
- );
- }
+ if (rank == 0) {
+ // Count existing rank 0 items to insert after them
+ final rankZeroCount = list.where((h) => h.position.rank == 0).length;
+ list.insert(rankZeroCount, item);
+ } else {
+ // Count rank 0 items, then insert after them using rank - 1
+ final rankZeroCount = list.where((h) => h.position.rank == 0).length;
+ final insertAt = (rankZeroCount + rank - 1).clamp(0, list.length);
+ list.insert(insertAt, item);
}
}
diff --git a/lib/l10n/app_ar.arb b/lib/l10n/app_ar.arb
index 0a2632f463..66ba61235e 100644
--- a/lib/l10n/app_ar.arb
+++ b/lib/l10n/app_ar.arb
@@ -934,6 +934,7 @@
"tokenized_community_comments_empty": "كن أول من ينضم إلى المحادثة",
"tokenized_community_comments_tab": "التعليقات",
"tokenized_community_holders_tab": "الحائزون",
+ "tokenized_community_burned": "محروق",
"token_comment_holders_only": "التعليقات متاحة فقط لحاملي الرموز.",
"tokenized_community_not_available_description": "إنشاء الرموز غير متاح للمنشورات التي تم إنشاؤها مسبقًا.",
"tokenized_community_not_available_title": "خطأ في المحتوى المرمز",
diff --git a/lib/l10n/app_bg.arb b/lib/l10n/app_bg.arb
index 3503613724..ab9b0e207f 100644
--- a/lib/l10n/app_bg.arb
+++ b/lib/l10n/app_bg.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Токенът на създателя е АКТИВЕН!",
"tokenized_community_creator_token_live_subtitle": "Поздравления, вашият токен на създателя вече е активен и достъпен за търговия от всички",
"tokenized_community_holders_tab": "Притежатели",
+ "tokenized_community_burned": "Изгорени",
"token_comment_holders_only": "Коментарите са достъпни само за притежатели на токени.",
"tokenized_community_not_available_description": "Създаването на токени не е налично за вече създадени публикации.",
"tokenized_community_not_available_title": "Грешка при токенизирано съдържание",
diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb
index fdae60d6a1..6d318cca94 100644
--- a/lib/l10n/app_de.arb
+++ b/lib/l10n/app_de.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Creator-Token ist LIVE!",
"tokenized_community_creator_token_live_subtitle": "Herzlichen Glückwunsch, Ihr Creator-Token ist jetzt live und für jeden handelbar",
"tokenized_community_holders_tab": "Inhaber",
+ "tokenized_community_burned": "Verbrannt",
"token_comment_holders_only": "Kommentare sind nur für Token-Inhaber verfügbar.",
"tokenized_community_not_available_description": "Die Tokenerstellung ist für zuvor erstellte Beiträge nicht verfügbar.",
"tokenized_community_not_available_title": "Fehler bei tokenisiertem Inhalt",
diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb
index f23ccfb21f..daa65f4699 100644
--- a/lib/l10n/app_en.arb
+++ b/lib/l10n/app_en.arb
@@ -918,6 +918,7 @@
"tokenized_community_comments_empty": "Be the first to join the conversation",
"tokenized_community_comments_tab": "Comments",
"tokenized_community_holders_tab": "Holders",
+ "tokenized_community_burned": "Burned",
"token_comment_holders_only": "Comments are available only to token holders",
"tokenized_community_not_available_description": "Token creation is not available for previously created posts.",
"tokenized_community_not_available_title": "Tokenized content error",
diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb
index 5beee78851..29b34aff20 100644
--- a/lib/l10n/app_es.arb
+++ b/lib/l10n/app_es.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "¡El token del creador está EN VIVO!",
"tokenized_community_creator_token_live_subtitle": "Felicidades, tu token de creador ya está en vivo y disponible para que todos lo intercambien",
"tokenized_community_holders_tab": "Tenedores",
+ "tokenized_community_burned": "Quemado",
"token_comment_holders_only": "Los comentarios están disponibles solo para los tenedores de tokens.",
"tokenized_community_not_available_description": "La creación de tokens no está disponible para publicaciones creadas previamente.",
"tokenized_community_not_available_title": "Error de contenido tokenizado",
diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb
index 733db9a72e..9c2820a549 100644
--- a/lib/l10n/app_fr.arb
+++ b/lib/l10n/app_fr.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Le token du créateur est EN DIRECT !",
"tokenized_community_creator_token_live_subtitle": "Félicitations, votre token de créateur est maintenant en direct et disponible pour que tout le monde puisse l'échanger",
"tokenized_community_holders_tab": "Détenteurs",
+ "tokenized_community_burned": "Brûlé",
"token_comment_holders_only": "Les commentaires sont disponibles uniquement pour les détenteurs de tokens.",
"tokenized_community_not_available_description": "La création de tokens n'est pas disponible pour les publications déjà créées.",
"tokenized_community_not_available_title": "Erreur de contenu tokenisé",
diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb
index 38528b9ee8..77c05e597e 100644
--- a/lib/l10n/app_it.arb
+++ b/lib/l10n/app_it.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Il token del creatore è LIVE!",
"tokenized_community_creator_token_live_subtitle": "Congratulazioni, il tuo token creatore è ora attivo e disponibile per tutti per scambiarlo",
"tokenized_community_holders_tab": "Detentori",
+ "tokenized_community_burned": "Bruciato",
"token_comment_holders_only": "I commenti sono disponibili solo per i detentori di token.",
"tokenized_community_not_available_description": "La creazione di token non è disponibile per i post creati in precedenza.",
"tokenized_community_not_available_title": "Errore di contenuto tokenizzato",
diff --git a/lib/l10n/app_pl.arb b/lib/l10n/app_pl.arb
index a61df767a7..f953799a1a 100644
--- a/lib/l10n/app_pl.arb
+++ b/lib/l10n/app_pl.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Token twórcy jest NA ŻYWO!",
"tokenized_community_creator_token_live_subtitle": "Gratulacje, Twój token twórcy jest teraz aktywny i dostępny dla wszystkich do handlu",
"tokenized_community_holders_tab": "Posiadacze",
+ "tokenized_community_burned": "Spalone",
"token_comment_holders_only": "Komentarze są dostępne tylko dla posiadaczy tokenów.",
"tokenized_community_not_available_description": "Tworzenie tokenów nie jest dostępne dla wcześniej utworzonych postów.",
"tokenized_community_not_available_title": "Błąd tokenizowanej treści",
diff --git a/lib/l10n/app_ro.arb b/lib/l10n/app_ro.arb
index 00eaf66037..8c4538de19 100644
--- a/lib/l10n/app_ro.arb
+++ b/lib/l10n/app_ro.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Tokenul de creator este LIVE!",
"tokenized_community_creator_token_live_subtitle": "Felicitări, tokenul tău de creator este acum activ și disponibil pentru toată lumea să îl tranzacționeze",
"tokenized_community_holders_tab": "Deținători",
+ "tokenized_community_burned": "Arse",
"token_comment_holders_only": "Comentariile sunt disponibile doar pentru deținătorii de tokenuri.",
"tokenized_community_not_available_description": "Crearea de tokenuri nu este disponibilă pentru postările create anterior.",
"tokenized_community_not_available_title": "Eroare de conținut tokenizat",
diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb
index e3ab61dfd8..71690feda3 100644
--- a/lib/l10n/app_ru.arb
+++ b/lib/l10n/app_ru.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "Токен создателя АКТИВЕН!",
"tokenized_community_creator_token_live_subtitle": "Поздравляем, ваш токен создателя теперь активен и доступен всем для торговли",
"tokenized_community_holders_tab": "Держатели",
+ "tokenized_community_burned": "Сожжено",
"token_comment_holders_only": "Комментарии доступны только держателям токенов.",
"tokenized_community_not_available_description": "Создание токенов недоступно для ранее созданных публикаций.",
"tokenized_community_not_available_title": "Ошибка токенизированного контента",
diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb
index d3f5dfc169..398a286dab 100644
--- a/lib/l10n/app_tr.arb
+++ b/lib/l10n/app_tr.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "İçerik üreticisi tokeni YAYINDA!",
"tokenized_community_creator_token_live_subtitle": "Tebrikler, içerik üreticisi tokeniniz artık yayında ve herkesin işlem yapması için mevcut",
"tokenized_community_holders_tab": "Sahipler",
+ "tokenized_community_burned": "Yakıldı",
"token_comment_holders_only": "Yorumlar yalnızca token sahipleri için kullanılabilir.",
"tokenized_community_not_available_description": "Önceden oluşturulmuş gönderiler için token oluşturma kullanılamaz.",
"tokenized_community_not_available_title": "Tokenlaştırılmış içerik hatası",
diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb
index 2e74a2a6d6..bc9638fdef 100644
--- a/lib/l10n/app_zh.arb
+++ b/lib/l10n/app_zh.arb
@@ -920,6 +920,7 @@
"tokenized_community_creator_token_live_title": "创作者代币已上线!",
"tokenized_community_creator_token_live_subtitle": "恭喜,您的创作者代币现已上线,所有人都可以交易",
"tokenized_community_holders_tab": "持有者",
+ "tokenized_community_burned": "已销毁",
"token_comment_holders_only": "评论仅对代币持有者开放。",
"tokenized_community_not_available_description": "已创建的帖子无法创建代币。",
"tokenized_community_not_available_title": "代币化内容错误",
diff --git a/packages/ion_token_analytics/lib/src/community_tokens/top_holders/models/top_holder.f.dart b/packages/ion_token_analytics/lib/src/community_tokens/top_holders/models/top_holder.f.dart
index 0960295f64..1c10a90b15 100644
--- a/packages/ion_token_analytics/lib/src/community_tokens/top_holders/models/top_holder.f.dart
+++ b/packages/ion_token_analytics/lib/src/community_tokens/top_holders/models/top_holder.f.dart
@@ -35,6 +35,9 @@ extension TopHolderPatchExtension on TopHolderPatch {
}
}
+/// Burn address for tokenized communities
+const String _topHolderBurnAddress = '0x0000000000000000000000000000000000696f6e';
+
extension TopHolderExtension on TopHolder {
TopHolder merge(TopHolderPatch patch) {
final orgJson = toJson();
@@ -44,4 +47,17 @@ extension TopHolderExtension on TopHolder {
return TopHolder.fromJson(mergedJson);
}
+
+ /// Returns true if this holder is a burned holder (tokens sent to burn address)
+ bool get isBurning {
+ final holderAddress = position.holder?.addresses?.ionConnect;
+ return holderAddress != null &&
+ holderAddress.toLowerCase() == _topHolderBurnAddress.toLowerCase();
+ }
+
+ /// Returns true if this holder is the bounding curve contract
+ bool isBoundingCurve(String address) {
+ final holderAddress = position.holder?.addresses?.ionConnect;
+ return holderAddress != null && holderAddress.toLowerCase() == address.toLowerCase();
+ }
}