From 1d7ebe6b5608e6761a81a44d6f29d4f088d0784c Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Tue, 16 Apr 2024 12:47:43 +0200 Subject: [PATCH 1/8] wip --- .../src/components/address-input/address-input.ts | 13 ++++++------- .../fungible/transfer-button/transfer-button.ts | 1 + .../transfers/fungible-token-transfer.ts | 13 ++++++++++++- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/widget/src/components/address-input/address-input.ts b/packages/widget/src/components/address-input/address-input.ts index ca265292..35fe34d7 100644 --- a/packages/widget/src/components/address-input/address-input.ts +++ b/packages/widget/src/components/address-input/address-input.ts @@ -6,7 +6,7 @@ import { when } from 'lit/directives/when.js'; import type { PropertyValues } from '@lit/reactive-element'; import { validateAddress } from '../../utils'; -import { BaseComponent } from '../common/base-component/base-component'; +import { BaseComponent } from '../common'; import { styles } from './styles'; @@ -20,11 +20,10 @@ export class AddressInput extends BaseComponent { address: string = ''; @property({ attribute: false }) - onAddressChange: (address: string) => void = () => {}; + onAddressChange: (address: string, errorMessage?: string | null) => void = + () => {}; - @property({ - type: String - }) + @property({ type: String }) networkType: Network = Network.EVM; @state() @@ -49,7 +48,7 @@ export class AddressInput extends BaseComponent { this.errorMessage = validateAddress(trimedValue, this.networkType); - this.onAddressChange(trimedValue); + this.onAddressChange(trimedValue, this.errorMessage); }; protected updated(changedProperties: PropertyValues): void { @@ -60,7 +59,7 @@ export class AddressInput extends BaseComponent { } render(): HTMLTemplateResult { - return html`
+ return html`
`; diff --git a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts index 81ef5cb9..8941f9de 100644 --- a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts +++ b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts @@ -7,14 +7,17 @@ import type { Button } from '../../../common'; import { BaseComponent } from '../../../common'; const enabledStates = [ - FungibleTransferState.WRONG_CHAIN, - FungibleTransferState.WRONG_DESTINATION_ADDRESS, - FungibleTransferState.WALLET_NOT_CONNECTED, FungibleTransferState.PENDING_APPROVALS, FungibleTransferState.PENDING_TRANSFER, FungibleTransferState.COMPLETED ]; +const disabledState = [ + FungibleTransferState.WRONG_CHAIN, + FungibleTransferState.WRONG_DESTINATION_ADDRESS, + FungibleTransferState.WALLET_NOT_CONNECTED +]; + const loadingStates = [ FungibleTransferState.WAITING_TX_EXECUTION, FungibleTransferState.WAITING_USER_CONFIRMATION, @@ -29,9 +32,12 @@ export class FungibleTransferButton extends BaseComponent { @property({ type: Object }) onClick: () => void = () => {}; + handleDisabledState = (): boolean => + !enabledStates.includes(this.state) || disabledState.includes(this.state); + render(): HTMLTemplateResult { return html` 'Connect Wallet'], [FungibleTransferState.WRONG_CHAIN, () => 'Switch chain'], + [ + FungibleTransferState.WRONG_DESTINATION_ADDRESS, + () => 'Wrong Address' + ], [FungibleTransferState.PENDING_APPROVALS, () => 'Approve token'], [FungibleTransferState.PENDING_TRANSFER, () => 'Transfer'], [ @@ -68,7 +78,7 @@ export class FungibleTransferButton extends BaseComponent { [FungibleTransferState.COMPLETED, () => 'Start new transfer'] ], () => 'Loading' - )!} + )} @click=${this.onClick} >`; } diff --git a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts index 17da4f79..1025c88e 100644 --- a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts +++ b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts @@ -192,12 +192,6 @@ export class FungibleTokenTransferController implements ReactiveController { if (this.waitingTxExecution) { return FungibleTransferState.WAITING_TX_EXECUTION; } - if (this.pendingEvmApprovalTransactions.length > 0) { - return FungibleTransferState.PENDING_APPROVALS; - } - if (this.pendingEvmTransferTransaction) { - return FungibleTransferState.PENDING_TRANSFER; - } if (!this.sourceNetwork) { return FungibleTransferState.MISSING_SOURCE_NETWORK; } @@ -207,15 +201,18 @@ export class FungibleTokenTransferController implements ReactiveController { if (!this.selectedResource) { return FungibleTransferState.MISSING_RESOURCE; } + + if (this.invalidDestinationAddressErrorMessage?.length) { + return FungibleTransferState.WRONG_DESTINATION_ADDRESS; + } + if (this.resourceAmount.eq(0)) { return FungibleTransferState.MISSING_RESOURCE_AMOUNT; } if (this.destinationAddress === '') { return FungibleTransferState.MISSING_DESTINATION_ADDRESS; } - if (this.invalidDestinationAddressErrorMessage) { - return FungibleTransferState.WRONG_DESTINATION_ADDRESS; - } + if ( !this.walletContext.value?.evmWallet && !this.walletContext.value?.substrateWallet @@ -229,6 +226,14 @@ export class FungibleTokenTransferController implements ReactiveController { ) { return FungibleTransferState.WRONG_CHAIN; } + + if (this.pendingEvmApprovalTransactions.length > 0) { + return FungibleTransferState.PENDING_APPROVALS; + } + if (this.pendingEvmTransferTransaction) { + return FungibleTransferState.PENDING_TRANSFER; + } + return FungibleTransferState.UNKNOWN; } From faf4ea6846bb9b3a850b5f2caa19af4e5b8533e1 Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Wed, 17 Apr 2024 16:41:28 +0200 Subject: [PATCH 3/8] fix tests --- .../address-input/address-input.test.ts | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/packages/widget/tests/unit/components/address-input/address-input.test.ts b/packages/widget/tests/unit/components/address-input/address-input.test.ts index 61eef08d..20e6de70 100644 --- a/packages/widget/tests/unit/components/address-input/address-input.test.ts +++ b/packages/widget/tests/unit/components/address-input/address-input.test.ts @@ -9,6 +9,8 @@ import { html } from 'lit'; import { Network } from '@buildwithsygma/sygma-sdk-core'; import { AddressInput } from '../../../../src/components'; +const errorMessageInvalidAddress = 'invalid Ethereum address'; + describe('address-input component', function () { afterEach(() => { fixtureCleanup(); @@ -110,9 +112,13 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['0x123']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], [ + '0x123', + errorMessageInvalidAddress + ]); assert.deepEqual(mockAddressChangeHandler.mock.lastCall, [ - '0xebFC7A970CAAbC18C8e8b7367147C18FC7585492' + '0xebFC7A970CAAbC18C8e8b7367147C18FC7585492', + null ]); }); @@ -137,8 +143,8 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); - assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); + assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['', null]); const errorMessage = el.shadowRoot!.querySelector( '.errorMessage' @@ -154,9 +160,10 @@ describe('address-input component', function () { assert.equal(mockAddressChangeHandler.mock.calls.length, 4); assert.deepEqual(mockAddressChangeHandler.mock.calls[2], [ - '0xebFC7A970CAAbC18C8e8b7367147C18FC7' + '0xebFC7A970CAAbC18C8e8b7367147C18FC7', + errorMessageInvalidAddress ]); - assert.deepEqual(mockAddressChangeHandler.mock.lastCall, ['']); + assert.deepEqual(mockAddressChangeHandler.mock.lastCall, ['', null]); const errorMessageAfterClean = el.shadowRoot!.querySelector( '.errorMessage' @@ -188,9 +195,10 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); assert.deepEqual(mockAddressChangeHandler.mock.lastCall, [ - '42sydUvocBuEorweEPqxY5vZae1VaTtWoJFiKMrPbRamy2BL' + '42sydUvocBuEorweEPqxY5vZae1VaTtWoJFiKMrPbRamy2BL', + null ]); }); @@ -216,9 +224,10 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); assert.deepEqual(mockAddressChangeHandler.mock.lastCall, [ - '0xebFC7A970CAAbC18C8e8b7367147C18FC7585492' + '0xebFC7A970CAAbC18C8e8b7367147C18FC7585492', + null ]); }); @@ -245,8 +254,8 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); - assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); + assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['', null]); const errorMessage = el.shadowRoot!.querySelector( '.errorMessage' @@ -277,8 +286,8 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); - assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); + assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['', null]); const errorMessage = el.shadowRoot!.querySelector( '.errorMessage' @@ -308,8 +317,8 @@ describe('address-input component', function () { await listener; assert.equal(mockAddressChangeHandler.mock.calls.length, 3); - assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['']); - assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['']); + assert.deepEqual(mockAddressChangeHandler.mock.calls[0], ['', null]); + assert.deepEqual(mockAddressChangeHandler.mock.calls[1], ['', null]); el.networkType = Network.SUBSTRATE; From 6f5539257d5f2d1049fdf8f910e936685515b34d Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Tue, 2 Apr 2024 17:24:34 +0200 Subject: [PATCH 4/8] lykhoyda/network_whitelisting --- .../fungible/transfer-button/transfer-button.ts | 11 ++--------- .../controllers/transfers/fungible-token-transfer.ts | 12 +++++++++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts index 8941f9de..9bfa12cb 100644 --- a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts +++ b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts @@ -9,12 +9,8 @@ import { BaseComponent } from '../../../common'; const enabledStates = [ FungibleTransferState.PENDING_APPROVALS, FungibleTransferState.PENDING_TRANSFER, - FungibleTransferState.COMPLETED -]; - -const disabledState = [ + FungibleTransferState.COMPLETED, FungibleTransferState.WRONG_CHAIN, - FungibleTransferState.WRONG_DESTINATION_ADDRESS, FungibleTransferState.WALLET_NOT_CONNECTED ]; @@ -32,12 +28,9 @@ export class FungibleTransferButton extends BaseComponent { @property({ type: Object }) onClick: () => void = () => {}; - handleDisabledState = (): boolean => - !enabledStates.includes(this.state) || disabledState.includes(this.state); - render(): HTMLTemplateResult { return html` Date: Thu, 18 Apr 2024 12:00:35 +0200 Subject: [PATCH 5/8] fix --- .../src/controllers/transfers/fungible-token-transfer.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts index cee0ffa9..27cff9c5 100644 --- a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts +++ b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts @@ -184,6 +184,11 @@ export class FungibleTokenTransferController implements ReactiveController { }; getTransferState(): FungibleTransferState { + // Enabled state + if (this.transferTransactionId) { + return FungibleTransferState.COMPLETED; + } + // Loading states if (this.waitingUserConfirmation) { return FungibleTransferState.WAITING_USER_CONFIRMATION; @@ -215,10 +220,6 @@ export class FungibleTokenTransferController implements ReactiveController { } // Enabled States - if (this.transferTransactionId) { - return FungibleTransferState.COMPLETED; - } - if ( !this.walletContext.value?.evmWallet && !this.walletContext.value?.substrateWallet From 35d8576ec14e0f6a442e89f1c7a7dfd5cfb44d01 Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Thu, 18 Apr 2024 15:43:51 +0200 Subject: [PATCH 6/8] nit --- packages/widget/src/components/address-input/address-input.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/widget/src/components/address-input/address-input.ts b/packages/widget/src/components/address-input/address-input.ts index b615f107..71476b24 100644 --- a/packages/widget/src/components/address-input/address-input.ts +++ b/packages/widget/src/components/address-input/address-input.ts @@ -23,7 +23,7 @@ export class AddressInput extends BaseComponent { onAddressChange: (address: string, errorMessage?: string | null) => void = () => {}; - @property() + @property({ attribute: false }) networkType: Network = Network.EVM; @state() From 2bd0c5bbe8e13f24ac6f810b1d44684a156cf2c5 Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Fri, 19 Apr 2024 13:29:32 +0200 Subject: [PATCH 7/8] update] --- .../components/address-input/address-input.ts | 7 ++--- .../transfer-button/transfer-button.ts | 4 +-- .../transfers/fungible-token-transfer.ts | 29 ++++++++++--------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/packages/widget/src/components/address-input/address-input.ts b/packages/widget/src/components/address-input/address-input.ts index 71476b24..b8f0ce2e 100644 --- a/packages/widget/src/components/address-input/address-input.ts +++ b/packages/widget/src/components/address-input/address-input.ts @@ -20,8 +20,7 @@ export class AddressInput extends BaseComponent { address: string = ''; @property({ attribute: false }) - onAddressChange: (address: string, errorMessage?: string | null) => void = - () => {}; + onAddressChange: (address: string) => void = () => {}; @property({ attribute: false }) networkType: Network = Network.EVM; @@ -42,12 +41,12 @@ export class AddressInput extends BaseComponent { } if (!trimedValue) { - void this.onAddressChange('', null); + void this.onAddressChange(''); return; } this.errorMessage = validateAddress(trimedValue, this.networkType); - this.onAddressChange(trimedValue, this.errorMessage); + this.onAddressChange(trimedValue); }; protected updated(changedProperties: PropertyValues): void { diff --git a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts index 9bfa12cb..1b2d6652 100644 --- a/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts +++ b/packages/widget/src/components/transfer/fungible/transfer-button/transfer-button.ts @@ -55,8 +55,8 @@ export class FungibleTransferButton extends BaseComponent { [FungibleTransferState.WALLET_NOT_CONNECTED, () => 'Connect Wallet'], [FungibleTransferState.WRONG_CHAIN, () => 'Switch chain'], [ - FungibleTransferState.WRONG_DESTINATION_ADDRESS, - () => 'Wrong Address' + FungibleTransferState.INVALID_DESTINATION_ADDRESS, + () => 'Invalid Address' ], [FungibleTransferState.PENDING_APPROVALS, () => 'Approve token'], [FungibleTransferState.PENDING_TRANSFER, () => 'Transfer'], diff --git a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts index 27cff9c5..481f21ec 100644 --- a/packages/widget/src/controllers/transfers/fungible-token-transfer.ts +++ b/packages/widget/src/controllers/transfers/fungible-token-transfer.ts @@ -12,6 +12,7 @@ import type { ReactiveController, ReactiveElement } from 'lit'; import type { WalletContext } from '../../context'; import { walletContext } from '../../context'; import { MAINNET_EXPLORER_URL, TESTNET_EXPLORER_URL } from '../../constants'; +import { validateAddress } from '../../utils'; import { buildEvmFungibleTransactions, executeNextEvmTransaction } from './evm'; export enum FungibleTransferState { @@ -20,7 +21,7 @@ export enum FungibleTransferState { MISSING_RESOURCE, MISSING_RESOURCE_AMOUNT, MISSING_DESTINATION_ADDRESS, - WRONG_DESTINATION_ADDRESS, + INVALID_DESTINATION_ADDRESS, WALLET_NOT_CONNECTED, WRONG_CHAIN, PENDING_APPROVALS, @@ -36,13 +37,12 @@ export class FungibleTokenTransferController implements ReactiveController { public waitingTxExecution: boolean = false; public transferTransactionId?: string; public errorMessage: string | null = null; - public invalidDestinationAddressErrorMessage: string | null = null; public sourceNetwork?: Domain; public destinationNetwork?: Domain; public selectedResource?: Resource; public resourceAmount: BigNumber = ethers.constants.Zero; - public destinationAddress: string = ''; + public destinationAddress?: string | null = ''; public supportedSourceNetworks: Domain[] = []; public supportedDestinationNetworks: Domain[] = []; @@ -167,17 +167,13 @@ export class FungibleTokenTransferController implements ReactiveController { this.host.requestUpdate(); }; - onDestinationAddressChange = ( - address: string, - errorMessage: string | null - ): void => { + onDestinationAddressChange = (address: string): void => { this.destinationAddress = address; - this.invalidDestinationAddressErrorMessage = errorMessage; if (this.destinationAddress.length === 0) { this.pendingEvmApprovalTransactions = []; this.pendingEvmTransferTransaction = undefined; - this.invalidDestinationAddressErrorMessage = null; + this.destinationAddress = null; } void this.buildTransactions(); this.host.requestUpdate(); @@ -208,16 +204,21 @@ export class FungibleTokenTransferController implements ReactiveController { return FungibleTransferState.MISSING_RESOURCE; } - if (this.invalidDestinationAddressErrorMessage?.length) { - return FungibleTransferState.WRONG_DESTINATION_ADDRESS; + if (this.destinationAddress === '') { + return FungibleTransferState.MISSING_DESTINATION_ADDRESS; + } + + if ( + this.destinationAddress === null || + this.destinationAddress === undefined || + validateAddress(this.destinationAddress, this.destinationNetwork.type) + ) { + return FungibleTransferState.INVALID_DESTINATION_ADDRESS; } if (this.resourceAmount.eq(0)) { return FungibleTransferState.MISSING_RESOURCE_AMOUNT; } - if (this.destinationAddress === '') { - return FungibleTransferState.MISSING_DESTINATION_ADDRESS; - } // Enabled States if ( From d49dc4ed14e72b98b0c0974ca7346e273383a3e0 Mon Sep 17 00:00:00 2001 From: Anton Lykhoyda Date: Fri, 19 Apr 2024 13:47:11 +0200 Subject: [PATCH 8/8] fix tests --- .../components/address-input/address-input.ts | 2 +- .../transfers/fungible-token-transfer.ts | 2 +- .../address-input/address-input.test.ts | 41 ++++++++----------- .../fungible/fungible-token-transfer.test.ts | 2 +- 4 files changed, 19 insertions(+), 28 deletions(-) diff --git a/packages/widget/src/components/address-input/address-input.ts b/packages/widget/src/components/address-input/address-input.ts index b8f0ce2e..da5c005e 100644 --- a/packages/widget/src/components/address-input/address-input.ts +++ b/packages/widget/src/components/address-input/address-input.ts @@ -63,7 +63,7 @@ export class AddressInput extends BaseComponent { Send to ${when( this.errorMessage, - () => html` ${this.errorMessage}` + () => html`${this.errorMessage}` )}