Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rework app asset info fetching #3480

Merged
merged 15 commits into from
Jan 9, 2025
22 changes: 12 additions & 10 deletions app/src/generated/graphql-env.d.ts

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<script lang="ts">
import type { Readable } from "svelte/store"
import type { ContextStore } from "$lib/components/TransferFrom/transfer/context.ts"
import { truncate } from "$lib/utilities/format.ts"
import { formatUnits } from "viem"
import { Button } from "$lib/components/ui/button"
import type { CubeFaces } from "$lib/components/TransferFrom/components/Cube/types.ts"
import type { RawIntentsStore } from "$lib/components/TransferFrom/transfer/raw-intents.ts"
import type { IntentsStore } from "$lib/components/TransferFrom/transfer/intents.ts"
import { derived, writable } from "svelte/store"

interface Props {
stores: {
Expand All @@ -21,43 +21,56 @@ export let rotateTo: Props["rotateTo"]

let { rawIntents, intents } = stores

$: sortedAssets = [...($intents.sourceAssets ?? [])].sort((a, b) => {
if (a.isSupported !== b.isSupported) {
return a.isSupported ? -1 : 1
}
return Number(b.balance.balance - a.balance.balance)
})
const showZeroBalances = writable(false)

$: filteredAssets = derived([intents, showZeroBalances], ([$intents, $showZeroBalances]) =>
$showZeroBalances
? $intents.sourceAssets
: $intents.sourceAssets.filter(asset => BigInt(asset.balance) > 0n)
)

function setAsset(address: string) {
rawIntents.updateField("asset", address)
function setAsset(denom: string) {
rawIntents.updateField("asset", denom)
rotateTo("intentFace")
}

function toggleZeroBalances() {
showZeroBalances.update(value => !value)
}
</script>

<div class="flex flex-col h-full w-full">
<div class="text-primary p-2 px-4 flex items-center justify-between border-b-2">
<span class="font-bold uppercase">Assets</span>
<div class="flex items-center gap-2">
<span class="font-bold uppercase">Assets</span>
<button
class="text-xs border px-2 py-1 rounded"
on:click={toggleZeroBalances}
>
{$showZeroBalances ? 'Hide' : 'Show'} Zero Balances
</button>
</div>
<button
class="border-2 h-6 w-6 flex items-center justify-center"
on:click={() => rotateTo("intentFace")}
>✕
</button>
</div>

{#if sortedAssets.length}
{#if $filteredAssets.length}
<div class="flex-1 overflow-y-auto">
{#each sortedAssets as asset}
{#each $filteredAssets as asset (asset)}
<div class="pb-2 flex flex-col justify-start">
<Button
variant="ghost"
class="px-4 py-2 w-full rounded-none flex justify-between items-center"
on:click={() => setAsset(asset.balance.address)}
on:click={() => setAsset(asset.metadata.denom)}
>
<div class:opacity-30={!asset.isSupported}>
{truncate(asset.symbol, 6)}
<div class:opacity-30={asset.metadata.metadata_level === "none"}>
{truncate(asset.metadata.display_symbol || asset.metadata.denom, 6)}
</div>
<p class:opacity-30={!asset.isSupported}>
{formatUnits(asset.balance.balance, asset.supportedAsset?.decimals ?? 0)}
<p class:opacity-30={asset.metadata.metadata_level === "none"}>
{formatUnits(BigInt(asset.balance), asset.metadata.decimals ?? 0)}
</p>
</Button>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,5 +100,4 @@ function toggleExpand(chainId: string) {
{/each}
</div>
</div>

</div>
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@
import Direction from "$lib/components/TransferFrom/components/Direction.svelte"
import SelectedAsset from "$lib/components/TransferFrom/components/SelectedAsset.svelte"
import type { Readable } from "svelte/store"
import type {
ValidationStore,
ValidationStoreAndMethods
} from "$lib/components/TransferFrom/transfer/validation.ts"
import type { ContextStore } from "$lib/components/TransferFrom/transfer/context.ts"
import type { ValidationStore } from "$lib/components/TransferFrom/transfer/validation.ts"
import { Button } from "$lib/components/ui/button"
import type { IntentsStore } from "$lib/components/TransferFrom/transfer/intents.ts"
import type { CubeFaces } from "$lib/components/TransferFrom/components/Cube/types.ts"
Expand Down Expand Up @@ -46,7 +42,7 @@ let { rawIntents, intents, validation } = stores
minlength={1}
maxlength={64}
required={true}
disabled={!$intents.selectedAsset.address}
disabled={!$intents.selectedAsset?.metadata.denom}
autocorrect="off"
placeholder="0.00"
spellcheck="false"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,10 @@ let transferState: Writable<TransferState> = writable({ kind: "PRE_TRANSFER" })
const transfer = async () => {
if (!$validation.isValid) return

let parsedAmount = parseUnits($validation.transfer.amount, $validation.transfer.asset.decimals)
let parsedAmount = parseUnits(
$validation.transfer.amount,
$validation.transfer.asset.metadata.decimals
)

/** --- APTOS START --- */
if ($validation.transfer.sourceChain.rpc_type === "aptos") {
Expand Down Expand Up @@ -109,7 +112,7 @@ const transfer = async () => {
receiver: $validation.transfer.receiver,
amount: parsedAmount,
authAccess: "wallet",
denomAddress: $validation.transfer.asset.address,
denomAddress: $validation.transfer.asset?.balance,
destinationChainId: $validation.transfer.destinationChain.chain_id as ChainId
} satisfies TransferAssetsParameters<"2">

Expand Down Expand Up @@ -201,18 +204,18 @@ const transfer = async () => {
account: cosmosOfflineSigner,
transport: http(`https://${rpcUrl}`),
chainId: $validation.transfer.sourceChain.chain_id as CosmosChainId,
gasPrice: { amount: "0.0025", denom: $validation.transfer.asset.address }
gasPrice: { amount: "0.0025", denom: $validation.transfer.asset.metadata.denom }
})

const transfer = await unionClient.transferAsset({
autoApprove: true,
receiver: $validation.transfer.receiver,
amount: parsedAmount,
denomAddress: $validation.transfer.asset.address,
denomAddress: $validation.transfer.asset.metadata.denom,
account: cosmosOfflineSigner,
// TODO: verify chain id is correct
destinationChainId: $validation.transfer.destinationChain.chain_id as ChainId,
gasPrice: { amount: "0.0025", denom: $validation.transfer.asset.address }
gasPrice: { amount: "0.0025", denom: $validation.transfer.asset.metadata.denom }
})
if (transfer.isErr()) throw transfer.error
transferState.set({ kind: "TRANSFERRING", transferHash: transfer.value })
Expand Down Expand Up @@ -273,7 +276,7 @@ const transfer = async () => {
const approve = await unionClient.approveTransaction({
amount: parsedAmount,
receiver: $validation.transfer.receiver,
denomAddress: getAddress($validation.transfer.asset.address),
denomAddress: getAddress($validation.transfer.asset.metadata.denom),
// TODO: verify chain id is correct
destinationChainId: $validation.transfer.destinationChain.chain_id as ChainId
})
Expand Down Expand Up @@ -334,7 +337,7 @@ const transfer = async () => {
autoApprove: false,
amount: parsedAmount,
receiver: $validation.transfer.receiver,
denomAddress: getAddress($validation.transfer.asset.address),
denomAddress: getAddress($validation.transfer.asset.metadata.denom),
destinationChainId: $validation.transfer.destinationChain.chain_id as ChainId
})
if (transfer.isErr()) throw transfer.error
Expand Down Expand Up @@ -387,10 +390,10 @@ const transfer = async () => {
transfer_day: toIsoString(new Date(Date.now())).split("T")[0],
receiver: $validation.transfer?.receiver,
assets: {
[$validation.transfer?.asset.address]: {
[$validation.transfer?.asset.metadata.denom]: {
info:
$validation.transfer?.sourceChain?.assets?.find(
d => d.denom === $validation.transfer?.asset.address
d => d.denom === $validation.transfer?.asset.metadata.denom
) ?? null,
amount: parsedAmount
}
Expand Down Expand Up @@ -643,7 +646,7 @@ let stepperSteps = derived(
</div>
<div class="flex justify-between">
<span>ASSET:</span>
<span>{truncate($validation.transfer.asset.address, 6)}</span>
<span>{truncate($validation.transfer.asset.metadata.denom, 6)}</span>
</div>
<div class="flex justify-between">
<span>AMOUNT:</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,13 @@ export let onSelectAsset: Props["onSelectAsset"]
class="border-2 font-bold"
on:click={onSelectAsset}
>
{$intents.selectedAsset.symbol ?
truncate($intents.selectedAsset.symbol, 18) :
$rawIntents.asset ? truncate($rawIntents.asset, 6) :
"Select Asset"}
{#if $intents.selectedAsset}
{truncate($intents.selectedAsset.metadata.display_symbol || $intents.selectedAsset.metadata.denom, 18)}
{:else if $rawIntents.asset}
{truncate($rawIntents.asset, 6)}
{:else}
Select Asset
{/if}
</Button>
{#if $validation.errors.asset}
<p class="text-red-500 text-sm">{$validation.errors.asset}</p>
Expand Down
21 changes: 8 additions & 13 deletions app/src/lib/components/TransferFrom/index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,14 @@ import Chains from "$lib/components/TransferFrom/components/Cube/faces/Chains.sv
import Assets from "$lib/components/TransferFrom/components/Cube/faces/Assets.svelte"
import Transfer from "$lib/components/TransferFrom/components/Cube/faces/Transfer.svelte"
import Cube from "$lib/components/TransferFrom/components/Cube/index.svelte"
import type { Chain, UserAddresses } from "$lib/types.ts"
import type { Chain } from "$lib/types.ts"
import { userBalancesQuery } from "$lib/queries/balance"
import { balanceStore, userAddress } from "$lib/components/TransferFrom/transfer/balances.ts"
import { userAddress, balanceStore } from "$lib/components/TransferFrom/transfer/balances.ts"

export let chains: Array<Chain>

$: userBalancesQuery({
chains,
userAddr: $userAddress,
connected: true
}).subscribe(x => {
balanceStore.set(x)
})
$: userBalancesQueries = userBalancesQuery({ chains, userAddr: $userAddress, connected: true })
$: balanceStore.set($userBalancesQueries.map(query => query.data || []))

const stores = createTransferStore(chains)
</script>
Expand All @@ -30,11 +25,11 @@ const stores = createTransferStore(chains)
</div>

<div slot="source" let:rotateTo class="w-full h-full">
<Chains {stores} {rotateTo} selected="source" />
<Chains {stores} {rotateTo} selected="source"/>
</div>

<div slot="destination" let:rotateTo class="w-full h-full">
<Chains {stores} {rotateTo} selected="destination" />
<Chains {stores} {rotateTo} selected="destination"/>
</div>

<div slot="assets" let:rotateTo class="w-full h-full">
Expand All @@ -48,6 +43,6 @@ const stores = createTransferStore(chains)

<div class="absolute bottom-0 inset-x-0 text-center py-2">
{#if TRANSFER_DEBUG}
<DebugBox {stores} />
<DebugBox {stores}/>
{/if}
</div>
</div>
7 changes: 3 additions & 4 deletions app/src/lib/components/TransferFrom/transfer/balances.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { derived, type Readable, writable } from "svelte/store"
import type { UserAddresses } from "$lib/types.ts"
import { userAddrCosmos } from "$lib/wallet/cosmos"
import { userAddrEvm } from "$lib/wallet/evm"
import { userAddressAptos } from "$lib/wallet/aptos"
import type { QueryObserverResult } from "@tanstack/query-core"
import type { BalanceResult } from "$lib/queries/balance"
import type { BalanceData } from "$lib/queries/balance"
import { derived, type Readable, writable } from "svelte/store"

export let userAddress: Readable<UserAddresses> = derived(
[userAddrCosmos, userAddrEvm, userAddressAptos],
Expand All @@ -15,4 +14,4 @@ export let userAddress: Readable<UserAddresses> = derived(
})
)

export const balanceStore = writable<Array<QueryObserverResult<Array<BalanceResult>, Error>>>()
export const balanceStore = writable<Array<Array<BalanceData>>>([])
62 changes: 22 additions & 40 deletions app/src/lib/components/TransferFrom/transfer/context.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,11 @@
import { derived, type Readable } from "svelte/store"
import type { Chain, UserAddresses } from "$lib/types"
import type { Address } from "$lib/wallet/types"
import { balanceStore, userAddress } from "./balances.ts"
import type { BalanceResult } from "$lib/queries/balance"
import type { QueryObserverResult } from "@tanstack/query-core"

export type BalanceRecord = {
balance: bigint
gasToken: boolean
address: Address
symbol: string
}
import type { BalanceData } from "$lib/queries/balance"

export type ChainBalances = {
chainId: string
balances: Array<BalanceRecord>
balances: Array<BalanceData>
}

export type BalancesList = Array<ChainBalances>
Expand All @@ -26,40 +17,31 @@ export interface ContextStore {
}

export function createContextStore(chains: Array<Chain>): Readable<ContextStore> {
const balances = derived(
balanceStore as Readable<Array<QueryObserverResult<Array<BalanceResult>, Error>>>,
$rawBalances => {
if ($rawBalances?.length === 0) {
return chains.map(chain => ({
chainId: chain.chain_id,
balances: []
}))
}
const balances = derived(balanceStore, ($rawBalances: Array<Array<BalanceData>>) => {
console.log("context", $rawBalances)
if ($rawBalances?.length === 0) {
return chains.map(chain => ({
chainId: chain.chain_id,
balances: []
}))
}

return chains.map((chain, chainIndex) => {
const balanceResult = $rawBalances[chainIndex]

if (!(balanceResult?.isSuccess && balanceResult.data)) {
console.log(`No balances fetched yet for chain ${chain.chain_id}`)
return {
chainId: chain.chain_id,
balances: []
}
}
return chains.map((chain, chainIndex) => {
const chainBalances = $rawBalances[chainIndex]

if (!chainBalances || chainBalances.length === 0) {
return {
chainId: chain.chain_id,
balances: balanceResult.data.map((balance: BalanceResult) => ({
...balance,
balance: BigInt(balance.balance),
gasToken: "gasToken" in balance ? (balance.gasToken ?? false) : false,
address: balance.address as Address,
symbol: balance.symbol || balance.address
}))
balances: []
}
})
}
) as Readable<BalancesList>
}

return {
chainId: chain.chain_id,
balances: chainBalances
}
})
}) as Readable<BalancesList>

return derived([userAddress, balances], ([$userAddress, $balances]) => ({
chains,
Expand Down
Loading
Loading