Skip to content

Commit

Permalink
chore: pr review, adding test and validation for address
Browse files Browse the repository at this point in the history
  • Loading branch information
wainola committed Jan 23, 2024
1 parent 08146cd commit 739a467
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 19 deletions.
2 changes: 2 additions & 0 deletions packages/widget/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@
"@lit/reactive-element": "^2.0.3",
"@polkadot/api": "^10.11.2",
"@polkadot/extension-dapp": "^0.46.6",
"@polkadot/keyring": "^12.6.2",
"@polkadot/util": "^12.6.2",
"ethers": "5.7.2",
"events": "^3.3.0",
"lit": "3.0.0"
Expand Down
45 changes: 38 additions & 7 deletions packages/widget/src/components/address-input/address-input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,62 @@ import { LitElement, html } from 'lit';
import type { HTMLTemplateResult } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { ifDefined } from 'lit/directives/if-defined.js';
import { ethers } from 'ethers';
import { validatePolkadotAddress } from '../../utils';
import { styles } from './styles';

@customElement('address-input')
export default class AddressInput extends LitElement {
@customElement('sygma-address-input')
export class AddressInput extends LitElement {
static styles = styles;
@property({
type: String
})
addressToTransfer?: string;
address: string = '';

@property()
handleAddress?: (e: Event) => void;
handleAddress?: (address: string) => void;

@property({
type: Object
})
network?: 'substrate' | 'evm';

private handleAddressChange = ({ target }: Event): void => {
const { value } = target as HTMLInputElement;
if (this.network !== 'evm') {
const validPolkadotAddress = validatePolkadotAddress(value);

if (validPolkadotAddress) {
return void this.handleAddress?.(value);
}
// TODO: if not defined or show error
} else {
const isAddress = ethers.utils.isAddress(value);
if (isAddress) {
return void this.handleAddress?.(value);
}
// TODO: if not defined or show error
}
};

render(): HTMLTemplateResult {
return html`<section class="switch-container">
return html`<section class="address-input-container">
<div class="input-address-container">
<label>Send to</label>
<input
class="input-address"
name="address"
type="text"
@change=${this.handleAddress}
value=${ifDefined(this.addressToTransfer)}
@change=${(evt: Event) => this.handleAddressChange.bind(this)(evt)}
value=${ifDefined(this.address)}
/>
</div>
</section>`;
}
}

declare global {
interface HTMLElementTagNameMap {
'sygma-address-input': AddressInput;
}
}
2 changes: 1 addition & 1 deletion packages/widget/src/components/address-input/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { default } from './address-input';
export { AddressInput } from './address-input';
12 changes: 1 addition & 11 deletions packages/widget/src/components/address-input/styles.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,7 @@
import { css } from 'lit';

export const styles = css`
.switcher {
--md-sys-color-primary: var(--primary-500-main, #6366f1);
--md-switch-track-color: #ffffff;
--md-switch-selected-handle-color: #ffffff;
--md-switch-track-height: 25px;
--md-switch-track-width: 45px;
--md-switch-selected-handle-height: 17px;
--md-switch-selected-handle-width: 17px;
}
.switch-container {
.address-input-container {
display: flex;
flex-direction: column;
justify-content: center;
Expand Down
1 change: 1 addition & 0 deletions packages/widget/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { AmountSelector } from './amount-selector';
export { NetworkSelector } from './network-selector';
export { AddressInput } from './address-input';
11 changes: 11 additions & 0 deletions packages/widget/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { HTMLTemplateResult } from 'lit';
import { html } from 'lit';
import { decodeAddress, encodeAddress } from '@polkadot/keyring';
import { hexToU8a, isHex } from '@polkadot/util';
import {
baseNetworkIcon,
cronosNetworkIcon,
Expand Down Expand Up @@ -46,3 +48,12 @@ export const capitalize = (s: string): string => {
const rest = s.slice(1);
return `${firstLetter}${rest}`;
};

export const validatePolkadotAddress = (address: string): boolean => {
try {
encodeAddress(isHex(address) ? hexToU8a(address) : decodeAddress(address));
return true;
} catch (error) {
return false;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { afterEach, assert, describe, it, vi } from 'vitest';
import { fixture, fixtureCleanup, oneEvent } from '@open-wc/testing-helpers';
import { html } from 'lit';
import { AddressInput } from '../../../../src/components';

describe('address-input component', function () {
afterEach(() => {
fixtureCleanup();
});

const handleAddress = (address: string) => console.log(address);

Check failure on line 11 in packages/widget/tests/unit/components/address-input/address-input.test.ts

View workflow job for this annotation

GitHub Actions / check

Missing return type on function

it('is defined', () => {
const el = document.createElement('sygma-address-input');
assert.instanceOf(el, AddressInput);
});
it('renders input field with address value', async () => {
const el = await fixture(html`
<sygma-address-input
.address=${'0x123'}
.handleAddress=${handleAddress}
></sygma-address-input>
`);

const input = el.shadowRoot!.querySelector(
'.input-address'
) as HTMLInputElement;

console.log(input.value);
assert.equal(input.value, '0x123');
});
it('triggers callback on address change and validates Substrate address', async () => {
const mockAddressChangeHandler = vi.fn();

const el = await fixture(html`
<sygma-address-input
.network=${'substrate'}
.handleAddress=${mockAddressChangeHandler}
></sygma-address-input>
`);

const input = el.shadowRoot!.querySelector(
'.input-address'
) as HTMLInputElement;

const listener = oneEvent(input, 'change', false);

input.value = '42sydUvocBuEorweEPqxY5vZae1VaTtWoJFiKMrPbRamy2BL';

input.dispatchEvent(new Event('change'));

await listener;

assert.equal(mockAddressChangeHandler.mock.calls.length, 1);
assert.deepEqual(mockAddressChangeHandler.mock.lastCall, [
'42sydUvocBuEorweEPqxY5vZae1VaTtWoJFiKMrPbRamy2BL'
]);
});

it('triggers callback on address change and validates Ethereum address', async () => {
const mockAddressChangeHandler = vi.fn();

const el = await fixture(html`
<sygma-address-input
.network=${'evm'}
.handleAddress=${mockAddressChangeHandler}
></sygma-address-input>
`);

const input = el.shadowRoot!.querySelector(
'.input-address'
) as HTMLInputElement;

const listener = oneEvent(input, 'change', false);

input.value = '0xebFC7A970CAAbC18C8e8b7367147C18FC7585492';

input.dispatchEvent(new Event('change'));

await listener;

assert.equal(mockAddressChangeHandler.mock.calls.length, 1);
assert.deepEqual(mockAddressChangeHandler.mock.lastCall, [
'0xebFC7A970CAAbC18C8e8b7367147C18FC7585492'
]);
});
});
2 changes: 2 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,8 @@ __metadata:
"@open-wc/testing-helpers": "npm:^3.0.0"
"@polkadot/api": "npm:^10.11.2"
"@polkadot/extension-dapp": "npm:^0.46.6"
"@polkadot/keyring": "npm:^12.6.2"
"@polkadot/util": "npm:^12.6.2"
eslint: "npm:^8.48.0"
eslint-plugin-lit: "npm:^1.9.1"
ethers: "npm:5.7.2"
Expand Down

0 comments on commit 739a467

Please sign in to comment.