fix: Generic utilities (isRecord, coerceString, getErrorMessage, ensureAddress) have no shared home (#363)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
e53591de9d
commit
59ae30bb37
6 changed files with 63 additions and 35 deletions
13
package-lock.json
generated
13
package-lock.json
generated
|
|
@ -3360,6 +3360,10 @@
|
||||||
"resolved": "packages/ui-shared",
|
"resolved": "packages/ui-shared",
|
||||||
"link": true
|
"link": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@harb/utils": {
|
||||||
|
"resolved": "packages/utils",
|
||||||
|
"link": true
|
||||||
|
},
|
||||||
"node_modules/@harb/web3": {
|
"node_modules/@harb/web3": {
|
||||||
"resolved": "packages/web3",
|
"resolved": "packages/web3",
|
||||||
"link": true
|
"link": true
|
||||||
|
|
@ -19332,10 +19336,18 @@
|
||||||
"vue": "^3.5.0"
|
"vue": "^3.5.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"packages/utils": {
|
||||||
|
"name": "@harb/utils",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": {
|
||||||
|
"viem": "^2.22.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
"packages/web3": {
|
"packages/web3": {
|
||||||
"name": "@harb/web3",
|
"name": "@harb/web3",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@harb/utils": "*",
|
||||||
"@wagmi/vue": "^0.2.8",
|
"@wagmi/vue": "^0.2.8",
|
||||||
"viem": "^2.22.13"
|
"viem": "^2.22.13"
|
||||||
},
|
},
|
||||||
|
|
@ -19347,6 +19359,7 @@
|
||||||
"name": "harb-staking",
|
"name": "harb-staking",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@harb/utils": "*",
|
||||||
"@harb/web3": "*",
|
"@harb/web3": "*",
|
||||||
"@tanstack/vue-query": "^5.64.2",
|
"@tanstack/vue-query": "^5.64.2",
|
||||||
"@vue/test-utils": "^2.4.6",
|
"@vue/test-utils": "^2.4.6",
|
||||||
|
|
|
||||||
11
packages/utils/package.json
Normal file
11
packages/utils/package.json
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
{
|
||||||
|
"name": "@harb/utils",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"private": true,
|
||||||
|
"type": "module",
|
||||||
|
"main": "src/index.ts",
|
||||||
|
"types": "src/index.ts",
|
||||||
|
"dependencies": {
|
||||||
|
"viem": "^2.22.13"
|
||||||
|
}
|
||||||
|
}
|
||||||
34
packages/utils/src/index.ts
Normal file
34
packages/utils/src/index.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
import { getAddress, isAddress, type Address } from 'viem';
|
||||||
|
|
||||||
|
export function isRecord(value: unknown): value is Record<string, unknown> {
|
||||||
|
return typeof value === 'object' && value !== null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function coerceString(value: unknown): string | null {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
const trimmed = value.trim();
|
||||||
|
if (trimmed.length > 0) return trimmed;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getErrorMessage(error: unknown, fallback: string): string {
|
||||||
|
if (error instanceof Error) {
|
||||||
|
const msg = coerceString(error.message);
|
||||||
|
if (msg) return msg;
|
||||||
|
}
|
||||||
|
if (isRecord(error)) {
|
||||||
|
const short = coerceString(error.shortMessage);
|
||||||
|
if (short) return short;
|
||||||
|
const msg = coerceString(error.message);
|
||||||
|
if (msg) return msg;
|
||||||
|
}
|
||||||
|
return fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ensureAddress(value: string, label: string): Address {
|
||||||
|
if (!value || !isAddress(value)) {
|
||||||
|
throw new Error(`${label} is not a valid address`);
|
||||||
|
}
|
||||||
|
return getAddress(value);
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"types": "src/index.ts",
|
"types": "src/index.ts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@harb/utils": "*",
|
||||||
"@wagmi/vue": "^0.2.8",
|
"@wagmi/vue": "^0.2.8",
|
||||||
"viem": "^2.22.13"
|
"viem": "^2.22.13"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@
|
||||||
"vue-router": "^4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"vue-tippy": "^6.6.0",
|
"vue-tippy": "^6.6.0",
|
||||||
"vue-toastification": "^2.0.0-rc.5",
|
"vue-toastification": "^2.0.0-rc.5",
|
||||||
"@harb/web3": "*"
|
"@harb/web3": "*",
|
||||||
|
"@harb/utils": "*"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@iconify/vue": "^4.3.0",
|
"@iconify/vue": "^4.3.0",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
import { useAccount } from '@wagmi/vue';
|
import { useAccount } from '@wagmi/vue';
|
||||||
import { readContract, writeContract } from '@wagmi/core';
|
import { readContract, writeContract } from '@wagmi/core';
|
||||||
import { erc20Abi, getAddress, isAddress, maxUint256, parseEther, zeroAddress, type Abi, type Address } from 'viem';
|
import { erc20Abi, maxUint256, parseEther, zeroAddress, type Abi } from 'viem';
|
||||||
import { useToast } from 'vue-toastification';
|
import { useToast } from 'vue-toastification';
|
||||||
import { config as wagmiConfig } from '@/wagmi';
|
import { config as wagmiConfig } from '@/wagmi';
|
||||||
import { getChain, DEFAULT_CHAIN_ID } from '@/config';
|
import { getChain, DEFAULT_CHAIN_ID } from '@/config';
|
||||||
import { useWallet } from '@/composables/useWallet';
|
import { useWallet } from '@/composables/useWallet';
|
||||||
|
import { getErrorMessage, ensureAddress } from '@harb/utils';
|
||||||
|
|
||||||
export const WETH_ABI = [
|
export const WETH_ABI = [
|
||||||
{
|
{
|
||||||
|
|
@ -89,39 +90,6 @@ export const UNISWAP_POOL_ABI = [
|
||||||
},
|
},
|
||||||
] as const satisfies Abi;
|
] as const satisfies Abi;
|
||||||
|
|
||||||
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
||||||
return typeof value === 'object' && value !== null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function coerceString(value: unknown): string | null {
|
|
||||||
if (typeof value === 'string') {
|
|
||||||
const trimmed = value.trim();
|
|
||||||
if (trimmed.length > 0) return trimmed;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getErrorMessage(error: unknown, fallback: string): string {
|
|
||||||
if (error instanceof Error) {
|
|
||||||
const msg = coerceString(error.message);
|
|
||||||
if (msg) return msg;
|
|
||||||
}
|
|
||||||
if (isRecord(error)) {
|
|
||||||
const short = coerceString(error.shortMessage);
|
|
||||||
if (short) return short;
|
|
||||||
const msg = coerceString(error.message);
|
|
||||||
if (msg) return msg;
|
|
||||||
}
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function ensureAddress(value: string, label: string): Address {
|
|
||||||
if (!value || !isAddress(value)) {
|
|
||||||
throw new Error(`${label} is not a valid address`);
|
|
||||||
}
|
|
||||||
return getAddress(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useSwapKrk() {
|
export function useSwapKrk() {
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
const { address, chainId } = useAccount();
|
const { address, chainId } = useAccount();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue