parent
66106077ba
commit
db3633425a
17 changed files with 18548 additions and 199 deletions
15
packages/web3/package.json
Normal file
15
packages/web3/package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "@harb/web3",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"types": "src/index.ts",
|
||||
"dependencies": {
|
||||
"@wagmi/vue": "^0.2.8",
|
||||
"viem": "^2.22.13"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.5.0"
|
||||
}
|
||||
}
|
||||
59
packages/web3/src/composables/useTokenBalance.ts
Normal file
59
packages/web3/src/composables/useTokenBalance.ts
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import { ref, watch, type Ref } from 'vue';
|
||||
import { useAccount, useChainId } from '@wagmi/vue';
|
||||
import { createPublicClient, erc20Abi, formatUnits, http } from 'viem';
|
||||
import { getHarbConfig, KRAIKEN_LOCAL_CHAIN } from '../config';
|
||||
|
||||
/**
|
||||
* Read-only KRK token balance for the connected wallet.
|
||||
* Lightweight — no contract writes, no staking, just balanceOf.
|
||||
*/
|
||||
export function useTokenBalance(tokenAddress: Ref<`0x${string}` | undefined> | `0x${string}`) {
|
||||
const { address, isConnected } = useAccount();
|
||||
const chainId = useChainId();
|
||||
|
||||
const balance = ref(0n);
|
||||
const formatted = ref('0');
|
||||
const loading = ref(false);
|
||||
|
||||
async function refresh() {
|
||||
const token = typeof tokenAddress === 'string' ? tokenAddress : tokenAddress.value;
|
||||
if (!address.value || !token) {
|
||||
balance.value = 0n;
|
||||
formatted.value = '0';
|
||||
return;
|
||||
}
|
||||
|
||||
loading.value = true;
|
||||
try {
|
||||
const config = getHarbConfig();
|
||||
const chain = config.chains.find(c => c.id === chainId.value) ?? KRAIKEN_LOCAL_CHAIN;
|
||||
const rpcUrl = chain.rpcUrls.default.http[0];
|
||||
const client = createPublicClient({ chain, transport: http(rpcUrl) });
|
||||
|
||||
const result = await client.readContract({
|
||||
abi: erc20Abi,
|
||||
address: token,
|
||||
functionName: 'balanceOf',
|
||||
args: [address.value],
|
||||
});
|
||||
balance.value = result;
|
||||
formatted.value = formatUnits(result, 18);
|
||||
} catch {
|
||||
balance.value = 0n;
|
||||
formatted.value = '0';
|
||||
} finally {
|
||||
loading.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
watch([address, isConnected], () => {
|
||||
if (isConnected.value) {
|
||||
void refresh();
|
||||
} else {
|
||||
balance.value = 0n;
|
||||
formatted.value = '0';
|
||||
}
|
||||
}, { immediate: true });
|
||||
|
||||
return { balance, formatted, loading, refresh };
|
||||
}
|
||||
87
packages/web3/src/config.ts
Normal file
87
packages/web3/src/config.ts
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
import { http, createConfig, createStorage } from '@wagmi/vue';
|
||||
import { baseSepolia } from '@wagmi/vue/chains';
|
||||
import { coinbaseWallet, injected, walletConnect } from '@wagmi/vue/connectors';
|
||||
import { defineChain } from 'viem';
|
||||
|
||||
/**
|
||||
* Shared wagmi config for all harb apps.
|
||||
* RPC URL and WalletConnect project ID are passed in to keep this package env-agnostic.
|
||||
*/
|
||||
export interface HarbWeb3Options {
|
||||
rpcUrl?: string;
|
||||
walletConnectProjectId?: string;
|
||||
}
|
||||
|
||||
const defaults = {
|
||||
rpcUrl: '/api/rpc',
|
||||
walletConnectProjectId: 'd8e5ecb0353c02e21d4c0867d4473ac5',
|
||||
};
|
||||
|
||||
export const KRAIKEN_LOCAL_CHAIN = defineChain({
|
||||
id: 31337,
|
||||
name: 'Kraiken Local Fork',
|
||||
network: 'kraiken-local',
|
||||
nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },
|
||||
rpcUrls: {
|
||||
default: { http: ['http://localhost:8545'] },
|
||||
public: { http: ['http://localhost:8545'] },
|
||||
},
|
||||
blockExplorers: {
|
||||
default: { name: 'Local Explorer', url: '' },
|
||||
},
|
||||
testnet: true,
|
||||
});
|
||||
|
||||
let _config: ReturnType<typeof createConfig> | null = null;
|
||||
|
||||
export function createHarbConfig(opts: HarbWeb3Options = {}) {
|
||||
const rpcUrl = opts.rpcUrl ?? defaults.rpcUrl;
|
||||
const wcProjectId = opts.walletConnectProjectId ?? defaults.walletConnectProjectId;
|
||||
|
||||
// Build chain with provided RPC URL
|
||||
const chain = defineChain({
|
||||
...KRAIKEN_LOCAL_CHAIN,
|
||||
rpcUrls: {
|
||||
default: { http: [rpcUrl] },
|
||||
public: { http: [rpcUrl] },
|
||||
},
|
||||
});
|
||||
|
||||
_config = createConfig({
|
||||
chains: [chain, baseSepolia],
|
||||
storage: createStorage({ storage: window.localStorage }),
|
||||
connectors: [
|
||||
injected(),
|
||||
walletConnect({
|
||||
projectId: wcProjectId,
|
||||
metadata: {
|
||||
name: 'Kraiken',
|
||||
description: 'Connect your wallet with Kraiken',
|
||||
url: 'https://kraiken.eth.limo',
|
||||
icons: [''],
|
||||
},
|
||||
}),
|
||||
coinbaseWallet({
|
||||
appName: 'Kraiken',
|
||||
darkMode: true,
|
||||
preference: { options: 'all', telemetry: false },
|
||||
}),
|
||||
],
|
||||
transports: {
|
||||
[chain.id]: http(rpcUrl),
|
||||
[baseSepolia.id]: http(),
|
||||
},
|
||||
});
|
||||
|
||||
// Default to local chain
|
||||
if (_config.state.chainId !== chain.id) {
|
||||
_config.setState(state => ({ ...state, chainId: chain.id }));
|
||||
}
|
||||
|
||||
return _config;
|
||||
}
|
||||
|
||||
export function getHarbConfig() {
|
||||
if (!_config) throw new Error('@harb/web3: call createHarbConfig() first');
|
||||
return _config;
|
||||
}
|
||||
6
packages/web3/src/index.ts
Normal file
6
packages/web3/src/index.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export { createHarbConfig, getHarbConfig, KRAIKEN_LOCAL_CHAIN } from './config';
|
||||
export type { HarbWeb3Options } from './config';
|
||||
export { useTokenBalance } from './composables/useTokenBalance';
|
||||
|
||||
// Re-export commonly used wagmi composables so consumers don't need to import @wagmi/vue directly
|
||||
export { useAccount, useConnect, useDisconnect, useChainId } from '@wagmi/vue';
|
||||
Loading…
Add table
Add a link
Reference in a new issue