Skip to content

Commit

Permalink
feat(app): working balances queries on start page
Browse files Browse the repository at this point in the history
  • Loading branch information
cor committed Jun 7, 2024
1 parent 7d83e8c commit 3b144a0
Show file tree
Hide file tree
Showing 7 changed files with 239 additions and 143 deletions.
2 changes: 1 addition & 1 deletion app/app.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
{
packages = {
app = unstablePkgs.buildNpmPackage {
npmDepsHash = "sha256-P5e1Phv2SiSg7ferB3H4+e/6Szw6XfEF1yKVxp+e864=";
npmDepsHash = "sha256-JJH1vqXzv7IYw2SEVJFqHydvlGXdtPvfb/PazNsZqv4=";
src = ./.;
sourceRoot = "app";
npmFlags = [ "--legacy-peer-deps" ];
Expand Down
192 changes: 99 additions & 93 deletions app/package-lock.json

Large diffs are not rendered by default.

40 changes: 20 additions & 20 deletions app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@
"@leapwallet/cosmos-snap-provider": "^0.1.26",
"@tanstack/match-sorter-utils": "^8.15.1",
"@tanstack/query-sync-storage-persister": "^5.40.0",
"@tanstack/svelte-query": "^5.40.0",
"@tanstack/svelte-query-persist-client": "^5.40.0",
"@tanstack/svelte-query": "^5.40.1",
"@tanstack/svelte-query-persist-client": "^5.40.1",
"@tanstack/svelte-table": "^8.17.3",
"@tanstack/svelte-virtual": "^3.5.0",
"@union/client": "npm:@jsr/union__client@^0.0.1-rc.10",
"@wagmi/connectors": "^5.0.7",
"@tanstack/svelte-virtual": "^3.5.1",
"@union/client": "npm:@jsr/union__client@^0.0.1-rc.17",
"@wagmi/connectors": "^5.0.8",
"@wagmi/core": "^2.10.5",
"bits-ui": "^0.21.10",
"cmdk-sv": "^0.0.17",
Expand All @@ -36,27 +36,27 @@
"paneforge": "^0.0.4",
"svelte-french-toast": "^1.2.0",
"svelte-legos": "^0.2.3",
"svelte-persisted-store": "^0.9.4",
"svelte-persisted-store": "^0.11.0",
"svelte-radix": "^1.1.0",
"svelte-ux": "^0.65.0",
"svelte-ux": "^0.66.5",
"sveltekit-superforms": "^2.14.0",
"uint8array-extras": "^1.1.0",
"valibot": "^0.30.0",
"valibot": "^0.31.0",
"vaul-svelte": "^0.3.1",
"viem": "^2.13.1"
"viem": "^2.13.7"
},
"devDependencies": {
"@0no-co/graphqlsp": "^1.12.5",
"@cosmjs/tendermint-rpc": "0.32.3",
"@iconify-json/fa6-solid": "^1.1.21",
"@iconify-json/logos": "^1.1.42",
"@iconify-json/lucide": "^1.1.188",
"@iconify-json/logos": "^1.1.43",
"@iconify-json/lucide": "^1.1.190",
"@iconify-json/mdi": "^1.1.66",
"@iconify-json/tabler": "^1.1.113",
"@keplr-wallet/types": "^0.12.96",
"@keplr-wallet/types": "^0.12.98",
"@leapwallet/types": "^0.0.5",
"@melt-ui/pp": "^0.3.2",
"@melt-ui/svelte": "^0.80.0",
"@melt-ui/svelte": "^0.81.0",
"@svelte-put/shortcut": "^3.1.1",
"@sveltejs/adapter-static": "^3.0.1",
"@sveltejs/kit": "^2.5.10",
Expand All @@ -65,22 +65,22 @@
"@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/forms": "^0.5.7",
"@tailwindcss/typography": "^0.5.13",
"@tanstack/svelte-query-devtools": "^5.40.0",
"@tanstack/svelte-query-devtools": "^5.40.1",
"@total-typescript/ts-reset": "^0.5.1",
"@types/node": "^20.12.13",
"@types/node": "^20.14.2",
"@types/postcss-import": "^14.0.3",
"autoprefixer": "^10.4.19",
"buffer": "^6.0.3",
"clsx": "^2.1.1",
"fluid-tailwind": "^0.3.8",
"fluid-tailwind": "^0.3.9",
"graphql": "^16.8.1",
"jsr": "^0.12.4",
"patch-package": "^8.0.0",
"postcss": "^8.4.38",
"postcss-import": "^16.1.0",
"process": "^0.11.10",
"rollup-plugin-visualizer": "^5.12.0",
"svelte": "^4.2.17",
"svelte": "^4.2.18",
"svelte-check": "^3.8.0",
"svelte-preprocess": "^5.1.4",
"sveltekit-flash-message": "^2.4.4",
Expand All @@ -89,10 +89,10 @@
"tailwind-merge": "^2.3.0",
"tailwind-scrollbar": "^3.1.0",
"tailwind-variants": "^0.2.1",
"tailwindcss": "^3.4.3",
"tailwindcss": "^3.4.4",
"tailwindcss-animate": "^1.0.7",
"tslib": "^2.6.2",
"tsx": "^4.11.0",
"tslib": "^2.6.3",
"tsx": "^4.12.0",
"typed-query-selector": "^2.11.2",
"typescript": "^5.4.5",
"unplugin-icons": "^0.19.0",
Expand Down
55 changes: 38 additions & 17 deletions app/src/lib/queries/balance.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import * as v from "valibot"
import { KEY } from "$lib/constants/keys.ts"
import { CHAIN_URLS } from "$lib/constants";
import { formatUnits, type Address } from "viem"
import type { Address } from "viem"
import { getEvmTokensInfo } from "./token-info.ts"
import { createQuery } from "@tanstack/svelte-query"
import type { ChainId } from "$/lib/constants/assets.ts"
Expand Down Expand Up @@ -39,17 +39,17 @@ const evmBalancesResponseSchema = v.object({
jsonrpc: v.string(),
id: v.number(),
result: v.object({
address: v.string([v.length(42)]),
address: v.pipe(v.string(), v.length(42)),
tokenBalances: v.array(
v.object({
contractAddress: v.string([v.length(42)]),
contractAddress: v.pipe(v.string(), v.length(42)),
tokenBalance: v.string()
})
)
})
})

export type EvmBalances = v.Output<typeof evmBalancesResponseSchema>
export type EvmBalances = v.InferOutput<typeof evmBalancesResponseSchema>

/**
* @docs https://docs.alchemy.com/reference/alchemy-gettokenbalances
Expand All @@ -67,7 +67,7 @@ export function evmBalancesQuery({
queryKey: ["balances", chainId, address],
enabled: isValidEvmAddress(address),
refetchOnWindowFocus: false,
refetchInterval: 10_000,
refetchInterval: 2_000,
queryFn: async () => {
const assetsToCheck =
"contractAddresses" in restParams && Array.isArray(restParams.contractAddresses)
Expand All @@ -77,6 +77,7 @@ export function evmBalancesQuery({
? restParams.tokenSpecification // if tokenSpecification is a string, use it
: "DEFAULT_TOKENS"


let json: undefined | unknown;

try {
Expand Down Expand Up @@ -112,6 +113,13 @@ export function evmBalancesQuery({
})
}

const cosmosBalancesResponseSchema = v.object({
balances: v.array(v.object({
denom: v.string(),
amount: v.string()
}))
});

export function cosmosBalancesQuery({
address,
chainId
Expand All @@ -124,19 +132,32 @@ export function cosmosBalancesQuery({
enabled: isValidCosmosAddress(address),
refetchOnWindowFocus: false,
queryFn: async () => {
const restUrl = CHAIN_URLS[chainId].REST
const response = await fetch(
`${restUrl}/cosmos/bank/v1beta1/balances/${address}`,
{});
const restUrl = CHAIN_URLS[chainId].REST

let json: undefined | unknown;
try {
const response = await fetch(`${restUrl}/cosmos/bank/v1beta1/balances/${address}`);

if (!response.ok) return new Error("invalid response");
return (await response.json()).balances.map((x) => {
return {
address: x.denom,
symbol: x.denom,
balance: x.amount,
decimals: 0
}
})

json = await response.json()
} catch(err) {
if (err instanceof Error) {
raise(`error fetching balances from /cosmos/bank: ${err.message}`);
}
raise(`unknown error while fetching from /cosmos/bank: ${JSON.stringify(err)}`);
}

const result = v.safeParse(cosmosBalancesResponseSchema, json);

if (!result.success) raise(`error parsing result ${JSON.stringify(result.issues)}`);

return result.output.balances.map((x) => ({
address: x.denom,
symbol: x.denom,
balance: x.amount,
decimals: 0
}))
}
})
}
79 changes: 71 additions & 8 deletions app/src/routes/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
<script lang="ts">
import * as Card from "$lib/components/ui/card/index.ts"
import { sepoliaStore } from "$lib/wallet/evm/config.ts"
import { cosmosStore } from "$lib/wallet/cosmos"
import AlphaNotice from "$lib/components/alpha-notice.svelte";
import { summarizeString } from "$lib/utilities/format";
import * as Card from "$lib/components/ui/card/index.ts"
import { cosmosBalancesQuery, evmBalancesQuery } from '$lib/queries/balance'
import { sepoliaStore } from "$lib/wallet/evm/config.ts"
import { cosmosStore } from "$lib/wallet/cosmos"
import { summarizeString } from '$lib/utilities/format';
let evmBalances: null | ReturnType<typeof evmBalancesQuery>;
$: if($sepoliaStore.address) evmBalances = evmBalancesQuery({
chainId: '11155111',
address: $sepoliaStore.address,
tokenSpecification: 'erc20',
})
let cosmosBalances: null | ReturnType<typeof cosmosBalancesQuery>;
$: if ($cosmosStore.address) cosmosBalances = cosmosBalancesQuery({
chainId: 'union-testnet-8',
address: $cosmosStore.address
})
</script>

<main class="flex flex-col items-center size-full p-4 mt-16">
<Card.Root class="max-w-lg">
<main class="flex flex-col items-center w-full p-4 mt-16 gap-6">
<Card.Root class="max-w-lg size-full">
<Card.Header>
<Card.Title>Welcome to Union</Card.Title>
</Card.Header>
Expand All @@ -25,11 +39,60 @@ import { cosmosStore } from "$lib/wallet/cosmos"

<div>
{#if $cosmosStore.address }
✅Cosmos wallet connected
Cosmos wallet <span class="font-mono">{summarizeString($cosmosStore.address, 6)}</span> connected
{:else}
Connect cosmos wallet
{/if}
</div>
</Card.Content>
</Card.Root>

<Card.Root class="max-w-lg w-full">
<Card.Header>
<Card.Title>Balances</Card.Title>
</Card.Header>
<Card.Content class="flex flex-col gap-2">
<h2 class="font-bold">EVM</h2>
{#if $evmBalances}
{#if $evmBalances.isLoading}
Loading...
{:else if $evmBalances.isError}
Error: {$evmBalances.error.message}
{:else if $evmBalances.isSuccess}
<div>
{#each $evmBalances.data as asset}
<div>{summarizeString(asset.symbol, 8)} | {asset.balance}</div>
{/each}
</div>
{/if}
{:else}
<p>Connect your EVM wallet to continue</p>
{/if}

<h2 class="font-bold">Cosmos</h2>
{#if $cosmosBalances}
{#if $cosmosBalances.isLoading}
Loading...
{:else if $cosmosBalances.isError}
{$cosmosBalances.error.message}
{:else if $cosmosBalances.isSuccess}
<div>
{#each $cosmosBalances.data as asset}
<div>{summarizeString(asset.symbol, 8)} | {asset.balance}</div>
{/each}
</div>
{/if}
{:else}
<p>Connect your cosmos wallet to show cosmos balance</p>
{/if}
</Card.Content>
</Card.Root>





</main>



6 changes: 5 additions & 1 deletion app/src/routes/balance/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,11 @@
{:else if $cosmosBalances.isError}
{$cosmosBalances.error.message}
{:else if $cosmosBalances.isSuccess}
<pre>{JSON.stringify($cosmosBalances.data)}</pre>
<div>
{#each $cosmosBalances.data as asset}
<div>{summarizeString(asset.symbol, 4)} | {asset.balance}</div>
{/each}
</div>
{/if}
{:else}
<p>Connect your cosmos wallet to continue</p>
Expand Down
8 changes: 5 additions & 3 deletions app/src/routes/faucet/schema.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { string, regex, object, type Input } from "valibot"
import { string, regex, object, pipe, type InferOutput } from "valibot"

export const unionAddressRegex = /^union[a-z0-9]{39}$/

export const faucetFormSchema = object({
address: string([regex(unionAddressRegex, "Invalid Union address")])
address: pipe(string(), regex(unionAddressRegex, "Invalid Union address"))
})

export type FaucetSchema = typeof faucetFormSchema
export type FaucetForm = Input<typeof faucetFormSchema>
export type FaucetForm = InferOutput<typeof faucetFormSchema>

export type Message = { status: "error" | "success" | "warning"; text: string }


0 comments on commit 3b144a0

Please sign in to comment.