Looking for Contributors! This Skill needs an implementation.Contributing a Skill involves:
- Writing a reference implementation with full functionality
- Adding comprehensive tests
- Writing documentation with usage examples
Skill — Copyable reference implementation. Use as-is or customize. See Skills Philosophy.
Planned Implementation
Composables
Copy
Ask AI
// useProvider.ts
import { ref, shallowRef, onMounted, onUnmounted } from 'vue';
import { BrowserProvider } from './BrowserProvider.js';
export function useProvider() {
const provider = shallowRef(null);
const accounts = ref([]);
const chainId = ref(null);
const isConnected = computed(() => accounts.value.length > 0);
onMounted(() => {
try {
provider.value = BrowserProvider();
provider.value.getAccounts().then(a => accounts.value = a);
provider.value.getChainId().then(c => chainId.value = c);
provider.value.onAccountsChanged(a => accounts.value = a);
provider.value.onChainChanged(c => chainId.value = c);
} catch (e) {
// No provider available
}
});
async function connect() {
accounts.value = await provider.value?.requestAccounts();
}
return { provider, accounts, chainId, isConnected, connect };
}
useBalance
Copy
Ask AI
import { ref, watch, computed } from 'vue';
export function useBalance(address, options = {}) {
const data = ref(null);
const isLoading = ref(false);
const error = ref(null);
const { provider } = useProvider();
async function fetch() {
if (!address.value || !provider.value) return;
isLoading.value = true;
try {
data.value = await provider.value.getBalance(address.value);
error.value = null;
} catch (e) {
error.value = e;
} finally {
isLoading.value = false;
}
}
watch([address, provider], fetch, { immediate: true });
// Auto-refresh on new blocks
if (options.watch) {
// Set up block subscription
}
return { data, isLoading, error, refetch: fetch };
}
useContractRead
Copy
Ask AI
export function useContractRead({ address, abi, functionName, args }) {
const data = ref(null);
const isLoading = ref(false);
const error = ref(null);
const { provider } = useProvider();
async function fetch() {
if (!provider.value) return;
isLoading.value = true;
try {
const contract = Contract({ address, abi, provider: provider.value });
data.value = await contract.read[functionName](...(args.value || []));
error.value = null;
} catch (e) {
error.value = e;
} finally {
isLoading.value = false;
}
}
watch([args], fetch, { immediate: true, deep: true });
return { data, isLoading, error, refetch: fetch };
}
useContractWrite
Copy
Ask AI
export function useContractWrite({ address, abi, functionName }) {
const isLoading = ref(false);
const error = ref(null);
const txHash = ref(null);
const { provider } = useProvider();
async function write(...args) {
isLoading.value = true;
try {
const contract = Contract({ address, abi, provider: provider.value });
txHash.value = await contract.write[functionName](...args);
error.value = null;
return txHash.value;
} catch (e) {
error.value = e;
throw e;
} finally {
isLoading.value = false;
}
}
return { write, isLoading, error, txHash };
}
Example Component
Copy
Ask AI
<script setup>
import { useProvider, useBalance, useContractRead } from './composables';
const { accounts, isConnected, connect } = useProvider();
const { data: balance, isLoading: balanceLoading } = useBalance(
computed(() => accounts.value[0])
);
const { data: tokenBalance } = useContractRead({
address: USDC_ADDRESS,
abi: ERC20_ABI,
functionName: 'balanceOf',
args: computed(() => [accounts.value[0]])
});
</script>
<template>
<div v-if="!isConnected">
<button @click="connect">Connect Wallet</button>
</div>
<div v-else>
<p>Account: {{ accounts[0] }}</p>
<p>Balance: {{ balance }} ETH</p>
<p>USDC: {{ tokenBalance }}</p>
</div>
</template>
Related
- react-query — React integration
- eip1193-provider — Browser wallet connection
- ethers-contract — Contract interactions

