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
4 changes: 1 addition & 3 deletions examples/vue/src/views/ibc-transfer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { ref, computed } from 'vue'
import { useChain, useWalletManager } from '@interchain-kit/vue';
import { ibc } from 'osmojs'
import { SigningStargateClient } from '@cosmjs/stargate'
import { ExtensionWallet } from '@interchain-kit/core';

const chainName = ref("cosmoshub")
const { rpcEndpoint, chain } = useChain(chainName)
Expand All @@ -12,8 +11,7 @@ const signer = computed(() => {
if (!chain.value.chainId) {
return
}
const wallet = wm.getCurrentWallet() as ExtensionWallet
return wallet.getOfflineSigner(chain.value.chainId, 'direct') // cosmoshub-4
return wm.value.getOfflineSigner(wm.value.currentWalletName, chainName.value) // cosmoshub-4
})

const transferMsg = ibc.applications.transfer.v1.MessageComposer.withTypeUrl.transfer({
Expand Down
2 changes: 1 addition & 1 deletion examples/vue/src/views/use-chain-wallet.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<script setup lang="ts">
import { ref } from 'vue'
import { useChainWallet, useWalletManager } from '@interchain-kit/vue';
import { useChainWallet } from '@interchain-kit/vue';
const junoChainName = ref('juno')
const stargazeChainName = ref('stargaze')
const keplrWalletName = ref('keplr-extension')
Expand Down
15 changes: 3 additions & 12 deletions examples/vue/src/views/use-config.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
<script setup lang="ts">
import { watch } from 'vue'
import { useConfig, useWalletManager } from '@interchain-kit/vue';
import { useConfig } from '@interchain-kit/vue';
import { chain as stargazeChain, assetList as stargazeAssetList } from "chain-registry/mainnet/stargaze";

const { updateChains, updateAssetLists } = useConfig()
const walletManager = useWalletManager()

const { chains, assetLists } = walletManager

watch(walletManager, (wm) => {
console.log('wm>', wm)
})
const { addChains } = useConfig()

const handleUpdate = () => {
updateChains([stargazeChain, ...chains])
updateAssetLists([stargazeAssetList, ...assetLists])
addChains([stargazeChain], [stargazeAssetList])
}
</script>

Expand Down
18 changes: 6 additions & 12 deletions examples/vue/src/views/wallet-connect.vue
Original file line number Diff line number Diff line change
@@ -1,25 +1,19 @@
<script setup lang="ts">
import { useAccount, useWalletManager } from '@interchain-kit/vue';
import { BaseWallet, WCWallet } from '@interchain-kit/core';
import VueQrcode from '@chenfengyuan/vue-qrcode';
import { ref, computed, watch } from 'vue';
import { ref, computed } from 'vue';

const walletManager = useWalletManager()
const chainName = ref('osmosis')
const currentWallet = ref<WCWallet>(walletManager.wallets.find((w: BaseWallet) => w.info?.name === 'WalletConnect') as WCWallet)
const walletName = computed(() => {
return currentWallet.value?.info?.name || ''
})
watch(walletManager, (wm: any) => {
currentWallet.value = wm.wallets.find((w: BaseWallet) => w.info?.name === 'WalletConnect')
})
const walletName = ref('WalletConnect')
const pairingUri = computed(() => walletManager.value.walletConnectQRCodeUri)
const account = useAccount(chainName, walletName)
const connect = async() => {
await walletManager.connect('WalletConnect')
await walletManager.value.connect(walletName.value, chainName.value)
}

const disconnect = async() => {
await walletManager.disconnect('WalletConnect')
await walletManager.value.disconnect(walletName.value, chainName.value)
}
</script>

Expand All @@ -28,7 +22,7 @@ const disconnect = async() => {
address: {{ account?.address }}
<button @click="connect">connect</button>
<button @click="disconnect">disconnect</button>
<vue-qrcode v-if="currentWallet?.pairingUri" :value="currentWallet?.pairingUri" :options="{ width: 200 }"></vue-qrcode>
<vue-qrcode v-if="pairingUri" :value="pairingUri" :options="{ width: 200 }"></vue-qrcode>
</div>
</template>

Expand Down
4 changes: 2 additions & 2 deletions packages/vue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ const stargaze = useChainWallet(stargazeChainName, leapWalletName);
const walletManager = useWalletManager()

const connectKeplr = async() => {
await walletManager.connect('keplr-extension')
await walletManager.value.connect('keplr-extension', 'juno')
}
const connectLeap = async() => {
await walletManager.connect('leap-extension')
await walletManager.value.connect('leap-extension', 'stargaze')
}
</script>

Expand Down
1 change: 1 addition & 0 deletions packages/vue/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"dependencies": {
"@chain-registry/types": "^2.0.1",
"@interchain-kit/core": "workspace:*",
"@interchain-kit/store": "workspace:*",
"@interchain-ui/vue": "^1.4.1",
"@interchainjs/cosmos": "1.21.0",
"@interchainjs/cosmos-types": "1.21.0",
Expand Down
18 changes: 11 additions & 7 deletions packages/vue/src/ChainProvider.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
<script setup lang="ts">
import { ref, provide, defineProps, reactive } from 'vue'
import { ref, provide, defineProps, shallowRef, triggerRef, onMounted, onUnmounted } from 'vue'
import { Modal } from './modal'
import { AssetList, Chain } from "@chain-registry/types";
import {
BaseWallet,
SignerOptions,
WalletManager,
EndpointOptions,
} from "@interchain-kit/core";
import { WalletManagerStore } from "@interchain-kit/store";
import { WALLET_MANAGER_KEY, OPEN_MODAL_KEY, CLOSE_MODAL_KEY } from './utils/index'

type InterchainWalletProviderProps = {
Expand All @@ -34,17 +34,21 @@ provide(CLOSE_MODAL_KEY, closeModal);

const { chains, assetLists, wallets, signerOptions, endpointOptions } = props;

// Make the walletManager instance reactive
// so that changes to any property of walletManager will immediately update currentWallet.
// without needing to rerender the whole app like in React.
const walletManager = reactive(new WalletManager(
// State lives in the WalletManagerStore; every store update re-triggers the ref
// so computeds reading through it re-evaluate.
const walletManager = shallowRef(new WalletManagerStore(
chains,
assetLists,
wallets,
signerOptions,
endpointOptions,
));
walletManager.init();
const unsubscribe = walletManager.value.subscribe(() => triggerRef(walletManager));

onMounted(() => {
walletManager.value.init();
});
onUnmounted(unsubscribe);

// injected globally
provide(WALLET_MANAGER_KEY, walletManager)
Expand Down
53 changes: 5 additions & 48 deletions packages/vue/src/composables/useAccount.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,9 @@
import { ChainNameNotExist, WalletAccount, WalletState } from '@interchain-kit/core';
import { computed, Ref, ref, watch } from 'vue';
import { onMounted } from 'vue';
import { WalletAccount } from '@interchain-kit/core';
import { computed, ComputedRef, Ref } from 'vue';

import { useWalletManager } from './useWalletManager';

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

const wallet = computed(() => {
return walletManager.wallets.find(w => w.info.name === walletName.value);
});

const chain = computed(() => {
return walletManager.chains.find(c => c.chainName === chainName.value);
});

const getAccount = async () => {
if (!chain.value) {
console.error(`[useAccount] error: the chain ${chainName.value} was not found, please check if it was registered in ChainProvider`);
throw new ChainNameNotExist(chainName.value);
}
if (wallet.value && chain.value) {
if (wallet.value.walletState === WalletState.Connected) {
const act = await wallet.value.getAccount(chain.value.chainId) as WalletAccount;
account.value = act;
}
if (wallet.value.walletState === WalletState.Disconnected) {
account.value = null;
}
}
if (!wallet.value) {
account.value = null;
}
};

watch([wallet, chain, walletManager], getAccount);
watch(wallet, (newWt, oldWt) => {
if (newWt) {
oldWt?.events.off('accountChanged', getAccount);
newWt?.events.on('accountChanged', getAccount);
}
});
getAccount();

onMounted(() => {
wallet.value?.events.on('accountChanged', getAccount);
});

return account;
};
return computed(() => walletManager.value.getChainWalletState(walletName.value, chainName.value)?.account ?? null);
};
78 changes: 27 additions & 51 deletions packages/vue/src/composables/useChain.ts
Original file line number Diff line number Diff line change
@@ -1,75 +1,51 @@
import { AssetList, Chain } from '@chain-registry/types';
import { ChainNameNotExist, WalletState } from '@interchain-kit/core';
import { computed, inject, Ref, ref, watch } from 'vue';
import { computed, inject, Ref } from 'vue';

import { CosmosKitUseChainReturnType, UseChainReturnType } from '../types/chain';
import { CLOSE_MODAL_KEY, OPEN_MODAL_KEY } from '../utils';
import { useAccount } from './useAccount';
import { useCurrentWallet } from './useCurrentWallet';
import { useInterchainClient } from './useInterchainClient';
import { useWalletManager } from './useWalletManager';

export const useChain = (chainName: Ref<string>): UseChainReturnType => {
const walletManager = useWalletManager();
const chainToShow = ref<Chain>();
const assetList = ref<AssetList>();
const getRpcEndpoint = ref();
const currentWallet = useCurrentWallet();
const walletName = computed<string>(() => currentWallet.value?.info?.name);
const walletName = computed<string>(() => walletManager.value.currentWalletName);
const interchainClient = useInterchainClient(chainName, walletName);
const logoUrl = ref<string>('');
const account = useAccount(chainName, walletName);
const _setValuesByChainName = () => {
chainToShow.value = walletManager.chains.find((c: Chain) => c.chainName === chainName.value);
if (!chainToShow.value) {

const chain = computed(() => {
const c = walletManager.value.getChainByName(chainName.value);
if (!c) {
throw new ChainNameNotExist(chainName.value);
}
assetList.value = walletManager.assetLists.find((a: AssetList) => a.chainName === chainName.value);
logoUrl.value = walletManager.getChainLogoUrl(chainName.value);
getRpcEndpoint.value = async () => {
return await walletManager.getRpcEndpoint(currentWallet.value, chainName.value);
};
};

watch([chainName, walletManager], () => {
_setValuesByChainName();
return c;
});
_setValuesByChainName();
const chainWalletState = computed(() => walletManager.value.getChainWalletState(walletName.value, chainName.value));

const open = inject<() => void>(OPEN_MODAL_KEY);
const close = inject<() => void>(CLOSE_MODAL_KEY);

const disconnect = computed(() => {
return () => {
walletManager.disconnect(currentWallet.value?.info?.name);
};
});
const openView = () => {
walletManager.value.setCurrentChainName(chainName.value);
open();
};

const cosmosKitUserChainReturnType: CosmosKitUseChainReturnType = {
connect: computed(() => {
return () => {
if (currentWallet.value?.walletState === WalletState.Connected) {
return;
}
open();
};
}),
disconnect,
openView: open,
const cosmosKitUseChainReturnType: CosmosKitUseChainReturnType = {
connect: computed(() => openView),
disconnect: computed(() => () => walletManager.value.disconnect(walletName.value, chainName.value)),
openView,
closeView: close,
getRpcEndpoint,
status: computed(() => currentWallet.value?.walletState),
username: computed(() => account.value?.username),
message: computed(() => currentWallet.value?.errorMessage),
getRpcEndpoint: computed(() => () => walletManager.value.getRpcEndpoint(walletName.value, chainName.value)),
status: computed(() => chainWalletState.value?.walletState || WalletState.Disconnected),
username: computed(() => chainWalletState.value?.account?.username),
message: computed(() => chainWalletState.value?.errorMessage),
};

return {
logoUrl,
chain: chainToShow,
assetList,
address: computed(() => account.value?.address),
wallet: currentWallet,
logoUrl: computed(() => walletManager.value.getChainLogoUrl(chainName.value)),
chain,
assetList: computed(() => walletManager.value.getAssetListByName(chainName.value)),
address: computed(() => chainWalletState.value?.account?.address),
wallet: computed(() => walletManager.value.getChainWalletByName(walletName.value, chainName.value)),
...interchainClient,
...cosmosKitUserChainReturnType,
...cosmosKitUseChainReturnType,
};
};
};
61 changes: 18 additions & 43 deletions packages/vue/src/composables/useChainWallet.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,31 @@
import { AssetList, Chain } from '@chain-registry/types';
import { BaseWallet } from '@interchain-kit/core';
import { computed, Ref, ref, watch } from 'vue';
import { computed, Ref } from 'vue';

import { UseChainWalletReturnType } from '../types/chain';
import { useAccount } from './useAccount';
import { useInterchainClient } from './useInterchainClient';
import { useWalletManager } from './useWalletManager';

export const useChainWallet = (chainName: Ref<string>, walletName: Ref<string>): UseChainWalletReturnType => {
const logoUrl = ref<string>('');
const walletManager = useWalletManager();
const chainToShow = ref<Chain>();
const assetList = ref<AssetList>();
const account = useAccount(chainName, walletName);
const interchainClient = useInterchainClient(chainName, walletName);
const getRpcEndpoint = ref();

const wallet = computed(() => {
return walletManager.wallets.find((w: BaseWallet) => w.info.name === walletName.value);
});

const _setValues = () => {
logoUrl.value = walletManager.getChainLogoUrl(chainName.value);
chainToShow.value = walletManager.chains.find((c: Chain) => c.chainName === chainName.value);
assetList.value = walletManager.assetLists.find((a: AssetList) => a.chainName === chainName.value);
getRpcEndpoint.value = async () => {
await walletManager.getRpcEndpoint(wallet.value, walletName.value);
};
};

const connect = computed(() => {
return () => walletManager.connect(walletName.value);
});
const disconnect = computed(() => {
return () => walletManager.disconnect(walletName.value);
});

watch([chainName, walletName, walletManager], _setValues);
_setValues();
const chainWalletState = computed(() => walletManager.value.getChainWalletState(walletName.value, chainName.value));

return {
connect,
disconnect,
getRpcEndpoint,
status: computed(() => wallet.value?.walletState),
username: computed(() => account.value?.username),
message: computed(() => wallet.value?.errorMessage),
logoUrl,
chain: chainToShow,
assetList,
address: computed(() => account.value?.address),
wallet,
connect: computed(() => async () => {
walletManager.value.setCurrentWalletName(walletName.value);
walletManager.value.setCurrentChainName(chainName.value);
await walletManager.value.connect(walletName.value, chainName.value);
}),
disconnect: computed(() => () => walletManager.value.disconnect(walletName.value, chainName.value)),
getRpcEndpoint: computed(() => () => walletManager.value.getRpcEndpoint(walletName.value, chainName.value)),
status: computed(() => chainWalletState.value?.walletState),
username: computed(() => chainWalletState.value?.account?.username),
message: computed(() => chainWalletState.value?.errorMessage),
logoUrl: computed(() => walletManager.value.getChainLogoUrl(chainName.value)),
chain: computed(() => walletManager.value.getChainByName(chainName.value)),
assetList: computed(() => walletManager.value.getAssetListByName(chainName.value)),
address: computed(() => chainWalletState.value?.account?.address),
wallet: computed(() => walletManager.value.getChainWalletByName(walletName.value, chainName.value)),
...interchainClient,
};
};
};
Loading
Loading