Skip to content

Commit 4f1aa36

Browse files
committed
fix: fix issues
1 parent bcb99f7 commit 4f1aa36

File tree

12 files changed

+223
-61
lines changed

12 files changed

+223
-61
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ opt-level = 's'
1010

1111
[workspace.package]
1212
edition = "2024"
13-
version = "0.3.1"
13+
version = "0.3.2"
1414
repository = "https://github.com/ldclabs/ic-one-bridge"
1515
keywords = ["canister", "icp", "bridge", "erc20", "icrc"]
1616
categories = ["web-programming"]

src/one_bridge_app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
"test": "vitest run"
1212
},
1313
"type": "module",
14-
"version": "0.1.0",
14+
"version": "0.3.0",
1515
"dependencies": {
1616
"@dfinity/agent": "^3.3.0",
1717
"@dfinity/auth-client": "^3.3.0",

src/one_bridge_app/src/lib/canisters/bridge.svelte.ts

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ export class BridgeCanisterAPI {
7070
return this.#tokenDisplay
7171
}
7272

73+
getTokenUrl(chain: string): [string, string] {
74+
if (!this.#state) return ['', '']
75+
if (chain === 'ICP') {
76+
const token = this.#state.token_ledger.toText()
77+
return [token, `https://dashboard.internetcomputer.org/canister/${token}`]
78+
}
79+
const contract = this.#state.evm_token_contracts.find(
80+
([name, _]) => name === chain
81+
)?.[1][0]
82+
if (!contract) return ['', '']
83+
switch (chain) {
84+
case 'BNB':
85+
return [contract, `https://bscscan.com/token/${contract}`]
86+
default:
87+
return ['', '']
88+
}
89+
}
90+
7391
toIcpAmount(chain: string, evmBalance: bigint): bigint {
7492
if (!this.#state) return evmBalance
7593
const evmDecimals = this.#state.evm_token_contracts.find(
@@ -372,7 +390,7 @@ export class BridgingProgress {
372390
if (this.#log.error.length > 0) {
373391
return `${this.#log.error[0]}`
374392
}
375-
if (this.#log.to_tx.length > 0) {
393+
if (isFinalized(this.#log.from_tx)) {
376394
return `waiting for confirmation on ${getChainName(this.#log.to)}`
377395
}
378396
return `waiting for confirmation on ${getChainName(this.#log.from)}`

src/one_bridge_app/src/lib/components/BridgeCard.svelte

Lines changed: 100 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
} from '$lib/canisters/bridge.svelte'
77
import ArrowLeftRightLine from '$lib/icons/arrow-left-right-line.svelte'
88
import ArrowRightUpLine from '$lib/icons/arrow-right-up-line.svelte'
9+
import RefreshLine from '$lib/icons/refresh-line.svelte'
910
import { authStore } from '$lib/stores/auth.svelte'
1011
import { toastRun } from '$lib/stores/toast.svelte'
1112
import type { Chain } from '$lib/types/bridge'
@@ -16,6 +17,7 @@
1617
} from '$lib/utils/helper'
1718
import { type TokenInfo } from '$lib/utils/token'
1819
import { tick } from 'svelte'
20+
import Spinner from '../ui/Spinner.svelte'
1921
import TextClipboardButton from '../ui/TextClipboardButton.svelte'
2022
import NetworkSelector from './ChainSelector.svelte'
2123
import PrimaryButton from './PrimaryButton.svelte'
@@ -145,6 +147,7 @@
145147
fromAmount = undefined
146148
error = null
147149
bridgingProgress = null
150+
refreshMyTokenInfo()
148151
}
149152
150153
function validateSendAmount(event: Event) {
@@ -210,7 +213,7 @@
210213
}
211214
}
212215
213-
async function refreshMyTokenInfo() {
216+
async function refreshMyTokenInfo(all: boolean = false) {
214217
await tick()
215218
216219
if (
@@ -229,6 +232,18 @@
229232
230233
try {
231234
isLoading = true
235+
236+
if (all) {
237+
await mainBridge.refreshState()
238+
if (selectedBridge !== mainBridge) {
239+
await selectedBridge.refreshState()
240+
}
241+
242+
const subBridges = await mainBridge.loadSubBridges()
243+
bridges = [mainBridge, ...subBridges]
244+
supportTokens = bridges.map((b) => b.token!)
245+
}
246+
232247
const icp = await selectedBridge.loadICPTokenAPI()
233248
switch (fromChain.name) {
234249
case 'ICP':
@@ -269,6 +284,7 @@
269284
if (bridge) {
270285
selectedBridge = bridge
271286
}
287+
refreshMyTokenInfo()
272288
}
273289
274290
async function onSwapChains() {
@@ -329,6 +345,11 @@
329345
localStorage.setItem('defaultToken', selectedBridge.token.symbol)
330346
localStorage.setItem('defaultFrom', fromChain.name)
331347
localStorage.setItem('defaultTo', toChain.name)
348+
349+
refreshMyTokenInfo()
350+
setTimeout(() => {
351+
refreshMyTokenInfo()
352+
}, 5000)
332353
} catch (err) {
333354
isBridging = false
334355
throw err
@@ -341,19 +362,37 @@
341362
class="space-y-6 rounded-xl border border-white/10 bg-[#131721]/80 p-6 pb-10 text-white/90 shadow-2xl backdrop-blur"
342363
>
343364
{#key bridgeCanister}
365+
<button
366+
title="Refresh state"
367+
class="absolute top-2 right-4 rounded-full bg-white/10 p-1 text-white/60 hover:bg-white/20 hover:text-white/80"
368+
onclick={() => refreshMyTokenInfo(true)}
369+
disabled={isLoading}
370+
>
371+
{#if isLoading}
372+
<Spinner class="size-5 text-white" />
373+
{:else}
374+
<span class=" *:size-5"><RefreshLine /></span>
375+
{/if}
376+
</button>
344377
{#if myIcpAddress && myEvmAddress}
345-
<div class="mb-3 flex flex-col gap-1 text-sm text-white/90">
378+
<div class="mb-3 flex flex-col gap-1 text-sm text-white/80">
346379
<p class="mb-1 text-white/60">Your address</p>
347380
<p class="flex items-center gap-1">
348381
{#key myIcpAddress}
349382
<span>ICP: {pruneAddress(myIcpAddress, true)}</span>
350-
<TextClipboardButton value={myIcpAddress} class="*:size-5" />
383+
<TextClipboardButton
384+
value={myIcpAddress}
385+
class="text-white/60 *:size-5 hover:text-white/80"
386+
/>
351387
{/key}
352388
</p>
353389
<p class="flex items-center gap-1">
354390
{#key myEvmAddress}
355391
<span>EVM: {pruneAddress(myEvmAddress, true)}</span>
356-
<TextClipboardButton value={myEvmAddress} class="*:size-5" />
392+
<TextClipboardButton
393+
value={myEvmAddress}
394+
class="text-white/60 *:size-5 hover:text-white/80"
395+
/>
357396
{/key}
358397
</p>
359398
</div>
@@ -367,14 +406,15 @@
367406
{onSelectToken}
368407
tokens={supportTokens}
369408
/>
370-
{#if selectedToken}
409+
{#if selectedBridge}
371410
<a
372411
class="flex items-center gap-1 text-sm font-medium text-white/60"
373412
title="View token ledger canister"
374-
href="https://dashboard.internetcomputer.org/canister/{selectedToken.canisterId}"
413+
href="https://dashboard.internetcomputer.org/canister/{selectedBridge.canisterId.toText()}"
375414
target="_blank"
376415
>
377-
<span>{pruneCanister(selectedToken.canisterId)}</span>
416+
<span>Bridge</span>
417+
<span>{pruneCanister(selectedBridge.canisterId.toText())}</span>
378418
<span class="*:size-4"><ArrowRightUpLine /></span>
379419
</a>
380420
{/if}
@@ -384,7 +424,25 @@
384424
<div class="grid grid-cols-[1fr_32px_1fr] items-center gap-0">
385425
<!-- From Section -->
386426
<div class="">
387-
<p class="mb-1 text-sm text-white/60">From</p>
427+
<p class="mb-1 flex items-center gap-2 text-sm text-white/60">
428+
<span>From</span>
429+
{#if selectedBridge && fromChain}
430+
{@const [token, tokenUrl] = selectedBridge.getTokenUrl(
431+
fromChain.name
432+
)}
433+
{#if token && tokenUrl}
434+
<a
435+
class="flex items-center gap-1 text-sm font-medium text-white/60"
436+
title="View {token} info"
437+
href={tokenUrl}
438+
target="_blank"
439+
>
440+
<span>{pruneCanister(token, false)}</span>
441+
<span class="*:size-4"><ArrowRightUpLine /></span>
442+
</a>
443+
{/if}
444+
{/if}
445+
</p>
388446
<NetworkSelector
389447
disabled={isLoading || isBridging}
390448
selectedChain={fromChain}
@@ -410,7 +468,25 @@
410468

411469
<!-- To Section -->
412470
<div class="relative">
413-
<p class="mb-1 text-sm text-white/60">To</p>
471+
<p class="mb-1 flex items-center gap-2 text-sm text-white/60">
472+
<span>To</span>
473+
{#if selectedBridge && toChain}
474+
{@const [token, tokenUrl] = selectedBridge.getTokenUrl(
475+
toChain.name
476+
)}
477+
{#if token && tokenUrl}
478+
<a
479+
class="flex items-center gap-1 text-sm font-medium text-white/60"
480+
title="View {token} info"
481+
href={tokenUrl}
482+
target="_blank"
483+
>
484+
<span>{pruneCanister(token, false)}</span>
485+
<span class="*:size-4"><ArrowRightUpLine /></span>
486+
</a>
487+
{/if}
488+
{/if}</p
489+
>
414490
<NetworkSelector
415491
disabled={isLoading || isBridging}
416492
selectedChain={toChain}
@@ -440,7 +516,7 @@
440516
placeholder="0.0"
441517
data-1p-ignore
442518
autocomplete="off"
443-
class="w-full flex-1 rounded-xl border border-white/10 bg-white/10 p-2 text-left font-mono text-xl leading-8 ring-0 transition-all duration-200 outline-none placeholder:text-gray-500 invalid:border-red-400 focus:bg-white/20"
519+
class="w-full flex-1 rounded-xl border border-white/10 bg-white/10 p-2 text-left font-mono text-xl leading-8 ring-0 transition-all duration-200 outline-none placeholder:text-gray-500 invalid:border-red-400 focus:bg-white/20 disabled:cursor-not-allowed"
444520
/>
445521
{#if selectedBridge}
446522
{@const token_bridge_fee = selectedBridge.state?.token_bridge_fee || 0n}
@@ -478,16 +554,28 @@
478554
placeholder={pruneAddress(toAddress) || '0x...'}
479555
data-1p-ignore
480556
autocomplete="off"
481-
class="mb-1 w-full min-w-0 flex-1 rounded-xl border border-white/10 bg-white/10 p-2 text-left leading-8 ring-0 transition-all duration-200 outline-none placeholder:text-gray-500 invalid:border-red-400 focus:bg-white/20"
557+
class="mb-1 w-full min-w-0 flex-1 rounded-xl border border-white/10 bg-white/10 p-2 text-left leading-8 ring-0 transition-all duration-200 outline-none placeholder:text-gray-500 invalid:border-red-400 focus:bg-white/20 disabled:cursor-not-allowed"
482558
/>
559+
{#if selectedBridge && !error && fromAmount! > 0}
560+
{@const token_bridge_fee = selectedBridge.state?.token_bridge_fee || 0n}
561+
{@const amount = selectedBridge.parseAmount(fromAmount!)}
562+
<div class="mt-1 text-sm text-green-500">
563+
<span
564+
>You receive: {selectedBridge.displayAmount(
565+
amount - token_bridge_fee
566+
)}</span
567+
>
568+
</div>
569+
{/if}
483570
{#if thirdAddress}
484571
<label
485572
class="flex items-center text-sm font-medium text-white/60 rtl:text-right"
486573
><input
487574
type="checkbox"
488575
name="confirmAddress"
576+
disabled={isLoading || isBridging}
489577
bind:checked={confirmAddress}
490-
class="text-primary-600 me-2 size-4 flex-shrink-0 rounded-sm border-gray-300 bg-gray-100 ring-0"
578+
class="text-primary-600 me-2 size-4 flex-shrink-0 rounded-sm border-gray-300 bg-gray-100 ring-0 disabled:cursor-not-allowed"
491579
/>
492580
I confirmed the address is correct and not an exchange or contract address.
493581
Any tokens sent to an incorrect address will be unrecoverable.</label

src/one_bridge_app/src/lib/components/ChainSelector.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
{disabled}
5151
{trigger}
5252
{containerClass}
53-
triggerClass="grid w-full grid-cols-[1fr_24px] rounded-xl p-2 duration-200"
53+
triggerClass="grid w-full grid-cols-[1fr_24px] rounded-xl p-2 duration-200 disabled:cursor-not-allowed disabled:bg-gray-500"
5454
menuClass="top-full z-20 mt-2 w-60 rounded-xl border border-white/20 bg-black shadow-lg"
5555
>
5656
<ul class="py-4">

src/one_bridge_app/src/lib/components/TokenSelector.svelte

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151
{disabled}
5252
{trigger}
5353
{containerClass}
54-
triggerClass="px-0 py-2 duration-200 overflow-hidden"
54+
triggerClass="px-0 py-2 duration-200 overflow-hidden disabled:cursor-not-allowed disabled:bg-gray-500"
5555
menuClass="top-full mt-2 w-60 rounded-xl border border-white/20 bg-black shadow-lg"
5656
>
5757
<ul class="py-4">
@@ -61,9 +61,7 @@
6161
<button
6262
onclick={() => handleSelect(token)}
6363
disabled={isDisabled}
64-
class="flex w-full items-center gap-2 px-3 py-2 text-left text-sm {isDisabled
65-
? 'cursor-not-allowed text-gray-500'
66-
: 'text-white/80 hover:bg-white/20 hover:text-white'}"
64+
class="flex w-full items-center gap-2 px-3 py-2 text-left text-sm text-white/80 hover:bg-white/20 hover:text-white disabled:cursor-not-allowed disabled:bg-gray-500"
6765
>
6866
<img
6967
src={token.logo}

0 commit comments

Comments
 (0)