Skip to content

Commit

Permalink
Merge branch 'main' into av/feat/qr-code-modal
Browse files Browse the repository at this point in the history
  • Loading branch information
AntonioVentilii-DFINITY authored May 22, 2024
2 parents ac58930 + 7181b28 commit 998cdfd
Show file tree
Hide file tree
Showing 10 changed files with 193 additions and 87 deletions.
15 changes: 12 additions & 3 deletions src/frontend/src/env/networks.ircrc.env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,10 @@ const CKUSDC_LOCAL_DATA: IcCkInterface | undefined =
minterCanisterId: LOCAL_CKETH_MINTER_CANISTER_ID,
exchangeCoinId: 'ethereum',
position: 3,
twinToken: SEPOLIA_USDC_TOKEN
twinToken: SEPOLIA_USDC_TOKEN,
...(nonNullish(LOCAL_CKETH_LEDGER_CANISTER_ID) && {
feeLedgerCanisterId: LOCAL_CKETH_LEDGER_CANISTER_ID
})
}
: undefined;

Expand All @@ -226,7 +229,10 @@ const CKUSDC_STAGING_DATA: IcCkInterface | undefined =
minterCanisterId: STAGING_CKETH_MINTER_CANISTER_ID,
exchangeCoinId: 'ethereum',
position: 2,
twinToken: SEPOLIA_USDC_TOKEN
twinToken: SEPOLIA_USDC_TOKEN,
...(nonNullish(STAGING_CKETH_LEDGER_CANISTER_ID) && {
feeLedgerCanisterId: STAGING_CKETH_LEDGER_CANISTER_ID
})
}
: undefined;

Expand All @@ -242,7 +248,10 @@ const CKUSDC_IC_DATA: IcCkInterface | undefined =
exchangeCoinId: 'ethereum',
position: 1,
twinToken: USDC_TOKEN,
explorerUrl: `${CKETH_EXPLORER_URL}/${IC_CKUSDC_LEDGER_CANISTER_ID}`
explorerUrl: `${CKETH_EXPLORER_URL}/${IC_CKUSDC_LEDGER_CANISTER_ID}`,
...(nonNullish(IC_CKETH_LEDGER_CANISTER_ID) && {
feeLedgerCanisterId: IC_CKETH_LEDGER_CANISTER_ID
})
}
: undefined;

Expand Down
12 changes: 6 additions & 6 deletions src/frontend/src/icp-eth/services/eth.services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
type MapCkEthereumPendingTransactionParams
} from '$icp-eth/utils/cketh-transactions.utils';
import { icPendingTransactionsStore } from '$icp/stores/ic-pending-transactions.store';
import type { IcCkTwinToken, IcToken, IcTransactionUi } from '$icp/types/ic';
import type { IcCkLinkedAssets, IcToken, IcTransactionUi } from '$icp/types/ic';
import { nullishSignOut } from '$lib/services/auth.services';
import { i18n } from '$lib/stores/i18n.store';
import { toastsError } from '$lib/stores/toasts.store';
Expand All @@ -35,7 +35,7 @@ export const loadCkEthereumPendingTransactions = async ({
token: IcToken;
lastObservedBlockNumber: bigint;
identity: OptionIdentity;
} & IcCkTwinToken) => {
} & IcCkLinkedAssets) => {
const { id: twinTokenId } = twinToken;

if (isSupportedEthTokenId(twinTokenId)) {
Expand All @@ -61,7 +61,7 @@ const loadCkETHPendingTransactions = async ({
token: IcToken;
lastObservedBlockNumber: bigint;
identity: OptionIdentity;
} & IcCkTwinToken) => {
} & IcCkLinkedAssets) => {
const logsTopics = (to: ETH_ADDRESS): (string | null)[] => [
CKETH_HELPER_CONTRACT_SIGNATURE,
null,
Expand All @@ -86,7 +86,7 @@ const loadCkErc20PendingTransactions = async ({
lastObservedBlockNumber: bigint;
identity: OptionIdentity;
token: IcToken;
} & IcCkTwinToken) => {
} & IcCkLinkedAssets) => {
const logsTopics = (to: ETH_ADDRESS): (string | null)[] => [
CKERC20_HELPER_CONTRACT_SIGNATURE,
null,
Expand Down Expand Up @@ -118,7 +118,7 @@ const loadPendingTransactions = async ({
logsTopics: (to: ETH_ADDRESS) => (string | null)[];
token: IcToken;
mapPendingTransaction: (params: MapCkEthereumPendingTransactionParams) => IcTransactionUi;
} & IcCkTwinToken) => {
} & IcCkLinkedAssets) => {
if (isNullish(identity)) {
await nullishSignOut();
return;
Expand Down Expand Up @@ -199,7 +199,7 @@ export const loadPendingCkEthereumTransaction = async ({
hash: string;
token: IcToken;
networkId: NetworkId;
} & IcCkTwinToken) => {
} & IcCkLinkedAssets) => {
try {
const { getTransaction } = alchemyProviders(networkId);
const transaction = await getTransaction(hash);
Expand Down
6 changes: 3 additions & 3 deletions src/frontend/src/icp-eth/utils/cketh-transactions.utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { EthereumNetwork } from '$eth/types/network';
import type { IcCkTwinToken, IcToken, IcTransactionUi } from '$icp/types/ic';
import type { IcCkLinkedAssets, IcToken, IcTransactionUi } from '$icp/types/ic';
import { i18n } from '$lib/stores/i18n.store';
import { replacePlaceholders } from '$lib/utils/i18n.utils';
import { nonNullish } from '@dfinity/utils';
Expand All @@ -11,7 +11,7 @@ import { get } from 'svelte/store';
export type MapCkEthereumPendingTransactionParams = {
transaction: Transaction;
token: IcToken;
} & IcCkTwinToken;
} & IcCkLinkedAssets;

export const mapCkEthPendingTransaction = ({
transaction: { value, ...transaction },
Expand Down Expand Up @@ -42,7 +42,7 @@ const mapPendingTransaction = ({
transaction: Omit<Transaction, 'value' | 'data'>;
token: IcToken;
value: BigNumber;
} & IcCkTwinToken): IcTransactionUi => {
} & IcCkLinkedAssets): IcTransactionUi => {
const explorerUrl = (twinToken.network as EthereumNetwork).explorerUrl;

const { symbol: twinTokenSymbol } = twinToken;
Expand Down
73 changes: 22 additions & 51 deletions src/frontend/src/icp/components/fee/EthereumEstimatedFee.svelte
Original file line number Diff line number Diff line change
@@ -1,75 +1,46 @@
<script lang="ts">
import { slide, fade } from 'svelte/transition';
import { token, tokenId } from '$lib/derived/token.derived';
import { nonNullish } from '@dfinity/utils';
import { isTokenCkErc20Ledger, isTokenCkEthLedger } from '$icp/utils/ic-send.utils';
import type { IcToken } from '$icp/types/ic';
import type { NetworkId } from '$lib/types/network';
import Value from '$lib/components/ui/Value.svelte';
import { eip1559TransactionPriceStore } from '$icp/stores/cketh.store';
import { loadEip1559TransactionPrice } from '$icp/services/cketh.services';
import { formatToken } from '$lib/utils/format.utils';
import { BigNumber } from '@ethersproject/bignumber';
import { onDestroy } from 'svelte';
import { getContext } from 'svelte';
import { EIGHT_DECIMALS } from '$lib/constants/app.constants';
import { isNetworkIdEthereum } from '$lib/utils/network.utils';
import { ckEthereumNativeToken } from '$icp-eth/derived/cketh.derived';
import { i18n } from '$lib/stores/i18n.store';
import { CKERC20_TO_ERC20_MAX_TRANSACTION_FEE } from '$icp/constants/cketh.constants';
import {
ETHEREUM_FEE_CONTEXT_KEY,
type EthereumFeeContext
} from '$icp/stores/ethereum-fee.store';
import { isTokenCkErc20Ledger } from '$icp/utils/ic-send.utils';
import { token } from '$lib/derived/token.derived';
import type { IcCkToken, IcToken } from '$icp/types/ic';
import { icrcTokens } from '$icp/derived/icrc.derived';
export let networkId: NetworkId | undefined = undefined;
let ckETH = false;
$: ckETH = isTokenCkEthLedger($token as IcToken);
import type { LedgerCanisterIdText } from '$icp/types/canister';
let ckEr20 = false;
$: ckEr20 = isTokenCkErc20Ledger($token as IcToken);
let ethNetwork = false;
$: ethNetwork = isNetworkIdEthereum(networkId);
let maxTransactionFeeEth: bigint | undefined = undefined;
$: maxTransactionFeeEth = $eip1559TransactionPriceStore?.[$tokenId]?.data.max_transaction_fee;
let feeLedgerCanisterId: LedgerCanisterIdText | undefined;
$: feeLedgerCanisterId = ($token as IcCkToken).feeLedgerCanisterId;
let tokenCkEth: IcToken | undefined;
$: tokenCkEth = $icrcTokens.find(isTokenCkEthLedger);
let maxTransactionFeePlusEthLedgerApprove: bigint | undefined = undefined;
$: maxTransactionFeePlusEthLedgerApprove = nonNullish(maxTransactionFeeEth)
? maxTransactionFeeEth + CKERC20_TO_ERC20_MAX_TRANSACTION_FEE + (tokenCkEth?.fee ?? 0n)
$: tokenCkEth = nonNullish(feeLedgerCanisterId)
? $icrcTokens.find(({ ledgerCanisterId }) => ledgerCanisterId === feeLedgerCanisterId)
: undefined;
let maxTransactionFee: bigint | undefined = undefined;
$: maxTransactionFee =
nonNullish(maxTransactionFeePlusEthLedgerApprove) && ckEr20
? maxTransactionFeePlusEthLedgerApprove + CKERC20_TO_ERC20_MAX_TRANSACTION_FEE
: maxTransactionFeePlusEthLedgerApprove;
const loadFee = async () => {
clearTimer();
if ((!ckETH && !ckEr20) || !ethNetwork) {
return;
}
const load = async () => await loadEip1559TransactionPrice($token as IcToken);
await load();
timer = setInterval(load, 30000);
};
$: networkId, (async () => await loadFee())();
let timer: NodeJS.Timeout | undefined;
let feeSymbol: string;
$: feeSymbol = ckEr20
? tokenCkEth?.symbol ?? $ckEthereumNativeToken.symbol
: $ckEthereumNativeToken.symbol;
const clearTimer = () => clearInterval(timer);
const { store } = getContext<EthereumFeeContext>(ETHEREUM_FEE_CONTEXT_KEY);
onDestroy(clearTimer);
let maxTransactionFee: bigint | undefined | null = undefined;
$: maxTransactionFee = $store?.maxTransactionFee;
</script>

{#if (ckETH || ckEr20) && ethNetwork}
{#if nonNullish($store)}
<div transition:slide={{ duration: 250 }}>
<Value ref="kyt-fee">
<svelte:fragment slot="label">{$i18n.fee.text.estimated_eth}</svelte:fragment>
Expand All @@ -82,7 +53,7 @@
value: BigNumber.from(maxTransactionFee),
displayDecimals: EIGHT_DECIMALS
})}
{$ckEthereumNativeToken.symbol}
{feeSymbol}
</span>
{/if}
</div>
Expand Down
84 changes: 84 additions & 0 deletions src/frontend/src/icp/components/fee/EthereumFeeContext.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<script lang="ts">
import type { NetworkId } from '$lib/types/network';
import { isTokenCkErc20Ledger, isTokenCkEthLedger } from '$icp/utils/ic-send.utils';
import { token, tokenId } from '$lib/derived/token.derived';
import type { IcToken } from '$icp/types/ic';
import { isNetworkIdEthereum } from '$lib/utils/network.utils';
import { eip1559TransactionPriceStore } from '$icp/stores/cketh.store';
import { icrcTokens } from '$icp/derived/icrc.derived';
import { nonNullish } from '@dfinity/utils';
import { CKERC20_TO_ERC20_MAX_TRANSACTION_FEE } from '$icp/constants/cketh.constants';
import { loadEip1559TransactionPrice } from '$icp/services/cketh.services';
import { getContext, onDestroy } from 'svelte';
import {
ETHEREUM_FEE_CONTEXT_KEY,
type EthereumFeeContext
} from '$icp/stores/ethereum-fee.store';
export let networkId: NetworkId | undefined = undefined;
let ckETH = false;
$: ckETH = isTokenCkEthLedger($token as IcToken);
let ckEr20 = false;
$: ckEr20 = isTokenCkErc20Ledger($token as IcToken);
let ethNetwork = false;
$: ethNetwork = isNetworkIdEthereum(networkId);
let maxTransactionFeeEth: bigint | undefined = undefined;
$: maxTransactionFeeEth = $eip1559TransactionPriceStore?.[$tokenId]?.data.max_transaction_fee;
let tokenCkEth: IcToken | undefined;
$: tokenCkEth = $icrcTokens.find(isTokenCkEthLedger);
let maxTransactionFeePlusEthLedgerApprove: bigint | undefined = undefined;
$: maxTransactionFeePlusEthLedgerApprove = nonNullish(maxTransactionFeeEth)
? maxTransactionFeeEth + CKERC20_TO_ERC20_MAX_TRANSACTION_FEE + (tokenCkEth?.fee ?? 0n)
: undefined;
let maxTransactionFee: bigint | undefined = undefined;
$: maxTransactionFee =
nonNullish(maxTransactionFeePlusEthLedgerApprove) && ckEr20
? maxTransactionFeePlusEthLedgerApprove + CKERC20_TO_ERC20_MAX_TRANSACTION_FEE
: maxTransactionFeePlusEthLedgerApprove;
const { store } = getContext<EthereumFeeContext>(ETHEREUM_FEE_CONTEXT_KEY);
$: store.setFee({ maxTransactionFee });
const updateContext = () => {
if ((!ckETH && !ckEr20) || !ethNetwork) {
store.setFee(null);
return;
}
store.setFee({ maxTransactionFee });
};
$: maxTransactionFee, updateContext();
const loadFee = async () => {
clearTimer();
if ((!ckETH && !ckEr20) || !ethNetwork) {
updateContext();
return;
}
const load = async () => await loadEip1559TransactionPrice($token as IcToken);
await load();
timer = setInterval(load, 30000);
};
$: networkId, (async () => await loadFee())();
let timer: NodeJS.Timeout | undefined;
const clearTimer = () => clearInterval(timer);
onDestroy(clearTimer);
</script>

<slot />
2 changes: 1 addition & 1 deletion src/frontend/src/icp/components/send/IcFeeDisplay.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

<BitcoinEstimatedFee />
<BitcoinKYTFee {networkId} />
<EthereumEstimatedFee {networkId} />
<EthereumEstimatedFee />
48 changes: 29 additions & 19 deletions src/frontend/src/icp/components/send/IcSendModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@
} from '$lib/constants/analytics.contants';
import { replacePlaceholders } from '$lib/utils/i18n.utils';
import { ckEthereumTwinToken } from '$icp-eth/derived/cketh.derived';
import EthereumFeeContext from '$icp/components/fee/EthereumFeeContext.svelte';
import {
ETHEREUM_FEE_CONTEXT_KEY,
initEthereumFeeStore,
type EthereumFeeContext as EthereumFeeContextType
} from '$icp/stores/ethereum-fee.store';
/**
* Props
Expand Down Expand Up @@ -158,13 +164,15 @@
});
/**
* Btc Fee context store
* Init bitcoin and Ethereum fee context stores
*/
let storeFeeData = initBitcoinFeeStore();
setContext<BitcoinFeeContextType>(BITCOIN_FEE_CONTEXT_KEY, {
store: storeFeeData
store: initBitcoinFeeStore()
});
setContext<EthereumFeeContextType>(ETHEREUM_FEE_CONTEXT_KEY, {
store: initEthereumFeeStore()
});
</script>

Expand All @@ -177,19 +185,21 @@
>
<svelte:fragment slot="title">{currentStep?.title ?? ''}</svelte:fragment>

<BitcoinFeeContext {amount} {networkId}>
{#if currentStep?.name === 'Review'}
<IcSendReview on:icBack={modal.back} on:icSend={send} {destination} {amount} {networkId} />
{:else if currentStep?.name === 'Sending'}
<IcSendProgress bind:sendProgressStep {networkId} />
{:else}
<IcSendForm
on:icNext={modal.next}
on:icClose={close}
bind:destination
bind:amount
bind:networkId
/>
{/if}
</BitcoinFeeContext>
<EthereumFeeContext {networkId}>
<BitcoinFeeContext {amount} {networkId}>
{#if currentStep?.name === 'Review'}
<IcSendReview on:icBack={modal.back} on:icSend={send} {destination} {amount} {networkId} />
{:else if currentStep?.name === 'Sending'}
<IcSendProgress bind:sendProgressStep {networkId} />
{:else}
<IcSendForm
on:icNext={modal.next}
on:icClose={close}
bind:destination
bind:amount
bind:networkId
/>
{/if}
</BitcoinFeeContext>
</EthereumFeeContext>
</WizardModal>
Loading

0 comments on commit 998cdfd

Please sign in to comment.