diff --git a/packages/widget/src/components/common/dropdown/dropdown.ts b/packages/widget/src/components/common/dropdown/dropdown.ts index 9ee56fa3..9a232926 100644 --- a/packages/widget/src/components/common/dropdown/dropdown.ts +++ b/packages/widget/src/components/common/dropdown/dropdown.ts @@ -40,14 +40,30 @@ export class Dropdown extends BaseComponent { @property({ type: Object }) actionOption: HTMLTemplateResult | null = null; + @property({ type: String }) + preSelectedOption = ''; + @state() selectedOption: DropdownOption | null = null; @property({ attribute: false }) onOptionSelected: (option?: DropdownOption) => void = () => {}; + _setPreselectedOption = (): void => { + if (this.preSelectedOption) { + const newOption = + this.options.find((o) => o.name === this.preSelectedOption) || null; + + if (newOption) { + this.selectedOption = newOption; + this.onOptionSelected(newOption); + } + } + }; + connectedCallback(): void { super.connectedCallback(); + this._setPreselectedOption(); addEventListener('click', this._handleOutsideClick); } @@ -58,14 +74,28 @@ export class Dropdown extends BaseComponent { updated(changedProperties: PropertyValues): void { super.updated(changedProperties); + + // Set pre-selected option after transfer is completed + if ( + changedProperties.has('options') && + this.preSelectedOption && + this.selectedOption?.name !== this.preSelectedOption + ) { + this._setPreselectedOption(); + } + //if options changed, check if we have selected option that doesn't exist if (changedProperties.has('options') && this.selectedOption) { if ( Array.isArray(this.options) && !this.options.map((o) => o.value).includes(this.selectedOption.value) ) { - this.selectedOption = null; - this.onOptionSelected(undefined); + if (this.preSelectedOption) { + this._setPreselectedOption(); + } else { + this.selectedOption = null; + this.onOptionSelected(undefined); + } } } } diff --git a/packages/widget/src/components/common/index.ts b/packages/widget/src/components/common/index.ts index 11560cfa..3c56acd7 100644 --- a/packages/widget/src/components/common/index.ts +++ b/packages/widget/src/components/common/index.ts @@ -2,3 +2,4 @@ export { Button } from './buttons/button'; export { ConnectWalletButton } from './buttons/connect-wallet'; export { Dropdown } from './dropdown/dropdown'; export { OverlayComponent } from './overlay-component'; +export { BaseComponent } from './base-component'; diff --git a/packages/widget/src/components/network-selector/network-selector.ts b/packages/widget/src/components/network-selector/network-selector.ts index 8f00e381..09472dd5 100644 --- a/packages/widget/src/components/network-selector/network-selector.ts +++ b/packages/widget/src/components/network-selector/network-selector.ts @@ -5,7 +5,7 @@ import { customElement, property } from 'lit/decorators.js'; import { when } from 'lit/directives/when.js'; import { networkIconsMap } from '../../assets'; -import { BaseComponent } from '../common/base-component'; +import { BaseComponent } from '../common'; import type { DropdownOption } from '../common/dropdown/dropdown'; import { styles } from './styles'; @@ -28,6 +28,9 @@ export class NetworkSelector extends BaseComponent { @property({ type: String }) direction?: Direction; + @property({ type: String }) + selectedNetwork?: string; + @property({ attribute: false }) onNetworkSelected: (option?: Domain) => void = () => {}; @@ -55,6 +58,7 @@ export class NetworkSelector extends BaseComponent { render(): HTMLTemplateResult { return html`
{}}>
{ diff --git a/packages/widget/src/components/transfer/fungible/transfer-status/styles.ts b/packages/widget/src/components/transfer/fungible/transfer-status/styles.ts index 9de9abf7..2e846fa4 100644 --- a/packages/widget/src/components/transfer/fungible/transfer-status/styles.ts +++ b/packages/widget/src/components/transfer/fungible/transfer-status/styles.ts @@ -16,7 +16,8 @@ export const styles = css` flex-direction: column; align-items: center; border-radius: 1.5rem; - border: 0.0625rem solid var(--zinc-200); + border: 1px solid var(--zinc-200); + margin-bottom: 1rem; } .destinationMessage { @@ -36,7 +37,7 @@ export const styles = css` display: flex; flex-direction: row; align-items: center; - padding: 0rem 4.78125rem 0.9375rem 4.78125rem; + padding: 0 4.78125rem 0.9375rem 4.78125rem; color: var(--zinc-600); text-align: center; @@ -53,9 +54,7 @@ export const styles = css` align-items: center; justify-content: center; text-align: center; - color: var(--zinc-500); - text-align: center; font-size: 0.75rem; font-style: normal; font-weight: 400; diff --git a/packages/widget/src/controllers/transfers/evm/build.ts b/packages/widget/src/controllers/transfers/evm/build.ts index 7b640955..a85c375d 100644 --- a/packages/widget/src/controllers/transfers/evm/build.ts +++ b/packages/widget/src/controllers/transfers/evm/build.ts @@ -1,5 +1,10 @@ -import { EVMAssetTransfer } from '@buildwithsygma/sygma-sdk-core'; +import { + EVMAssetTransfer, + FeeHandlerType, + type PercentageFee +} from '@buildwithsygma/sygma-sdk-core'; import { Web3Provider } from '@ethersproject/providers'; +import { constants, utils } from 'ethers'; import { type FungibleTokenTransferController } from '../fungible-token-transfer'; /** @@ -29,12 +34,45 @@ export async function buildEvmFungibleTransactions( const evmTransfer = new EVMAssetTransfer(); await evmTransfer.init(new Web3Provider(provider, providerChaiId), this.env); + + // Hack to make fungible transfer behave like it does on substrate side + // where fee is deducted from user inputted amount rather than added on top + const originalTransfer = await evmTransfer.createFungibleTransfer( + address, + this.destinationNetwork.chainId, + this.destinationAddress, + this.selectedResource.resourceId, + this.resourceAmount.toString() + ); + const originalFee = await evmTransfer.getFee(originalTransfer); + //in case of percentage fee handler, we are calculating what amount + fee will result int user inputed amount + //in case of fixed(basic) fee handler, fee is taken from native token + if (originalFee.type === FeeHandlerType.PERCENTAGE) { + const { lowerBound, upperBound, percentage } = originalFee as PercentageFee; + const userInputAmount = this.resourceAmount; + //calculate amount without fee (percentage) + const feelessAmount = userInputAmount + .mul(constants.WeiPerEther) + .div(utils.parseEther(String(1 + percentage))); + + const calculatedFee = userInputAmount.sub(feelessAmount); + this.resourceAmount = feelessAmount; + //if calculated percentage fee is less than lower fee bound, substract lower bound from user input. If lower bound is 0, bound is ignored + if (calculatedFee.lt(lowerBound) && lowerBound.gt(0)) { + this.resourceAmount = userInputAmount.sub(lowerBound); + } + //if calculated percentage fee is more than upper fee bound, substract upper bound from user input. If upper bound is 0, bound is ignored + if (calculatedFee.gt(upperBound) && upperBound.gt(0)) { + this.resourceAmount = userInputAmount.sub(upperBound); + } + } + const transfer = await evmTransfer.createFungibleTransfer( address, this.destinationNetwork.chainId, this.destinationAddress, this.selectedResource.resourceId, - String(this.resourceAmount) + this.resourceAmount.toString() ); this.fee = await evmTransfer.getFee(transfer); this.pendingEvmApprovalTransactions = await evmTransfer.buildApprovals( diff --git a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts index b0c37902..8875c5b4 100644 --- a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts +++ b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts @@ -197,8 +197,10 @@ export class FungibleTokenTransferController implements ReactiveController { this.fee = null; } - reset(): void { - this.sourceNetwork = undefined; + reset({ omitSourceNetworkReset } = { omitSourceNetworkReset: false }): void { + if (!omitSourceNetworkReset) { + this.sourceNetwork = undefined; + } this.destinationNetwork = undefined; this.pendingEvmApprovalTransactions = []; this.pendingTransferTransaction = undefined;