forked from LaconicNetwork/cosmos-explorer
Merge branch 'master' of github.com:ping-pub/explorer
This commit is contained in:
commit
9026aa8579
@ -22,9 +22,3 @@ const expenseRationChartConfig = computed(() => {
|
||||
:series="series"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
export default {
|
||||
name: 'DonetChart',
|
||||
};
|
||||
</script>
|
||||
|
||||
@ -12,11 +12,11 @@ const txs = computed(() => {
|
||||
return props.value?.map((x) => {
|
||||
const tx_bytes = fromBase64(x);
|
||||
let tx = null
|
||||
let injected = false
|
||||
let injected = 'Standard'
|
||||
try {
|
||||
tx = decodeTxRaw(fromBase64(x))
|
||||
} catch(e) {
|
||||
injected = true
|
||||
injected = 'Injected'
|
||||
}
|
||||
return {
|
||||
hash: hashTx(tx_bytes),
|
||||
@ -34,7 +34,7 @@ const chain = useBlockchain();
|
||||
<table class="table w-full" density="compact" v-if="txs.length > 0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Injected</th>
|
||||
<th>Type</th>
|
||||
<th style="position: relative; z-index: 2;">Hash</th>
|
||||
<th>Msgs</th>
|
||||
<th>Memo</th>
|
||||
@ -44,7 +44,7 @@ const chain = useBlockchain();
|
||||
<tr v-for="item in txs">
|
||||
<td>{{ item.injected }}</td>
|
||||
<td>
|
||||
<span v-if="item.injected">{{ item.hash }}</span>
|
||||
<span v-if="item.injected ==='Injected'">{{ item.hash }}</span>
|
||||
<RouterLink v-else :to="`/${chain.chainName}/tx/${item.hash}`" class="text-primary dark:invert">{{
|
||||
item.hash
|
||||
}}</RouterLink>
|
||||
|
||||
104
src/libs/api/customization/xion.ts
Normal file
104
src/libs/api/customization/xion.ts
Normal file
@ -0,0 +1,104 @@
|
||||
import type { RequestRegistry } from '@/libs/api/registry';
|
||||
import { adapter } from '@/libs/api/registry'
|
||||
import { CosmosRestClient } from '@/libs/client';
|
||||
import { useBlockchain } from '@/stores';
|
||||
import type {
|
||||
GovProposal,
|
||||
PaginatedProposals,
|
||||
} from '@/types/';
|
||||
|
||||
// which registry is store
|
||||
export const store = 'name'; // name or version
|
||||
// Blockchain Name
|
||||
export const name = 'xion';
|
||||
|
||||
export function proposalAdapter(p: any): GovProposal {
|
||||
if (p) {
|
||||
if (p.messages && p.messages.length >= 1) p.content = p.messages[0].content || p.messages[0]
|
||||
p.proposal_id = p.id
|
||||
p.final_tally_result = {
|
||||
yes: p.final_tally_result?.yes_count,
|
||||
no: p.final_tally_result?.no_count,
|
||||
no_with_veto: p.final_tally_result?.no_with_veto_count,
|
||||
abstain: p.final_tally_result?.abstain_count,
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
// xion custom request
|
||||
export const requests: Partial<RequestRegistry> = {
|
||||
bank_supply_by_denom: { url: '/cosmos/bank/v1beta1/supply/by_denom?denom={denom}', adapter },
|
||||
gov_params_voting: { url: '/cosmos/gov/v1/params/voting', adapter },
|
||||
gov_params_tally: { url: '/cosmos/gov/v1/params/tallying', adapter },
|
||||
gov_params_deposit: { url: '/cosmos/gov/v1/params/deposit', adapter },
|
||||
gov_proposals: {
|
||||
url: '/cosmos/gov/v1/proposals', adapter: async (source: any): Promise<PaginatedProposals> => {
|
||||
const proposals = source.proposals.map((p: any) => proposalAdapter(p))
|
||||
return {
|
||||
proposals,
|
||||
pagination: source.pagination
|
||||
}
|
||||
}
|
||||
},
|
||||
gov_proposals_proposal_id: {
|
||||
url: '/cosmos/gov/v1/proposals/{proposal_id}',
|
||||
adapter: async (source: any): Promise<{ proposal: GovProposal }> => {
|
||||
return {
|
||||
proposal: proposalAdapter(source.proposal)
|
||||
}
|
||||
},
|
||||
},
|
||||
gov_proposals_deposits: {
|
||||
url: '/cosmos/gov/v1/proposals/{proposal_id}/deposits',
|
||||
adapter,
|
||||
},
|
||||
gov_proposals_tally: {
|
||||
url: '/cosmos/gov/v1/proposals/{proposal_id}/tally',
|
||||
adapter,
|
||||
},
|
||||
gov_proposals_votes: {
|
||||
url: '/cosmos/gov/v1/proposals/{proposal_id}/votes',
|
||||
adapter,
|
||||
},
|
||||
gov_proposals_votes_voter: {
|
||||
url: '/cosmos/gov/v1/proposals/{proposal_id}/votes/{voter}',
|
||||
adapter,
|
||||
},
|
||||
mint_inflation: {
|
||||
url: '/xion/mint/v1/inflation',
|
||||
adapter: async (data: any): Promise<{ inflation: string }> => {
|
||||
try {
|
||||
const client = CosmosRestClient.newDefault(
|
||||
useBlockchain().endpoint.address
|
||||
);
|
||||
|
||||
// Get distribution params to fetch community tax
|
||||
const { params } = await client.getDistributionParams().catch((e) => {
|
||||
console.error('[Xion Adapter] Failed to fetch distribution params:', {
|
||||
error: e instanceof Error ? e.message : e,
|
||||
endpoint: '/distribution/params',
|
||||
});
|
||||
return { params: { community_tax: '0' } };
|
||||
});
|
||||
|
||||
const communityTax = params.community_tax;
|
||||
|
||||
// apr calcuation is inflation * (1 - communityTax)
|
||||
const adjustedInflation =
|
||||
parseFloat(data.inflation) * (1 - parseFloat(communityTax));
|
||||
|
||||
return { inflation: adjustedInflation.toString() };
|
||||
} catch (e) {
|
||||
console.error('[Xion Adapter] Error calculating inflation:', {
|
||||
error: e instanceof Error ? e.message : e,
|
||||
timestamp: new Date().toISOString(),
|
||||
endpoint: useBlockchain().endpoint.address,
|
||||
});
|
||||
return { inflation: '0' };
|
||||
}
|
||||
},
|
||||
},
|
||||
mint_params: { url: '/xion/mint/v1/params', adapter },
|
||||
mint_annual_provisions: { url: '/xion/mint/v1beta1/annual_provisions', adapter }
|
||||
}
|
||||
@ -1,52 +1,96 @@
|
||||
<script lang="ts" setup>
|
||||
import { computed, ref } from '@vue/reactivity';
|
||||
import { useBaseStore, useBlockchain, useFormatter } from '@/stores';
|
||||
import { PageRequest, type AuthAccount, type Pagination, type Coin } from '@/types';
|
||||
import { ref } from '@vue/reactivity';
|
||||
import { useBlockchain, useFormatter } from '@/stores';
|
||||
import { PageRequest, type Pagination, type Coin, type DenomMetadata } from '@/types';
|
||||
import { onMounted } from 'vue';
|
||||
import type { Asset } from '@ping-pub/chain-registry-client/dist/types'
|
||||
import PaginationBar from '@/components/PaginationBar.vue';
|
||||
const props = defineProps(['chain']);
|
||||
|
||||
const format = useFormatter();
|
||||
const chainStore = useBlockchain()
|
||||
const chainStore = useBlockchain();
|
||||
|
||||
const list = ref([] as Coin[])
|
||||
|
||||
function showType(v: string) {
|
||||
return v.replace("/cosmos.auth.v1beta1.", "")
|
||||
}
|
||||
const list = ref([] as ({ denom: string, amount: string, base: string, info: string, logo: string | undefined })[])
|
||||
|
||||
const pageRequest = ref(new PageRequest())
|
||||
const pageResponse = ref({} as Pagination)
|
||||
|
||||
interface SupplyAsset extends Asset {
|
||||
logo: string | undefined
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
pageload(1)
|
||||
});
|
||||
|
||||
function findGlobalAssetConfig(denom: string) {
|
||||
const assets = chainStore.current?.assets
|
||||
if (assets) {
|
||||
const conf = assets.find(a => a.base === denom)
|
||||
if (conf) {
|
||||
return conf
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
async function mergeDenomMetadata(denom: string, denomsMetadatas: DenomMetadata[]): Promise<SupplyAsset> {
|
||||
const denomMetadata = denomsMetadatas.find(d => d.base.endsWith(denom));
|
||||
let asset = findGlobalAssetConfig(denom) as SupplyAsset
|
||||
if (asset && denomMetadata) {
|
||||
asset = { ...denomMetadata, ...asset }
|
||||
asset.display = denomMetadata.display
|
||||
asset.logo = asset.logo_URIs?.svg || asset.logo_URIs?.png || asset.logo_URIs?.jpeg || undefined
|
||||
} else if (denomMetadata) {
|
||||
return denomMetadata as SupplyAsset
|
||||
}
|
||||
return asset;
|
||||
}
|
||||
|
||||
function pageload(p: number) {
|
||||
pageRequest.value.setPage(p)
|
||||
chainStore.rpc.getBankSupply(pageRequest.value).then(x => {
|
||||
list.value = x.supply
|
||||
pageResponse.value = x.pagination
|
||||
});
|
||||
chainStore.rpc.getBankDenomMetadata().then(async (denomsMetaResponse) => {
|
||||
const bankSupplyResponse = await chainStore.rpc.getBankSupply(pageRequest.value);
|
||||
list.value = await Promise.all(bankSupplyResponse.supply.map(async (coin: Coin) => {
|
||||
const asset = await mergeDenomMetadata(coin.denom, denomsMetaResponse.metadatas)
|
||||
const denom = (asset?.symbol || coin.denom)
|
||||
return {
|
||||
denom: denom.split('/')[denom.split('/').length - 1].toUpperCase(),
|
||||
amount: format.tokenAmountNumber({ amount: coin.amount, denom: denom }).toString(),
|
||||
base: asset.base || coin.denom,
|
||||
info: asset.display || coin.denom,
|
||||
logo: asset?.logo_URIs?.svg || asset?.logo_URIs?.png || asset?.logo_URIs?.jpeg || "/logo.svg",
|
||||
}
|
||||
}));
|
||||
pageResponse.value = bankSupplyResponse.pagination
|
||||
})
|
||||
}
|
||||
|
||||
</script>
|
||||
<template>
|
||||
<div class="overflow-auto bg-base-100">
|
||||
<table class="table table-compact">
|
||||
<thead class=" bg-base-200">
|
||||
<tr>
|
||||
<td>Token</td>
|
||||
<td>Amount</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="item in list" class="hover">
|
||||
<td>{{ item.denom }}</td>
|
||||
<td>{{ item.amount }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<PaginationBar :limit="pageRequest.limit" :total="pageResponse.total" :callback="pageload" />
|
||||
</div>
|
||||
<div class="overflow-auto bg-base-100">
|
||||
<table class="table table-compact">
|
||||
<thead class=" bg-base-200">
|
||||
<tr>
|
||||
<td>Logo</td>
|
||||
<td>Token</td>
|
||||
<td>Amount</td>
|
||||
<td>Info</td>
|
||||
<td>Base</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tr v-for="item in list" class="hover">
|
||||
<td>
|
||||
<img v-if="item.logo" :src="item.logo" class="w-7 h-7" />
|
||||
</td>
|
||||
<td>{{ item.denom }}</td>
|
||||
<td>{{ item.amount }}</td>
|
||||
<td>{{ item.info }}</td>
|
||||
<td>{{ item.base }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
<PaginationBar :limit="pageRequest.limit" :total="pageResponse.total" :callback="pageload" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<route>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user