Skip to content

Commit

Permalink
Merge branch 'develop' into dependabot/npm_and_yarn/packages/desktop/…
Browse files Browse the repository at this point in the history
…electron-30.0.1
  • Loading branch information
Tuditi authored May 14, 2024
2 parents 6c24660 + 653082e commit 22b0fce
Show file tree
Hide file tree
Showing 20 changed files with 114 additions and 140 deletions.
2 changes: 1 addition & 1 deletion packages/desktop/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

The following **must** be installed on all platforms:

- [Node.js](https://nodejs.org/en/) 18.15.0+
- [Node.js](https://nodejs.org/en/) 20.10.0+
- [Yarn](https://classic.yarnpkg.com/en/docs/install)
- [Rust](https://www.rust-lang.org/tools/install)

Expand Down
15 changes: 4 additions & 11 deletions packages/desktop/components/modals/FilterModal.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,21 @@
bind:this={modal}
on:close={closeFilters}
position={{ absolute: true, right: '0', top: '30px' }}
classes="overflow-visible"
classes="flex !overflow-hidden"
autoMaxHeight
>
<filter-modal>
<filter-modal class="flex flex-col w-64 rounded-[inherit]">
<filter-modal-header
class="flex flex-row items-center justify-between bg-surface-1 dark:bg-transparent px-4 py-2 rounded-t-xl"
class="flex-none flex flex-row items-center justify-between bg-surface-1 dark:bg-transparent px-4 py-2 rounded-t-xl"
>
<Button text={localize('actions.clear')} on:click={onClearClick} size="xs" variant="outlined" />
<Text align="center">
{localize('filters.title')}
</Text>
<Button text={localize('actions.apply')} on:click={onConfirmClick} size="xs" disabled={!isChanged} />
</filter-modal-header>
<filter-modal-slot class="block">
<filter-modal-slot class="flex-1 h-0 overflow-y-scroll">
<slot />
</filter-modal-slot>
</filter-modal>
</Modal>

<style lang="scss">
filter-modal {
@apply block w-64;
border-radius: inherit;
}
</style>
1 change: 1 addition & 0 deletions packages/desktop/components/popup/Popup.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@
bind:this={popupContent}
class:relative
class="popup {size}"
class:-mt-7={IS_WINDOWS}
>
<svelte:component this={POPUP_MAP[id]} {...props} />
{#if !hideClose}
Expand Down
37 changes: 15 additions & 22 deletions packages/desktop/components/popup/PopupTemplate.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,13 @@
</script>

<popup-template>
<div class="popup-banner">
<div class="popup-banner overflow-hidden rounded-t-[32px]">
<slot name="banner" />
</div>
<popop-content class="flex flex-col gap-6 p-8 {$$slots.banner ? 'pt-4' : ''}">
<popup-content class="max-h-[90vh] flex flex-col gap-6 p-8" class:pt-4={$$slots.banner}>
{#if title || $$slots.menu || $$slots.description || description}
<popup-header class="flex flex-col space-y-2.5">
<title-row class="flex flex-row space-x-2 justify-between">
<popup-header class="flex-none flex flex-col gap-2.5">
<title-row class="flex flex-row gap-2 mr-7 justify-between">
{#if title}<Text type="h6" truncate>{title}</Text>{/if}
{#if $$slots.menu}
<slot name="menu" class="flex-0" />
Expand All @@ -76,13 +76,15 @@
{/if}
</popup-header>
{/if}
{#if $$slots.default}
<slot />
{:else if $$slots.content}
<slot name="content" />
{/if}
<div class="flex-1 h-0 flex flex-col">
{#if $$slots.default}
<slot />
{:else if $$slots.content}
<slot name="content" />
{/if}
</div>
{#if backButton || continueButton}
<popup-footer class="flex flex-row space-x-3">
<popup-footer class="flex-none flex flex-row gap-3">
{#if backButton}
<Button
type="button"
Expand All @@ -91,7 +93,7 @@
disabled={busy || _backButton.disabled}
width="full"
form={_backButton.type === 'submit' ? _backButton.form : undefined}
on:click={_backButton.type === 'button' && _backButton.onClick}
on:click={_backButton.type === 'button' ? _backButton.onClick : undefined}
{..._backButton.restProps}
/>
{/if}
Expand All @@ -105,20 +107,11 @@
disabled={_continueButton.disabled}
{busy}
width="full"
on:click={_continueButton.type === 'button' && _continueButton.onClick}
on:click={_continueButton.type === 'button' ? _continueButton.onClick : undefined}
{..._continueButton.restProps}
/>
{/if}
</popup-footer>
{/if}
</popop-content>
</popup-content>
</popup-template>

<style lang="postcss">
.popup-banner {
@apply overflow-hidden rounded-t-[32px];
}
title-row {
margin-right: 28px;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
onMount(() => {
getNodeInfo(node?.url, node?.auth)
.then((nodeInfoResponse) => {
nodeInfo = nodeInfoResponse.nodeInfo
nodeInfo = nodeInfoResponse?.nodeInfo
})
.catch((err) => {
closePopup()
Expand Down
21 changes: 13 additions & 8 deletions packages/desktop/lib/electron/apis/wallet.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,21 @@ const sdkUtilsMethods = bindSdkUtilsMethods()

export default {
...sdkUtilsMethods,
async getNodeInfo(managerId: number, url: string, auth: IAuth): Promise<INodeInfoResponse> {
const manager = profileManagers[managerId]
const client = await manager.getClient()
async getNodeInfo(managerId: number, url: string, auth: IAuth): Promise<INodeInfoResponse | undefined> {
try {
const manager = profileManagers[managerId]
const client = await manager.getClient()

const nodeUrl = url ?? (await client.getNode()).url
const nodeInfo = await client.getNodeInfo(nodeUrl, auth)
const nodeUrl = url ?? (await client.getNode()).url
const nodeInfo = await client.getNodeInfo(nodeUrl, auth)

return {
url: nodeUrl,
nodeInfo,
return {
url: nodeUrl,
nodeInfo,
}
} catch (err) {
console.error(err)
return undefined
}
},
createWallet(id: string, options: WalletOptions): Wallet {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,15 @@
disabled: !selectedToken || tokenError,
}}
>
<div class="space-y-4">
{#if $networks.length > 1}
<SelectInput bind:selected={selectedOption} {options} />
{/if}
<SearchInput bind:value={searchValue} />
<div class="-mr-3">
<token-list class="w-full flex flex-col">
<div class="flex-1 h-0 flex flex-col gap-4">
<div class="flex-none flex flex-col gap-4">
{#if $networks.length > 1}
<SelectInput bind:selected={selectedOption} {options} />
{/if}
<SearchInput bind:value={searchValue} />
</div>
<div class="-mr-3 overflow-y-scroll">
<token-list class="flex flex-col p-0.5 pr-1.5 gap-2">
{#each tokenList as token}
{@const selected = selectedToken?.id === token.id && selectedToken?.networkId === token?.networkId}
{@const error = selected ? Boolean(tokenError) : false}
Expand All @@ -189,16 +191,9 @@
</token-list>
</div>
{#if tokenError}
<Alert variant="danger" text={tokenError} />
<div class="flex-none">
<Alert variant="danger" text={tokenError} />
</div>
{/if}
</div>
</PopupTemplate>

<style lang="postcss">
token-list {
max-height: 400px;
overflow-y: scroll;
@apply p-0.5 pr-1.5;
@apply gap-2;
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
formError = localize('error.node.unabledToConnect')
} else if (err?.message === 'error.node.differentNetwork') {
formError = localize('error.node.differentNetwork')
} else if (err?.message === 'error.node.invalidNode') {
formError = localize('error.node.invalidNode')
} else if (err?.type !== 'validationError') {
showNotification({
variant: 'error',
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"author": "Bloom Labs Ltd <[email protected]>",
"license": "PolyForm Strict License 1.0.0",
"dependencies": {
"@bloomwalletio/ui": "0.20.21",
"@bloomwalletio/ui": "0.20.22",
"@ethereumjs/common": "4.3.0",
"@ethereumjs/rlp": "5.0.2",
"@ethereumjs/tx": "5.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,7 @@
return Promise.reject({ type: 'validationError', error: formError })
}
const errorUrlValidity = checkNodeUrlValidity(
currentClientOptions?.nodes,
node.url,
$activeProfile.features.developer
)
const errorUrlValidity = checkNodeUrlValidity(currentClientOptions?.nodes, node.url, false)
if (errorUrlValidity) {
formError = localize(errorUrlValidity) ?? ''
return Promise.reject({ type: 'validationError', error: formError })
Expand All @@ -84,6 +80,10 @@
if (options.checkNodeInfo) {
try {
nodeInfoResponse = await getNodeInfo(node.url)
if (!nodeInfoResponse?.nodeInfo) {
formError = localize('error.node.invalidNode')
return Promise.reject({ type: 'validationError', error: formError })
}
} catch (err) {
formError = localize('error.node.unabledToConnect')
return Promise.reject({ type: 'validationError', error: formError })
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ export async function getNodeInfoWhileLoggedOut(url: string, auth: IAuth): Promi
{ stronghold: { snapshotPath: `${storagePath}/wallet.stronghold` } }
)
nodeInfoResponse = await api.getNodeInfo(manager?.id, url, auth)

if (!nodeInfoResponse) {
throw new Error('error.node.invalidNode')
}

return nodeInfoResponse
} catch (error) {
return Promise.reject(error)
} finally {
if (manager) {
api.deleteWallet(manager?.id)
await manager.destroy()
}
if (storagePath) {
await Platform.removeProfileFolder(storagePath)
}
await cleanupTemporaryProfile(manager, storagePath)
}
}

async function cleanupTemporaryProfile(
manager: IProfileManager | undefined,
storagePath: string | undefined
): Promise<void> {
if (manager) {
api.deleteWallet(manager?.id)
await manager.destroy()
}
if (storagePath) {
await Platform.removeProfileFolder(storagePath)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@ import { INodeInfoResponse } from '@core/network/interfaces/node-info-response.i
import { getProfileManager } from '../stores'
import { api } from '../api'

export function getNodeInfo(url?: string, auth?: IAuth): Promise<INodeInfoResponse> | undefined {
export async function getNodeInfo(url?: string, auth?: IAuth): Promise<INodeInfoResponse | undefined> {
const id = getProfileManager()?.id
if (id) {
return api.getNodeInfo(id, url, auth)
}
return id ? api.getNodeInfo(id, url, auth) : undefined
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export interface IApi {
getAccount(profileManagerId: string, index: number): Promise<IAccount>
getAccounts(profileManagerId: string): Promise<IAccount[]>
getClient(profileManagerId: string): Promise<Client>
getNodeInfo(profileManagerId: string, url?: string, auth?: IAuth): Promise<INodeInfoResponse>
getNodeInfo(profileManagerId: string, url?: string, auth?: IAuth): Promise<INodeInfoResponse | undefined>
getSecretManager(profileManagerId: string): Promise<ISecretManager>
recoverAccounts(profileManagerId: string, payload: RecoverAccountsPayload): Promise<IAccount[]>
migrateStrongholdSnapshotV2ToV3(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { get } from 'svelte/store'
import { localize } from '@core/i18n'
import { getAndUpdateNodeInfo } from '@core/network/actions'
import { activeProfile } from '@core/profile/stores'
import { NetworkNamespace, initializeNetworks } from '@core/network'

export async function checkAndInitializeActiveProfileNetwork(): Promise<void> {
const $activeProfile = get(activeProfile)
const existingNetwork = $activeProfile?.network
const nodeInfoResponse = await getAndUpdateNodeInfo(true)
if (!nodeInfoResponse) {
throw new Error(localize('error.network.mismatch'))
}

const networkIdFromNode = `${NetworkNamespace.Stardust}:${nodeInfoResponse?.nodeInfo?.protocol.networkName}`
if (existingNetwork?.id !== networkIdFromNode) {
throw new Error(localize('error.network.mismatch', { networkId: networkIdFromNode }))
}

if (existingNetwork?.protocol.version !== nodeInfoResponse?.nodeInfo?.protocol.version) {
throw new Error(localize('error.network.version.mismatch', { networkId: networkIdFromNode }))
}

initializeNetworks()
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export * from './checkActiveProfileAuth'
export * from './checkAndRemoveProfilePicture'
export * from './checkAndUpdateActiveProfileNetwork'
export * from './checkAndInitializeActiveProfileNetwork'
export * from './getBaseToken'
export * from './getNetworkHrp'
export * from './loadAccounts'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import {
} from '../../stores'
import { isLedgerProfile, waitForPreviousManagerToBeDestroyed } from '../../utils'
// import { checkAndRemoveProfilePicture } from './checkAndRemoveProfilePicture'
import { checkAndUpdateActiveProfileNetwork } from './checkAndUpdateActiveProfileNetwork'
import { checkAndInitializeActiveProfileNetwork } from './checkAndInitializeActiveProfileNetwork'
import { loadAccounts } from './loadAccounts'
import { logout } from './logout'
import { subscribeToWalletApiEventsForActiveProfile } from './subscribeToWalletApiEventsForActiveProfile'
Expand Down Expand Up @@ -67,7 +67,7 @@ export async function login(loginOptions?: ILoginOptions): Promise<void> {

// Step 2: get node info to check we have a synced node
incrementLoginProgress()
await checkAndUpdateActiveProfileNetwork()
await checkAndInitializeActiveProfileNetwork()

// Step 3: load accounts
incrementLoginProgress()
Expand Down
1 change: 1 addition & 0 deletions packages/shared/src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2026,6 +2026,7 @@
"timeNotSynced": "Device time is incorrect, unable to sync node.",
"unabledToConnect": "Unable to connect to the node",
"differentNetwork": "The node is located on a different network",
"invalidNode": "The URL is not a valid node",
"duplicateNodes": "Unable to add duplicate node",
"noCoinType": "No coin type specified"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/test/mocks/profile-manager.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export class ProfileManagerMock implements IProfileManager {
throw new Error('Method not implemented.')
}

getNodeInfo(url: string, auth?: IAuth): Promise<INodeInfoResponse> {
getNodeInfo(url: string, auth?: IAuth): Promise<INodeInfoResponse | undefined> {
return Promise.resolve({
nodeInfo: {
name: 'HORNET',
Expand Down
Loading

0 comments on commit 22b0fce

Please sign in to comment.