Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: address validation error behavior #5281

Merged
merged 17 commits into from Nov 25, 2022
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 9 additions & 4 deletions packages/mobile/components/inputs/RecipientInput.svelte
@@ -1,8 +1,9 @@
<script lang="typescript">
import { localize } from '@core/i18n'
import { networkHrp } from '@core/network'
import { BECH32_ADDRESS_LENGTH, validateBech32Address } from '@core/utils'
import { IAddressSubject } from '@core/wallet'
import { networkHrp } from '@core/network/stores'
import { BECH32_ADDRESS_LENGTH } from '@core/utils/constants'
import { validateBech32Address } from '@core/utils/crypto'
import { IAddressSubject } from '@core/wallet/interfaces'

export let recipient: IAddressSubject
export let disabled: boolean = false
Expand Down Expand Up @@ -31,7 +32,11 @@
},
})
} else {
error = validateBech32Address(addressPrefix, value)
try {
validateBech32Address(addressPrefix, value)
} catch (err) {
error = err?.message ?? err
}
}
}
</script>
Expand Down
37 changes: 19 additions & 18 deletions packages/shared/components/inputs/AliasInput.svelte
@@ -1,10 +1,11 @@
<script lang="typescript">
import { Modal, SelectorInput, IOption } from 'shared/components'
import { selectedAccount } from '@core/account'
import { ADDRESS_TYPE_ALIAS, convertHexAddressToBech32 } from '@core/wallet'
import { validateBech32Address } from '@core/utils'
import { networkHrp } from '@core/network'
import { selectedAccount } from '@core/account/stores'
import { localize } from '@core/i18n'
import { networkHrp } from '@core/network/stores'
import { validateBech32Address } from '@core/utils/crypto'
import { ADDRESS_TYPE_ALIAS } from '@core/wallet/constants'
import { convertHexAddressToBech32 } from '@core/wallet/utils'

export let alias: string = ''
export let error: string = ''
Expand All @@ -22,24 +23,24 @@
$: alias = selected?.value

export async function validate(): Promise<void> {
if (!alias) {
error = localize('error.aliasMinting.aliasRequired')
try {
if (!alias) {
throw new Error(localize('error.aliasMinting.aliasRequired'))
}
validateBech32Address($networkHrp, alias, ADDRESS_TYPE_ALIAS)
validateAliasInPossession()
} catch (err) {
error = err?.message ?? err
return Promise.reject(error)
}
const addressValidationError = validateBech32Address($networkHrp, alias, ADDRESS_TYPE_ALIAS)
if (addressValidationError) {
error = addressValidationError
return Promise.reject(error)
} else if (!isAliasInPossession()) {
error = localize('error.aliasMinting.aliasNotInPossession')
return Promise.reject(error)
} else {
return Promise.resolve()
}
}

function isAliasInPossession(): boolean {
return aliasOptions.some((option) => option.value === alias)
function validateAliasInPossession(): void {
if (aliasOptions.some((option) => option.value === alias)) {
return
} else {
throw new Error(localize('error.aliasMinting.aliasNotInPossession'))
}
Tuditi marked this conversation as resolved.
Show resolved Hide resolved
}
</script>

Expand Down
49 changes: 26 additions & 23 deletions packages/shared/components/inputs/RecipientInput.svelte
@@ -1,12 +1,13 @@
<script lang="typescript">
import { networkHrp } from '@core/network'
import { validateBech32Address } from '@core/utils'
import { Modal, SelectorInput, IOption, ColoredCircle } from 'shared/components'
import { visibleActiveAccounts } from '@core/profile'
import { getSubjectFromAddress, Subject } from '@core/wallet'
import { getAccountColorById, selectedAccountIndex } from '@core/account'
import { validateEthereumAddress } from '@core/layer-2'
import { selectedAccountIndex } from '@core/account/stores'
import { getAccountColorById } from '@core/account/utils'
import { localize } from '@core/i18n'
import { networkHrp } from '@core/network/stores'
import { visibleActiveAccounts } from '@core/profile/stores'
import { validateBech32Address, validateEthereumAddress } from '@core/utils/crypto'
import { Subject } from '@core/wallet/types'
import { getSubjectFromAddress } from '@core/wallet/utils'

export let recipient: Subject
export let disabled = false
Expand All @@ -28,27 +29,29 @@
$: isLayer2, (error = '')

export function validate(): Promise<void> {
if (recipient?.type === 'address') {
if (!recipient.address) {
error = localize('error.send.recipientRequired')
}
if (isLayer2) {
error = validateEthereumAddress(recipient?.address)
try {
if (recipient?.type === 'address') {
if (!recipient.address) {
throw new Error(localize('error.send.recipientRequired'))
}

if (isLayer2) {
validateEthereumAddress(recipient?.address)
} else {
validateBech32Address(addressPrefix, recipient?.address)
}
} else if (recipient?.type === 'account') {
if (isLayer2) {
throw new Error(localize('error.layer2.layer1Recipient'))
}
} else {
error = validateBech32Address(addressPrefix, recipient?.address)
throw new Error(localize('error.send.recipientRequired'))
}
} else if (recipient?.type === 'account') {
if (isLayer2) {
error = localize('error.layer2.layer1Recipient')
}
} else {
error = localize('error.send.recipientRequired')
}

if (error) {
Promise.resolve()
} catch (err) {
error = err?.message ?? err
return Promise.reject(error)
} else {
return Promise.resolve()
}
}

Expand Down
25 changes: 15 additions & 10 deletions packages/shared/components/popups/MintNftFormPopup.svelte
@@ -1,14 +1,18 @@
<script lang="typescript">
import { onMount } from 'svelte'
import { Button, Dropdown, Error, FontWeight, OptionalInput, Text, TextInput } from 'shared/components'
import { closePopup, openPopup } from '@auxiliary/popup'
import { BaseError } from '@core/error'
import { BaseError } from '@core/error/classes'
import { handleError } from '@core/error/handlers/handleError'
import { localize } from '@core/i18n'
import { networkHrp } from '@core/network'
import { IIrc27Metadata, MimeType, SupportedMimeType } from '@core/nfts'
import { isValidUri, validateBech32Address } from '@core/utils'
import { mintNftDetails, setMintNftDetails, TokenStandard } from '@core/wallet'
import { Button, Dropdown, Error, FontWeight, OptionalInput, Text, TextInput } from 'shared/components'
import { onMount } from 'svelte'
import { networkHrp } from '@core/network/stores'
import { SupportedMimeType } from '@core/nfts/enums'
import { IIrc27Metadata } from '@core/nfts/interfaces'
import { MimeType } from '@core/nfts/types'
import { isValidUri } from '@core/utils/validation'
import { validateBech32Address } from '@core/utils/crypto'
import { TokenStandard } from '@core/wallet/enums'
import { mintNftDetails, setMintNftDetails } from '@core/wallet/stores'

export let _onMount: (..._: any[]) => Promise<void> = async () => {}

Expand Down Expand Up @@ -94,11 +98,12 @@
return
}

const isKeysValid = Object.keys(royalties).every((key) => !validateBech32Address($networkHrp, key))
if (!isKeysValid) {
try {
Object.keys(royalties).forEach((key) => validateBech32Address($networkHrp, key))
} catch (err) {
optionalInputErrors.royalties = `Invalid address, must be a valid ${$networkHrp} address where royalties will be sent to.`
return
Tuditi marked this conversation as resolved.
Show resolved Hide resolved
}

const isValuesValid = Object.values(royalties).every((value) => value >= 0 && value <= 1)
if (!isValuesValid) {
optionalInputErrors.royalties =
Expand Down
1 change: 1 addition & 0 deletions packages/shared/lib/core/layer-2/errors/index.ts
@@ -0,0 +1 @@
export * from './layer1-recipient.error'
14 changes: 14 additions & 0 deletions packages/shared/lib/core/layer-2/errors/layer1-recipient.error.ts
@@ -0,0 +1,14 @@
import { BaseError } from '@core/error/classes'
import { localize } from '@core/i18n'

export class Layer1RecipientError extends BaseError {
constructor() {
const message = localize('error.layer2.layer1Recipient')
super({
message,
showNotification: false,
saveToErrorLog: false,
logToConsole: true,
})
}
}
Tuditi marked this conversation as resolved.
Show resolved Hide resolved
1 change: 0 additions & 1 deletion packages/shared/lib/core/layer-2/utils/index.ts
@@ -1,3 +1,2 @@
export * from './addGasBudget'
export * from './isLayer1Destination'
export * from './validateEthereumAddress'
@@ -1,4 +1,4 @@
import { NetworkProtocol } from '@core/network'
import { NetworkProtocol } from '@core/network/enums'

export function isShimmerNetworkProtocol(networkProtocol: NetworkProtocol): boolean {
return networkProtocol === NetworkProtocol.Shimmer
Expand Down
@@ -1,4 +1,5 @@
import { writable } from 'svelte/store'

import { INft } from '../interfaces'

export const allAccountNfts = writable<INft[][]>([])
@@ -1,5 +1,7 @@
import { selectedAccount } from '@core/account'
import { derived, Readable } from 'svelte/store'

import { selectedAccount } from '@core/account/stores'

Comment on lines +2 to +4
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reasons for the empty lines?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Matt added this, since the import comes from another module

import { INft } from '../interfaces'
import { allAccountNfts } from './all-account-nfts.store'

Expand Down
17 changes: 11 additions & 6 deletions packages/shared/lib/core/nfts/utils/parseNftMetadata.ts
@@ -1,10 +1,15 @@
import { networkHrp } from '@core/network'
import { IIrc27Metadata, MimeType, SupportedMimeType } from '@core/nfts'
import { isValidUri, validateBech32Address } from '@core/utils'
import { Converter } from '@core/utils/convert'
import { TokenStandard } from '@core/wallet'
import { get } from 'svelte/store'

import { networkHrp } from '@core/network/stores'
import { isValidUri } from '@core/utils/validation'
import { validateBech32Address } from '@core/utils/crypto'
import { Converter } from '@core/utils/convert'
import { TokenStandard } from '@core/wallet/enums'

import { SupportedMimeType } from '../enums'
import { IIrc27Metadata } from '../interfaces'
import { MimeType } from '../types'

export function parseNftMetadata(metadata: string): IIrc27Metadata {
try {
const convertedData = Converter.hexToUtf8(metadata)
Expand Down Expand Up @@ -57,7 +62,7 @@ function validate(data: IIrc27Metadata): void {
}

function validateRoyalties(royalties: unknown): void {
const isKeysValid = Object.keys(royalties).every((key) => !validateBech32Address(get(networkHrp), key))
const isKeysValid = Object.keys(royalties).every((key) => validateBech32Address(get(networkHrp), key))
if (!isKeysValid) {
throw `Invalid royalty address, must be a valid ${get(networkHrp)} address where royalties will be sent to.`
}
Tuditi marked this conversation as resolved.
Show resolved Hide resolved
Expand Down