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

feat(app): make recipient editable with reset #2867

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions app/src/generated/graphql-env.d.ts

Large diffs are not rendered by default.

10 changes: 7 additions & 3 deletions app/src/lib/wallet/utilities/validate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,17 @@ export function isValidEvmAddress(address: unknown): address is EvmAddress {

export function isValidCosmosAddress(
address: unknown,
expectedPrefixes = ["union"]
expectedPrefixes: Array<string> | string = ["union"]
): address is CosmosAddress {
if (typeof address !== "string") return false

try {
const nromalized = normalizeBech32(address)
return expectedPrefixes.includes(nromalized.slice(0, nromalized.indexOf("1")))
const normalized = normalizeBech32(address)
const prefix = normalized.slice(0, normalized.indexOf("1"))

const prefixes = Array.isArray(expectedPrefixes) ? expectedPrefixes : [expectedPrefixes]

return prefixes.includes(prefix)
} catch (error) {
return false
}
Expand Down
18 changes: 10 additions & 8 deletions app/src/routes/transfer/(components)/chain-dialog.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,16 @@ export let userAddr: UserAddresses | null
$: document.body.style.overflow = dialogOpen ? "hidden" : "auto"

function selectChain(chain: { chain_id: string; display_name: string; rpc_type: string }) {
if (chain.rpc_type === "evm" && !userAddr?.evm) {
toast.info(`Connect EVM wallet`)
return
}
if (kind === "from") {
if (chain.rpc_type === "evm" && !userAddr?.evm) {
toast.info(`Connect EVM wallet`)
return
}

if (chain.rpc_type === "cosmos" && !userAddr?.cosmos) {
toast.info(`Connect Cosmos wallet`)
return
if (chain.rpc_type === "cosmos" && !userAddr?.cosmos) {
toast.info(`Connect Cosmos wallet`)
return
}
}
onChainSelect(chain.chain_id)
dialogOpen = false
Expand Down Expand Up @@ -80,7 +82,7 @@ function selectChain(chain: { chain_id: string; display_name: string; rpc_type:
<span class="text-lg font-bold">
{chain.display_name}
</span>
{#if (chain.rpc_type === "evm" && !userAddr?.evm) || (chain.rpc_type === "cosmos" && !userAddr?.cosmos) }
{#if ((chain.rpc_type === "evm" && !userAddr?.evm) || (chain.rpc_type === "cosmos" && !userAddr?.cosmos))}
<Badge variant={selected ? 'secondary' : 'default'}>Disconnected</Badge>
{:else}
<Badge variant={selected ? 'secondary' : 'default'}>Connected</Badge>
Expand Down
141 changes: 71 additions & 70 deletions app/src/routes/transfer/(components)/transfer-form.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import {
switchChain
} from "@wagmi/core"
import { sepolia, berachainTestnetbArtio, arbitrumSepolia, scrollSepolia } from "viem/chains"
import { isValidCosmosAddress, isValidEvmAddress } from "$lib/wallet/utilities/validate.ts"

function getChainById(chainId: number): ViemChain | null {
const chains: { [key: number]: ViemChain } = {
Expand Down Expand Up @@ -69,6 +70,7 @@ let fromChainId = writable("")
let toChainId = writable("")
let assetSymbol = writable("")
let assetAddress = writable("")
let receiver = writable("")

let transferState: Writable<TransferState> = writable({ kind: "PRE_TRANSFER" })

Expand Down Expand Up @@ -128,7 +130,7 @@ $: asset = derived(
}
)

let recipient = derived([toChain, userAddr], ([$toChain, $userAddr]) => {
let connectedWalletReceiver = derived([toChain, userAddr], ([$toChain, $userAddr]) => {
switch ($toChain?.rpc_type) {
case "evm": {
const evmAddr = $userAddr.evm
Expand All @@ -146,9 +148,9 @@ let recipient = derived([toChain, userAddr], ([$toChain, $userAddr]) => {
})
Swepool marked this conversation as resolved.
Show resolved Hide resolved

let ucs01Configuration = derived(
[fromChain, toChainId, recipient],
([$fromChain, $toChainId, $recipient]) => {
if ($fromChain === null || $toChainId === null || $recipient === null) return null
[fromChain, toChainId, receiver],
([$fromChain, $toChainId, $receiver]) => {
if ($fromChain === null || $toChainId === null || $receiver === null) return null

let ucs1_configuration =
$toChainId in $fromChain.ucs1_configurations
Expand All @@ -175,8 +177,8 @@ let ucs01Configuration = derived(
let forwardConfig = ucs1_configuration.forwards[$toChainId]
pfmMemo = generatePfmMemo(
forwardConfig.channel_id,
forwardConfig.port_id,
$toChain?.rpc_type === "evm" ? $recipient.slice(2) : $recipient
forwardConfig.port,
$toChain?.rpc_type === "evm" ? $receiver.slice(2) : $receiver
)
break
}
Expand Down Expand Up @@ -233,7 +235,9 @@ const transfer = async () => {
if ($fromChain.rpc_type === "evm" && !$userAddr.evm) return toast.error("No evm wallet connected")
if ($fromChain.rpc_type === "cosmos" && !$userAddr.cosmos)
return toast.error("No cosmos wallet connected")
if (!$recipient) return toast.error("Invalid recipient")

if (!$receiver) return toast.error("Invalid connectedWalletReceiver")

if (!$ucs01Configuration)
return toast.error(
`No UCS01 configuration for ${$fromChain.display_name} -> ${$toChain.display_name}`
Expand Down Expand Up @@ -329,7 +333,7 @@ const transfer = async () => {
let transferAssetsMessage: Parameters<UnionClient["transferAssets"]>[0]
console.log({ ucs1_configuration })
if (ucs1_configuration.contract_address === "ics20") {
console.log({ $recipient })
console.log({ $receiver })
transferAssetsMessage = {
kind: "ibc",
messageTransfers: [
Expand All @@ -338,7 +342,7 @@ const transfer = async () => {
sourceChannel: ucs1_configuration.channel_id,
token: { denom: $assetAddress, amount: parsedAmount.toString() },
sender: rawToBech32($fromChain.addr_prefix, $userAddrCosmos.bytes),
receiver: $recipient,
receiver: $receiver,
memo: pfmMemo ?? "",
timeoutHeight: { revisionHeight: 888888888n, revisionNumber: 8n }
}
Expand All @@ -354,7 +358,7 @@ const transfer = async () => {
msg: {
transfer: {
channel: ucs1_configuration.channel_id,
receiver: $toChain.rpc_type === "evm" ? $recipient?.slice(2) : $recipient,
receiver: $toChain.rpc_type === "evm" ? $receiver?.slice(2) : $receiver,
memo: pfmMemo ?? ""
}
},
Expand Down Expand Up @@ -554,7 +558,7 @@ const transfer = async () => {
? $userAddrCosmos?.normalized
: $userAddrEvm?.normalized,
transfer_day: toIsoString(new Date(Date.now())).split("T")[0],
receiver: $recipient,
receiver: $receiver,
assets: {
[$assetSymbol]: {
info: $fromChain?.assets?.find(d => d.denom === $assetSymbol) ?? null,
Expand Down Expand Up @@ -846,24 +850,32 @@ let stepperSteps = derived([fromChain, transferState], ([$fromChain, $transferSt
raise("trying to make stepper for unsupported chain")
})

let inputState: "locked" | "unlocked" = "locked"

let userInput = false
$: address = $recipient ?? ""
let userInput = writable(false)

$: if (!userInput && $recipient !== address) {
address = $recipient ?? ""
$: if (!$userInput) {
$receiver = $connectedWalletReceiver ?? ""
}

const handleInput = (event: Event) => {
address = (event.target as HTMLInputElement).value
userInput = true
receiver.set((event.target as HTMLInputElement).value)
userInput.set(true)
}

const resetInput = () => {
userInput = false
address = $recipient ?? ""
userInput.set(false)
receiver.set($connectedWalletReceiver ?? "")
}

const addressIsValid = derived([receiver, toChain], ([$receiver, $toChain]) => {
if (!$toChain) return
if ($toChain.rpc_type === "cosmos") {
return isValidCosmosAddress($receiver, $toChain.addr_prefix)
}
if ($toChain.rpc_type === "evm") {
return isValidEvmAddress($receiver)
}
return false
})
</script>

<div
Expand Down Expand Up @@ -925,8 +937,43 @@ const resetInput = () => {
</div>
{/if}
</section>

<section>
<section>
<CardSectionHeading>Receiver</CardSectionHeading>
<div class="flex items-start gap-2">
<div class="w-full">
<div class="relative w-full mb-2">
<Input
autocapitalize="none"
autocomplete="off"
autocorrect="off"
bind:value={$receiver}
class={cn(
"disabled:bg-black/30",
$receiver && $toChain && !$addressIsValid? 'border-red-500' : ""
)}
id="address"
on:input={handleInput}
placeholder="Enter receiver's address"
required={true}
spellcheck="false"
type="text"
/>
</div>
<div class="flex justify-between px-1">
{#if $userInput}
<button
type="button"
on:click={resetInput}
class="text-xs text-muted-foreground hover:text-primary transition"
>
{$connectedWalletReceiver ? 'Reset to connected wallet' : 'Reset'}
</button>
{/if}
</div>
</div>
</div>
</section>
<section>
<CardSectionHeading>Amount</CardSectionHeading>
<Input
autocapitalize="none"
Expand All @@ -947,59 +994,13 @@ const resetInput = () => {
spellcheck="false"
/>
</section>
<section>
<CardSectionHeading>Recipient</CardSectionHeading>
<div class="flex items-start gap-2">
<div class="w-full">
<div class="relative w-full mb-2">
<Input
autocapitalize="none"
autocomplete="off"
autocorrect="off"
bind:value={address}
class="disabled:bg-black/30"
disabled={inputState === 'locked'}
id="address"
on:input={handleInput}
placeholder="Select chain"
required={true}
spellcheck="false"
type="text"
/>
</div>
<div class="flex justify-between px-1">
{#if userInput}
<button
type="button"
on:click={resetInput}
class="text-xs text-muted-foreground hover:text-primary transition"
>
Reset
</button>
{/if}
</div>
</div>
<!-- <Button-->
<!-- aria-label="Toggle address lock"-->
<!-- class="px-3"-->
<!-- on:click={onLockClick}-->
<!-- variant="ghost"-->
<!-- >-->
<!-- {#if inputState === 'locked'}-->
<!-- <LockLockedIcon class="size-4.5"/>-->
<!-- {:else}-->
<!-- <LockOpenIcon class="size-4.5"/>-->
<!-- {/if}-->
<!-- </Button>-->
</div>
</section>
</Card.Content>
<Card.Footer class="flex flex-col gap-4 items-start">
<Button
disabled={!amount ||
!$asset ||
!$addressIsValid ||
!$toChainId ||
!$recipient ||
!$assetSymbol ||
!$fromChainId ||
!amountLargerThanZero ||
Expand Down