Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add vue composables #9

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
48 changes: 48 additions & 0 deletions packages/vue/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
{
"name": "@interchain-kit/vue",
"version": "0.0.1-beta.1",
"author": "cosmology-tech <[email protected]>",
"description": "interchain-kit wallet connector vue package",
"main": "dist/index.js",
"module": "dist/index.mjs",
"types": "dist/index.d.ts",
"homepage": "https://github.com/interchain-kit/vue",
"license": "SEE LICENSE IN LICENSE",
"publishConfig": {
"access": "public",
"directory": "dist"
},
"repository": {
"type": "git",
"url": "https://github.com/interchain-kit/vue"
},
"bugs": {
"url": "https://github.com/interchain-kit/vue/issues"
},
"scripts": {
"copy": "copyfiles -f ../../LICENSE README.md package.json dist",
"clean": "rimraf dist/**",
"build": "vite build && vue-tsc --emitDeclarationOnly",
"lint": "eslint . --fix",
"test": "vitest",
"test:watch": "vitest --watch",
"dev": "vite"
},
"keywords": [],
"dependencies": {
"@chain-registry/v2-types": "^0.49.6",
"@interchain-kit/core": "0.0.1-beta.26",
"@interchain-ui/vue": "1.24.0",
"@interchainjs/cosmos-types": "0.0.1-beta.9",
"@interchainjs/injective": "0.0.1-beta.13",
"interchainjs": "0.0.1-beta.14",
"vue": "^3.3.4"
},
"devDependencies": {
"@vitejs/plugin-vue": "^4.2.3",
"typescript": "^5.0.2",
"vite": "^4.4.5",
"vitest": "^0.34.1",
"vue-tsc": "^1.8.5"
}
}
42 changes: 42 additions & 0 deletions packages/vue/src/composables/useAccount.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { ref, watch, onMounted, onUnmounted, Ref } from 'vue'
import { WalletAccount, WalletState } from "@interchain-kit/core"
import { useWalletManager } from './useWalletManager'

export function useAccount(chainName: Ref<string>, walletName: Ref<string>): Ref<WalletAccount | null> {
const walletManager = useWalletManager()
const account = ref<WalletAccount | null>(null)

const getAccount = async () => {
const wallet = walletManager.wallets.find(w => w.option.name === walletName.value)
const chain = walletManager.chains.find(c => c.chainName === chainName.value)

if (wallet && chain) {
if (wallet.walletState === WalletState.Connected) {
const newAccount = await wallet.getAccount(chain.chainId)
account.value = newAccount
}
if (wallet.walletState === WalletState.Disconnected) {
account.value = null
}
}
}

watch([chainName, walletName], getAccount)

onMounted(() => {
const wallet = walletManager.wallets.find(w => w.option.name === walletName.value)
if (wallet) {
wallet.events.on('keystoreChange', getAccount)
}
getAccount()
})

onUnmounted(() => {
const wallet = walletManager.wallets.find(w => w.option.name === walletName.value)
if (wallet) {
wallet.events.off('keystoreChange', getAccount)
}
})

return account
}
46 changes: 46 additions & 0 deletions packages/vue/src/composables/useChain.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { computed } from 'vue'
import { useWalletManager } from './useWalletManager'
import { useAccount } from './useAccount'
import { useCurrentWallet } from './useCurrentWallet'
import { useInterchainClient } from './useInterchainClient'
import { useWalletModal } from '../modal'
import { ChainNameNotExist } from '@interchain-kit/core'
import { getChainLogoUrl } from '../utils'

export function useChain(chainName: string) {
const walletManager = useWalletManager()
const currentWallet = useCurrentWallet()
const account = useAccount(chainName, computed(() => currentWallet.value?.option?.name))
const interchainClient = useInterchainClient(chainName, computed(() => currentWallet.value?.option?.name))
const { open, close } = useWalletModal()

const chainToShow = computed(() => walletManager.chains.find(c => c.chainName === chainName))
const assetList = computed(() => walletManager.assetLists.find(a => a.chainName === chainName))

if (!chainToShow.value) {
throw new ChainNameNotExist(chainName)
}

return {
logoUrl: computed(() => getChainLogoUrl(assetList.value)),
chain: chainToShow,
assetList,
address: computed(() => account.value?.address),
wallet: currentWallet,
connect: () => {
if (currentWallet.value) {
return
}
open()
},
openView: open,
closeView: close,
getRpcEndpoint: () => walletManager.getRpcEndpoint(currentWallet.value, chainName),
status: computed(() => currentWallet.value?.walletState),
username: computed(() => account.value?.username),
message: computed(() => currentWallet.value?.errorMessage),
getSigningCosmWasmClient: () => walletManager.getSigningCosmwasmClient(currentWallet.value?.option?.name || '', chainName),
getSigningCosmosClient: () => walletManager.getSigningCosmosClient(currentWallet.value?.option?.name || '', chainName),
...interchainClient
}
}
28 changes: 28 additions & 0 deletions packages/vue/src/composables/useChainWallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { computed, Ref } from 'vue'
import { AssetList, Chain } from "@chain-registry/v2-types"
import { useWalletManager } from "./useWalletManager"
import { useAccount } from "./useAccount"
import { BaseWallet } from "@interchain-kit/core"
import { UseChainReturnType } from "../types/chain"
import { useInterchainClient } from "./useInterchainClient"
import { getChainLogoUrl } from "../utils"

export function useChainWallet(chainName: Ref<string>, walletName: Ref<string>): UseChainReturnType {
const walletManager = useWalletManager()

const chainToShow = computed(() => walletManager.chains.find((c: Chain) => c.chainName === chainName.value))
const assetList = computed(() => walletManager.assetLists.find((a: AssetList) => a.chainName === chainName.value))
const wallet = computed(() => walletManager.wallets.find((w: BaseWallet) => w.option.name === walletName.value))

const account = useAccount(chainName, walletName)
const interchainClient = useInterchainClient(chainName, walletName)

return {
logoUrl: computed(() => getChainLogoUrl(assetList.value)),
chain: chainToShow,
assetList,
address: computed(() => account.value?.address),
wallet,
...interchainClient
}
}
14 changes: 14 additions & 0 deletions packages/vue/src/composables/useConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { AssetList, Chain } from "@chain-registry/v2-types"
import { useWalletManager } from "./useWalletManager"
import { EndpointOptions, SignerOptions } from "@interchain-kit/core"

export function useConfig() {
const walletManager = useWalletManager()

return {
updateChains: (chains: Chain[]) => walletManager.chains = chains,
updateAssetLists: (assetLists: AssetList[]) => walletManager.assetLists = assetLists,
updateSignerOptions: (signerOptions: SignerOptions) => walletManager.signerOptions = signerOptions,
updateEndpoints: (endpointOptions: EndpointOptions) => walletManager.endpointOptions = endpointOptions,
}
}
62 changes: 62 additions & 0 deletions packages/vue/src/composables/useInterchainClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { HttpEndpoint } from '@interchainjs/types'
import { CosmWasmSigningClient } from 'interchainjs/cosmwasm'
import { CosmosSigningClient } from 'interchainjs/cosmos'
import { SigningClient } from 'interchainjs/signing-client'
import { RpcQuery } from 'interchainjs/query/rpc'
import { ref, watch, Ref } from 'vue'
import { useWalletManager } from './useWalletManager'
import { Chain } from '@chain-registry/v2-types'
import { useAccount } from './useAccount'
import { WalletState } from '@interchain-kit/core'
import { InjSigningClient } from '@interchainjs/injective/signing-client'

export function useInterchainClient(chainName: Ref<string>, walletName: Ref<string>) {
const rpcEndpoint = ref<string | HttpEndpoint | undefined>()
const queryClient = ref<RpcQuery | null>(null)
const signingClient = ref<SigningClient | null>(null)
const signingCosmosClient = ref<CosmosSigningClient | null>(null)
const signingCosmWasmClient = ref<CosmWasmSigningClient | null>(null)
const signingInjectiveClient = ref<InjSigningClient | null>(null)
const error = ref<string | unknown | null>(null)
const isLoading = ref(false)

const walletManager = useWalletManager()
const account = useAccount(chainName, walletName)

const initialize = async () => {
const wallet = walletManager.wallets.find((w) => w.option.name === walletName.value)
const chainToShow = walletManager.chains.find((c: Chain) => c.chainName === chainName.value)

if (wallet && chainToShow && wallet?.walletState === WalletState.Connected) {
try {
isLoading.value = true

rpcEndpoint.value = await walletManager.getRpcEndpoint(wallet, chainName.value)
queryClient.value = await walletManager.getQueryClient(walletName.value, chainName.value)
signingClient.value = await walletManager.getSigningClient(walletName.value, chainName.value)
signingCosmosClient.value = await walletManager.getSigningCosmosClient(walletName.value, chainName.value)
signingCosmWasmClient.value = await walletManager.getSigningCosmwasmClient(walletName.value, chainName.value)
signingInjectiveClient.value = await walletManager.getSigningInjectiveClient(walletName.value, chainName.value)

} catch (err) {
error.value = err
console.log("create client error", err)
} finally {
isLoading.value = false
}
}
}

watch([chainName, walletName, account], initialize)

return {
rpcEndpoint,
signingClient: computed(() => chainName.value === 'injective' ? signingInjectiveClient.value : signingClient.value),
queryClient,
signingCosmosClient,
signingCosmWasmClient,
signingInjectiveClient,
error,
isLoading
}
}
19 changes: 19 additions & 0 deletions packages/vue/src/composables/useOfflineSigner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { OfflineSigner } from '@interchainjs/cosmos/types/wallet'
import { ref, watch, Ref } from 'vue'
import { useWalletManager } from './useWalletManager'

export function useOfflineSigner(chainName: Ref<string>, walletName: Ref<string>) {
const walletManager = useWalletManager()
const offlineSigner = ref<OfflineSigner | null>(null)

watch([chainName, walletName], () => {
const wallet = walletManager.wallets.find((w) => w.option.name === walletName.value)
if (wallet && chainName.value) {
offlineSigner.value = walletManager.getOfflineSigner(wallet, chainName.value)
}
}, { immediate: true })

return {
offlineSigner
}
}
11 changes: 11 additions & 0 deletions packages/vue/src/composables/useWalletManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { inject } from 'vue'
import { WalletManager } from '@interchain-kit/core'
import { WALLET_MANAGER_KEY } from '../provider'

export function useWalletManager(): WalletManager {
const walletManager = inject(WALLET_MANAGER_KEY)
if (!walletManager) {
throw new Error('useWalletManager must be used within a ChainProvider')
}
return walletManager
}
5 changes: 5 additions & 0 deletions packages/vue/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export * from './provider'
export * from './composables'
export * from './types'
export * from './enum'
export * from './modal'