Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
24 changes: 21 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,22 @@
# rename to .env.local or .env.<your_environment>
VITE_REFRESH_INTERVAL=2000
VITE_FETCH_ALL_BLOCKS=true
VITE_RECENT_BLOCK_LIMIT=100

# Refresh interval for the app to query api for new blocks
VITE_REFRESH_INTERVAL=6000

# Enable fetching all blocks (this can increase api calls to public nodes resulting in rate limiting)
VITE_FETCH_ALL_BLOCKS=false

# Limit for recent blocks and associated transactions displayed in the UI
VITE_RECENT_BLOCK_LIMIT=50

# URL for CoinGecko API or custom proxy
VITE_COINGECKO_URL=https://api.coingecko.com

# GITHUB_API_URL default
VITE_GITHUB_API_URL=https://api.github.com/repos/cosmos/chain-registry/contents

# PINGPUB_API_URL default
VITE_PINGPUB_API_URL=https://registry.ping.pub

# IBC use PINGPUB_API_URL by Default (false) or GITHUB_API_URL (true)
VITE_IBC_USE_GITHUB_API=false
14 changes: 7 additions & 7 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"tabWidth": 2,
"singleQuote": true,
"semi": true,
"endOfLine": "auto",
"bracketSpacing": true,
"trailingComma": "es5",
"arrowParens": "always",
"bracketSpacing": true,
"endOfLine": "auto",
"printWidth": 80,
"semi": true,
"singleAttributePerLine": false,
"printWidth": 120,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false
}
3 changes: 2 additions & 1 deletion chains/mainnet/xion.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"chain_name": "xion",
"chain_id": "xion-mainnet-1",
"registry_name": "xion",
"coingecko": "xion",
"network_type": "mainnet",
Expand Down Expand Up @@ -32,7 +33,7 @@
}
],
"snapshot_provider": "",
"sdk_version": "0.50.13",
"sdk_version": "0.53.3",
"coin_type": "118",
"min_tx_fee": "100",
"addr_prefix": "xion",
Expand Down
13 changes: 13 additions & 0 deletions env.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/// <reference types="vite/client" />

declare module '@personaxyz/ad-sdk';
interface ImportMetaEnv {
readonly VITE_REFRESH_INTERVAL?: number,
readonly VITE_FETCH_ALL_BLOCKS?: boolean,
readonly VITE_RECENT_BLOCK_LIMIT?: number,
readonly VITE_COINGECKO_URL?: string,
readonly VITE_GITHUB_API_URL?: string,
readonly VITE_PINGPUB_API_URL?: string,
readonly VITE_IBC_USE_GITHUB_API?: string,
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,31 +13,35 @@
"type-check": "vue-tsc --noEmit"
},
"dependencies": {
"@chain-registry/types": "^0.50.162",
"@chain-registry/client": "^1.53.184",
"@chain-registry/types": "^0.50.184",
"@chenfengyuan/vue-countdown": "2",
"@cosmjs/amino": "^0.32.3",
"@cosmjs/crypto": "^0.32.3",
"@cosmjs/encoding": "^0.32.3",
"@cosmjs/stargate": "^0.32.3",
"@cosmjs/cosmwasm-stargate": "^0.30.0",
"@iconify/vue": "^4.1.0",
"@intlify/unplugin-vue-i18n": "^0.8.2",
"@leapwallet/cosmos-snap-provider": "^0.1.20",
"@leapwallet/name-matcha": "^2.0.0",
"@osmonauts/lcd": "^0.8.0",
"@personaxyz/ad-sdk": "0.0.25",
"@ping-pub/chain-registry-client": "^0.0.25",
"@vitejs/plugin-vue-jsx": "^3.0.0",
"@vueuse/core": "^9.12.0",
"@vueuse/integrations": "^10.1.2",
"@vueuse/math": "^9.12.0",
"apexcharts": "^3.37.1",
"autoprefixer": "^10.4.14",
"axios": "^1.3.2",
"bech32": "^1.1.4",
"buffer": "^6.0.3",
"build": "^0.1.4",
"cross-fetch": "^3.1.5",
"daisyui": "^3.1.0",
"dayjs": "^1.11.7",
"idna-uts46-hx": "^5.0.7",
"js-sha3": "^0.8.0",
"lazy-load-vue3": "^1.3.0",
"long": "^5.2.1",
"md-editor-v3": "^2.8.1",
Expand Down Expand Up @@ -67,7 +71,7 @@
"@vue/tsconfig": "^0.1.3",
"husky": "^9.1.7",
"npm-run-all": "^4.1.5",
"prettier": "^2.7.1",
"prettier": "^3.0.0",
"pretty-quick": "^4.2.2",
"sass": "^1.58.0",
"shiki": "^1.0.0-beta.0",
Expand Down
92 changes: 65 additions & 27 deletions src/modules/[chain]/ibc/connStore.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,98 @@
import { defineStore } from 'pinia';

import { useBlockchain } from '@/stores';
import ChainRegistryClient from '@ping-pub/chain-registry-client';
import type { IBCPath, IBCInfo } from '@ping-pub/chain-registry-client/dist/types';
import type { Channel } from '@/types';
import { ChainRegistryClient } from '@chain-registry/client';
import type { IBCData } from '@chain-registry/types/ibc_data.schema';
import router from '@/router';
import fetch from 'cross-fetch';

const IBC_USE_GITHUB_API = import.meta.env.VITE_IBC_USE_GITHUB_API === 'true';
const PINGPUB_API_URL = import.meta.env.VITE_PINGPUB_API_URL || 'https://registry.ping.pub';
const GITHUB_API_URL =
import.meta.env.VITE_GITHUB_API_URL || 'https://api.github.com/repos/cosmos/chain-registry/contents';
const IBC_API_URL = IBC_USE_GITHUB_API ? GITHUB_API_URL : PINGPUB_API_URL;

export const useIBCModule = defineStore('module-ibc', {
state: () => {
return {
paths: [] as IBCPath[],
info: [] as IBCData[],
connectionId: '' as string,
registryConf: {} as IBCInfo,
registryConf: {} as IBCData,
};
},
getters: {
chain() {
return useBlockchain();
},
commonIBCs(): any {
return this.paths.filter(
(x: IBCPath) => x.path.search(this.chain.current?.prettyName || this.chain.chainName) > -1
chainName(): string {
return this.chain.chainName;
},
isFirstChain(): boolean {
return (
this.registryConf.chain_1.chain_name === this.chain.current?.prettyName ||
this.registryConf.chain_1.chain_name === this.chain.chainName
);
},
sourceField(): string {
return this.registryConf?.chain_1?.chain_name === this.chain.current?.prettyName || this.chain.chainName
? 'chain_1'
: 'chain_2';
return this.isFirstChain ? 'chain_1' : 'chain_2';
},
destField(): string {
return this.registryConf?.chain_1?.chain_name === this.chain.current?.prettyName || this.chain.chainName
? 'chain_2'
: 'chain_1';
return this.isFirstChain ? 'chain_2' : 'chain_1';
},
registryChannels(): any {
return this.registryConf.channels;
},
},
actions: {
load() {
const client = new ChainRegistryClient();
client.fetchIBCPaths().then((res) => {
this.paths = res;
const prefix = this.chain.current?.networkType?.includes('testnet') ? 'testnets/' : '';
const client = new ChainRegistryClient({
chainNames: [this.chainName],
baseUrl: IBC_USE_GITHUB_API ? undefined : new URL(`${prefix}`, PINGPUB_API_URL + '/').toString(),
});
this.fetchIBCUrls().then((res) => {
res.forEach((element: any) => {
if (element.download_url) {
client.urls.push(element.download_url);
}
});
client.fetchUrls().then(() => {
const info = client.getChainIbcData(this.chainName);
this.info = info.sort((a, b) => {
// Sort by remote chain name (not equal to this.chainName)
const getRemote = (x: any) =>
x?.chain_1?.chain_name === this.chain.current?.prettyName ||
x?.chain_1?.chain_name === this.chain.chainName
? x.chain_2.chain_name
: x.chain_1.chain_name;
return getRemote(a).localeCompare(getRemote(b));
});
});
});
},
fetchConnection(path: string) {
const client = new ChainRegistryClient();
client.fetchIBCPathInfo(path).then((res) => {
const isFirstChain =
res.chain_1.chain_name === this.chain.current?.prettyName || res.chain_1.chain_name === this.chain.chainName;

const connId = isFirstChain ? res.chain_1.connection_id : res.chain_2.connection_id;
async fetchIBCUrls(): Promise<any[]> {
const prefix = this.chain.current?.networkType?.includes('testnet') ? 'testnets/' : '';
const ibcEndpoint = new URL(`${prefix}_IBC`, IBC_API_URL + '/').toString();
console.log('Fetching IBC URLs from:', IBC_API_URL);
let entries = await fetch(ibcEndpoint)
.then((res) => res.json())
.then((data: any) => (Array.isArray(data) ? data.filter((x: any) => x.name.match(this.chainName)) : []));

this.registryConf = res;
this.showConnection(connId);
});
// If using PINGPUB_API_URL, add thedownload URLs
if (IBC_API_URL == PINGPUB_API_URL) {
return entries.map((entry: any) => {
entry.download_url = new URL(`${prefix}_IBC/${entry.name}`, PINGPUB_API_URL + '/').toString();
return entry;
});
}
return entries;
},
fetchConnection(index: number) {
this.registryConf = this.info[index];
const connId = this.isFirstChain
? this.registryConf.chain_1.connection_id
: this.registryConf.chain_2.connection_id;
this.showConnection(connId);
},
showConnection(connId?: string | number) {
if (!connId) {
Expand Down
53 changes: 35 additions & 18 deletions src/modules/[chain]/ibc/connection.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
<script lang="ts" setup>
import PaginationBar from '@/components/PaginationBar.vue';
import { useBlockchain, useFormatter } from '@/stores';
import { useBlockchain } from '@/stores';
import { PageRequest, type Connection, type Pagination } from '@/types';
import { computed, onMounted } from 'vue';
import { onMounted } from 'vue';
import { ref } from 'vue';

import ChainRegistryClient from '@ping-pub/chain-registry-client';
import type { IBCPath } from '@ping-pub/chain-registry-client/dist/types';
import router from '@/router';
import { useIBCModule } from './connStore';

const props = defineProps(['chain']);
Expand All @@ -29,7 +25,7 @@ function pageload(p: number) {
list.value = x.connections;
pageResponse.value = x.pagination;
if (x.pagination.total && Number(x.pagination.total) > 0) {
ibcStore.showConnection(0);
ibcStore.showConnection(list.value[0].id);
}
});
}
Expand All @@ -40,26 +36,44 @@ function pageload(p: number) {
<div class="flex flex-wrap gap-4 items-center">
<h2 class="card-title py-4">{{ $t('ibc.title') }}</h2>
<div class="tabs tabs-boxed">
<a class="tab" :class="{ 'tab-active': tab === 'registry' }" @click="tab = 'registry'">{{
$t('ibc.registry')
}}</a>
<a class="tab" :class="{ 'tab-active': tab === 'favorite' }" @click="tab = 'favorite'">{{
$t('module.favorite')
}}</a>
<a
class="tab"
:class="{ 'tab-active': tab === 'registry' }"
@click="tab = 'registry'"
>{{ $t('ibc.registry') }}</a
>
<a
class="tab"
:class="{ 'tab-active': tab === 'favorite' }"
@click="tab = 'favorite'"
>{{ $t('module.favorite') }}</a
>
</div>
</div>
<div>
<div v-show="tab === 'registry'" class="flex flex-wrap gap-1 p-4">
<span
v-for="s in ibcStore.commonIBCs"
v-for="(s, i) in ibcStore.info"
class="btn btn-xs btn-link mr-1"
@click="ibcStore.fetchConnection(s.path)"
>{{ s.from }} &#x21cc; {{ s.to }}</span
@click="ibcStore.fetchConnection(i)"
>{{
s.chain_1.chain_name === ibcStore.chainName
? s.chain_2.chain_name
: s.chain_1.chain_name
}}
&#x21cc;
{{
s.chain_1.chain_name === ibcStore.chainName
? s.chain_1.chain_name
: s.chain_2.chain_name
}}</span
>
</div>
<div v-show="tab === 'favorite'" class="flex flex-wrap gap-1 p-4">
<div class="join border border-primary">
<button class="join-item px-2">{{ $t('ibc.connection_id') }}:</button>
<button class="join-item px-2">
{{ $t('ibc.connection_id') }}:
</button>
<input
v-model="ibcStore.connectionId"
type="number"
Expand All @@ -68,7 +82,10 @@ function pageload(p: number) {
:max="pageResponse.total || 0"
:placeholder="`0~${pageResponse.total}`"
/>
<button class="join-item btn btn-primary" @click="ibcStore.showConnection()">
<button
class="join-item btn btn-primary"
@click="ibcStore.showConnection()"
>
{{ $t('ibc.btn_apply') }}
</button>
</div>
Expand Down
Loading