From bc5fabeb924de734391cab6221e72650571705a7 Mon Sep 17 00:00:00 2001 From: Max Korsunov Date: Fri, 10 Jan 2025 10:12:26 +0400 Subject: [PATCH 1/3] feat(extension): #252: asset list (#259) * feat(extension): #252: add assets table to the main popup screen * chore: changeset * fix: #252: fix review comments * fix: possible height fix --- .changeset/strong-carrots-protect.md | 6 ++ .../src/routes/popup/home/assets-table.tsx | 88 +++++++++++++++++++ .../extension/src/routes/popup/home/index.tsx | 38 +++++--- .../src/routes/popup/popup-layout.tsx | 2 +- packages/tailwind-config/index.ts | 4 +- .../components/ui/select/select-account.tsx | 5 +- packages/ui/components/ui/table/index.tsx | 81 +++++++++++++++++ 7 files changed, 207 insertions(+), 17 deletions(-) create mode 100644 .changeset/strong-carrots-protect.md create mode 100644 apps/extension/src/routes/popup/home/assets-table.tsx create mode 100644 packages/ui/components/ui/table/index.tsx diff --git a/.changeset/strong-carrots-protect.md b/.changeset/strong-carrots-protect.md new file mode 100644 index 00000000..68deabff --- /dev/null +++ b/.changeset/strong-carrots-protect.md @@ -0,0 +1,6 @@ +--- +'chrome-extension': minor +'@repo/ui': minor +--- + +Add AssetsTable to the home screen of the extension diff --git a/apps/extension/src/routes/popup/home/assets-table.tsx b/apps/extension/src/routes/popup/home/assets-table.tsx new file mode 100644 index 00000000..e28173b4 --- /dev/null +++ b/apps/extension/src/routes/popup/home/assets-table.tsx @@ -0,0 +1,88 @@ +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from '@repo/ui/components/ui/table'; +import { ValueViewComponent } from '@repo/ui/components/ui/value'; +import { ValueView } from '@penumbra-zone/protobuf/penumbra/core/asset/v1/asset_pb'; +import { getDisplayDenomFromView, getEquivalentValues } from '@penumbra-zone/getters/value-view'; +import { getMetadataFromBalancesResponse } from '@penumbra-zone/getters/balances-response'; +import { asValueView } from '@penumbra-zone/getters/equivalent-value'; +import { useQuery } from '@tanstack/react-query'; +import { viewClient } from '../../../clients'; + +const EquivalentValues = ({ valueView }: { valueView?: ValueView }) => { + const equivalentValuesAsValueViews = (getEquivalentValues.optional(valueView) ?? []).map( + asValueView, + ); + + return ( +
+ {equivalentValuesAsValueViews.map(equivalentValueAsValueView => ( + + ))} +
+ ); +}; + +export interface AssetsTableProps { + account: number; +} + +export const AssetsTable = ({ account }: AssetsTableProps) => { + const { + data: balances, + isLoading, + error, + } = useQuery({ + queryKey: ['balances', account], + staleTime: Infinity, + queryFn: async () => { + try { + const balances = await Array.fromAsync(viewClient.balances({ accountFilter: { account } })); + balances.sort((a, b) => { + const aScore = getMetadataFromBalancesResponse.optional(a)?.priorityScore ?? 0n; + const bScore = getMetadataFromBalancesResponse.optional(b)?.priorityScore ?? 0n; + return Number(bScore - aScore); + }); + return balances; + } catch (_) { + return []; + } + }, + }); + + if (isLoading || error || !balances?.length) { + return null; + } + + return ( + + + + Balance + Value + + + + {balances.map((assetBalance, index) => ( + + + + + + + + + ))} + +
+ ); +}; diff --git a/apps/extension/src/routes/popup/home/index.tsx b/apps/extension/src/routes/popup/home/index.tsx index 392e22d9..4f18ccf0 100644 --- a/apps/extension/src/routes/popup/home/index.tsx +++ b/apps/extension/src/routes/popup/home/index.tsx @@ -1,15 +1,17 @@ +import { Address, FullViewingKey } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; import { SelectAccount } from '@repo/ui/components/ui/select'; +import { getAddressByIndex, getEphemeralByIndex } from '@penumbra-zone/wasm/keys'; +import { Wallet } from '@penumbra-zone/types/wallet'; import { IndexHeader } from './index-header'; import { useStore } from '../../../state'; import { BlockSync } from './block-sync'; import { localExtStorage } from '../../../storage/local'; import { getActiveWallet } from '../../../state/wallets'; import { needsLogin, needsOnboard } from '../popup-needs'; -import { Address, FullViewingKey } from '@penumbra-zone/protobuf/penumbra/core/keys/v1/keys_pb'; -import { getAddressByIndex, getEphemeralByIndex } from '@penumbra-zone/wasm/keys'; -import { Wallet } from '@penumbra-zone/types/wallet'; import { ValidateAddress } from './validate-address'; import { FrontendLink } from './frontend-link'; +import { AssetsTable } from './assets-table'; +import { useState } from 'react'; export interface PopupLoaderData { fullSyncHeight?: number; @@ -45,23 +47,35 @@ const getAddrByIndex = export const PopupIndex = () => { const activeWallet = useStore(getActiveWallet); + const [index, setIndex] = useState(0); return ( <> - +
+
-
- +
+ -
- {activeWallet && } -
+
+ - +
+ {activeWallet && ( + + )} +
-
+ - + + + +
); diff --git a/apps/extension/src/routes/popup/popup-layout.tsx b/apps/extension/src/routes/popup/popup-layout.tsx index 1d609adb..12a222a3 100644 --- a/apps/extension/src/routes/popup/popup-layout.tsx +++ b/apps/extension/src/routes/popup/popup-layout.tsx @@ -16,7 +16,7 @@ export const PopupLayout = () => { usePopupReady(); return ( -
+
); diff --git a/packages/tailwind-config/index.ts b/packages/tailwind-config/index.ts index 1a7e6658..71483f6a 100644 --- a/packages/tailwind-config/index.ts +++ b/packages/tailwind-config/index.ts @@ -151,9 +151,9 @@ export default { linear-gradient( color-mix(in srgb, var(--charcoal) 80%, transparent), color-mix(in srgb, var(--charcoal) 80%, transparent) - ), - url('penumbra-logo.svg') + ) `, + logoImg: `url('penumbra-logo.svg')`, }, }, }, diff --git a/packages/ui/components/ui/select/select-account.tsx b/packages/ui/components/ui/select/select-account.tsx index 245572dd..2f058290 100644 --- a/packages/ui/components/ui/select/select-account.tsx +++ b/packages/ui/components/ui/select/select-account.tsx @@ -13,14 +13,15 @@ import { Box } from '../box'; export interface SelectAccountProps { getAddrByIndex: (index: number, ephemeral: boolean) => Promise
| Address; + index: number; + setIndex: (index: number) => void; } /** * Renders an account address, along with a switcher to choose a different * account index. Also allows the user to view a one-time IBC deposit address. */ -export const SelectAccount = ({ getAddrByIndex }: SelectAccountProps) => { - const [index, setIndex] = useState(0); +export const SelectAccount = ({ getAddrByIndex, index, setIndex }: SelectAccountProps) => { const [ephemeral, setEphemeral] = useState(false); const [address, setAddress] = useState
(); diff --git a/packages/ui/components/ui/table/index.tsx b/packages/ui/components/ui/table/index.tsx new file mode 100644 index 00000000..72ddd187 --- /dev/null +++ b/packages/ui/components/ui/table/index.tsx @@ -0,0 +1,81 @@ +import * as React from 'react'; +import { cn } from '../../../lib/utils'; + +const Table = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +Table.displayName = 'Table'; + +const TableHeader = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableHeader.displayName = 'TableHeader'; + +const TableBody = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableBody.displayName = 'TableBody'; + +const TableFooter = React.forwardRef< + HTMLTableSectionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableFooter.displayName = 'TableFooter'; + +const TableRow = React.forwardRef>( + ({ className, ...props }, ref) => ( + + ), +); +TableRow.displayName = 'TableRow'; + +const TableHead = React.forwardRef< + HTMLTableCellElement, + React.ThHTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableHead.displayName = 'TableHead'; + +const TableCell = React.forwardRef< + HTMLTableCellElement, + React.TdHTMLAttributes +>(({ className, ...props }, ref) => ( + +)); +TableCell.displayName = 'TableCell'; + +const TableCaption = React.forwardRef< + HTMLTableCaptionElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => ( +
+)); +TableCaption.displayName = 'TableCaption'; + +export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption }; From 48245aa6bd41f94fa61d863f212de47be0471604 Mon Sep 17 00:00:00 2001 From: Tal Derei <70081547+TalDerei@users.noreply.github.com> Date: Wed, 22 Jan 2025 19:26:33 -0800 Subject: [PATCH 2/3] registry: default frontend selection (#270) * default frontend selection * bump registry version to v13.0 * downgrade to patch version 12.0.1 * linting * upgrade registry dep to minor version 12.1.0 * lockfile --- apps/extension/package.json | 2 +- .../routes/page/onboarding/password/utils.ts | 20 ++++++++--- packages/context/package.json | 2 +- packages/ui/package.json | 2 +- pnpm-lock.yaml | 34 +++++++++---------- 5 files changed, 36 insertions(+), 24 deletions(-) diff --git a/apps/extension/package.json b/apps/extension/package.json index ee6f54a2..461b5303 100644 --- a/apps/extension/package.json +++ b/apps/extension/package.json @@ -18,7 +18,7 @@ "@bufbuild/protobuf": "^1.x", "@connectrpc/connect": "^1.x", "@connectrpc/connect-web": "^1.x", - "@penumbra-labs/registry": "^12.0.0", + "@penumbra-labs/registry": "^12.1.0", "@penumbra-zone/bech32m": "11.0.0", "@penumbra-zone/client": "22.0.0", "@penumbra-zone/crypto-web": "32.0.0", diff --git a/apps/extension/src/routes/page/onboarding/password/utils.ts b/apps/extension/src/routes/page/onboarding/password/utils.ts index b49e5205..52bb8f73 100644 --- a/apps/extension/src/routes/page/onboarding/password/utils.ts +++ b/apps/extension/src/routes/page/onboarding/password/utils.ts @@ -2,7 +2,7 @@ import { Location } from 'react-router-dom'; import { LocationState, SEED_PHRASE_ORIGIN } from './types'; import { PagePath } from '../../paths'; import { usePageNav } from '../../../../utils/navigate'; -import { ChainRegistryClient } from '@penumbra-labs/registry'; +import { ChainRegistryClient, EntityMetadata } from '@penumbra-labs/registry'; import { sample } from 'lodash'; import { createPromiseClient } from '@connectrpc/connect'; import { createGrpcWebTransport } from '@connectrpc/connect-web'; @@ -34,8 +34,20 @@ const DEFAULT_TRANSPORT_OPTS = { timeoutMs: 5000 }; export const setOnboardingValuesInStorage = async (seedPhraseOrigin: SEED_PHRASE_ORIGIN) => { const chainRegistryClient = new ChainRegistryClient(); const { rpcs, frontends } = await chainRegistryClient.remote.globals(); - const randomFrontend = sample(frontends); - if (!randomFrontend) { + + // Define a canconcial default frontend + const defaultFront = 'Radiant Commons'; + + let selectedFrontend: EntityMetadata | undefined = frontends.find( + frontend => frontend.name === defaultFront, + ); + + // If default frontend is not found, randomly select a frontend + if (!selectedFrontend) { + selectedFrontend = sample(frontends); + } + + if (!selectedFrontend) { throw new Error('Registry missing frontends'); } @@ -57,7 +69,7 @@ export const setOnboardingValuesInStorage = async (seedPhraseOrigin: SEED_PHRASE const { numeraires } = await chainRegistryClient.remote.get(appParameters.chainId); await localExtStorage.set('grpcEndpoint', rpc); - await localExtStorage.set('frontendUrl', randomFrontend.url); + await localExtStorage.set('frontendUrl', selectedFrontend.url); await localExtStorage.set( 'numeraires', numeraires.map(n => n.toJsonString()), diff --git a/packages/context/package.json b/packages/context/package.json index 96a32985..ae4f542a 100644 --- a/packages/context/package.json +++ b/packages/context/package.json @@ -17,7 +17,7 @@ }, "peerDependencies": { "@bufbuild/protobuf": "^1.x", - "@penumbra-labs/registry": "^12.0.0", + "@penumbra-labs/registry": "^12.1.0", "@penumbra-zone/bech32m": "11.0.0", "@penumbra-zone/crypto-web": "32.0.0", "@penumbra-zone/getters": "21.0.0", diff --git a/packages/ui/package.json b/packages/ui/package.json index 881bdead..05a19e28 100644 --- a/packages/ui/package.json +++ b/packages/ui/package.json @@ -29,7 +29,7 @@ "dependencies": { "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", - "@penumbra-labs/registry": "^12.0.0", + "@penumbra-labs/registry": "^12.1.0", "@penumbra-zone/bech32m": "11.0.0", "@penumbra-zone/getters": "21.0.0", "@penumbra-zone/perspective": "42.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index cf540471..a7164fd7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -87,8 +87,8 @@ importers: specifier: ^1.x version: 1.4.0(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.4.0(@bufbuild/protobuf@1.10.0)) '@penumbra-labs/registry': - specifier: ^12.0.0 - version: 12.0.0 + specifier: ^12.1.0 + version: 12.1.0 '@penumbra-zone/bech32m': specifier: 11.0.0 version: 11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) @@ -115,10 +115,10 @@ importers: version: link:../../packages/query '@penumbra-zone/services': specifier: 47.0.0 - version: 47.0.0(6fps6z5uuk6epgzufahiywxosy) + version: 47.0.0(a4kvhbyq3zzvfqzovgkdkkljkq) '@penumbra-zone/storage': specifier: 42.0.0 - version: 42.0.0(l65mk6ilmsmeu3y7rncvtveyd4) + version: 42.0.0(gurpzwyiul6ia5cgcso2wz7pke) '@penumbra-zone/transport-chrome': specifier: 8.0.1 version: 8.0.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.4.0(@bufbuild/protobuf@1.10.0))(@penumbra-zone/transport-dom@7.5.0) @@ -256,8 +256,8 @@ importers: specifier: ^1.x version: 1.10.0 '@penumbra-labs/registry': - specifier: ^12.0.0 - version: 12.0.0 + specifier: ^12.1.0 + version: 12.1.0 '@penumbra-zone/bech32m': specifier: 11.0.0 version: 11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) @@ -281,10 +281,10 @@ importers: version: link:../query '@penumbra-zone/services': specifier: 47.0.0 - version: 47.0.0(6fps6z5uuk6epgzufahiywxosy) + version: 47.0.0(a4kvhbyq3zzvfqzovgkdkkljkq) '@penumbra-zone/storage': specifier: 42.0.0 - version: 42.0.0(l65mk6ilmsmeu3y7rncvtveyd4) + version: 42.0.0(gurpzwyiul6ia5cgcso2wz7pke) '@penumbra-zone/transport-chrome': specifier: 8.0.1 version: 8.0.1(@bufbuild/protobuf@1.10.0)(@connectrpc/connect@1.4.0(@bufbuild/protobuf@1.10.0))(@penumbra-zone/transport-dom@7.5.0) @@ -369,8 +369,8 @@ importers: specifier: ^11.14.0 version: 11.14.0(@emotion/react@11.14.0(@types/react@18.3.18)(react@18.3.1))(@types/react@18.3.18)(react@18.3.1) '@penumbra-labs/registry': - specifier: ^12.0.0 - version: 12.0.0 + specifier: ^12.1.0 + version: 12.1.0 '@penumbra-zone/bech32m': specifier: 11.0.0 version: 11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) @@ -1639,8 +1639,8 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@penumbra-labs/registry@12.0.0': - resolution: {integrity: sha512-fQ4onHovusiOZL2nhoCoEo+/sQovK9NAQmNvehIw7Q0dhw9InXIZBTUSOKujhvyrcca+vA9FsaHWr0DSv/pDsw==} + '@penumbra-labs/registry@12.1.0': + resolution: {integrity: sha512-hBzCCJ9bykaJ86fW3J9IRjVIXuxGEsidTIhYwuLYEKpYkAhfHe3J4M5LR6gVU5XoqIx39QfeYf9j0cFIwHZlQQ==} '@penumbra-zone/bech32m@11.0.0': resolution: {integrity: sha512-GXBawCDEaEMMYSo8WIbpM0l8NbJC9gZMHS5ttDPNH1SC7LfMGzjvZeMHvNulNV3cLZJSrmxxTIbg78QKWNsldw==} @@ -9426,7 +9426,7 @@ snapshots: '@open-draft/until@2.1.0': {} - '@penumbra-labs/registry@12.0.0': {} + '@penumbra-labs/registry@12.1.0': {} '@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0))': dependencies: @@ -9496,7 +9496,7 @@ snapshots: dependencies: '@bufbuild/protobuf': 1.10.0 - '@penumbra-zone/services@47.0.0(6fps6z5uuk6epgzufahiywxosy)': + '@penumbra-zone/services@47.0.0(a4kvhbyq3zzvfqzovgkdkkljkq)': dependencies: '@bufbuild/protobuf': 1.10.0 '@connectrpc/connect': 1.4.0(@bufbuild/protobuf@1.10.0) @@ -9504,15 +9504,15 @@ snapshots: '@penumbra-zone/crypto-web': 32.0.0(@penumbra-zone/types@27.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/getters@21.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0))) '@penumbra-zone/getters': 21.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) '@penumbra-zone/protobuf': 7.0.0(@bufbuild/protobuf@1.10.0) - '@penumbra-zone/storage': 42.0.0(l65mk6ilmsmeu3y7rncvtveyd4) + '@penumbra-zone/storage': 42.0.0(gurpzwyiul6ia5cgcso2wz7pke) '@penumbra-zone/transport-dom': 7.5.0 '@penumbra-zone/types': 27.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/getters@21.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) '@penumbra-zone/wasm': 36.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0))(@penumbra-zone/types@27.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/getters@21.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0))) - '@penumbra-zone/storage@42.0.0(l65mk6ilmsmeu3y7rncvtveyd4)': + '@penumbra-zone/storage@42.0.0(gurpzwyiul6ia5cgcso2wz7pke)': dependencies: '@bufbuild/protobuf': 1.10.0 - '@penumbra-labs/registry': 12.0.0 + '@penumbra-labs/registry': 12.1.0 '@penumbra-zone/bech32m': 11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) '@penumbra-zone/getters': 21.0.0(@bufbuild/protobuf@1.10.0)(@penumbra-zone/bech32m@11.0.0(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)))(@penumbra-zone/protobuf@7.0.0(@bufbuild/protobuf@1.10.0)) '@penumbra-zone/protobuf': 7.0.0(@bufbuild/protobuf@1.10.0) From 0a6edc7bf897432e9ac0ab10b951ff92908c6ce8 Mon Sep 17 00:00:00 2001 From: Tal Derei <70081547+TalDerei@users.noreply.github.com> Date: Thu, 23 Jan 2025 16:27:23 -0800 Subject: [PATCH 3/3] feat: idle syncing (#269) * init background syncing * satisfy linter * listener logs * less noisy logging --- apps/extension/public/manifest.json | 2 +- apps/extension/src/service-worker.ts | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/apps/extension/public/manifest.json b/apps/extension/public/manifest.json index f5a84eb3..38e01a08 100644 --- a/apps/extension/public/manifest.json +++ b/apps/extension/public/manifest.json @@ -40,7 +40,7 @@ "matches": [""] } ], - "permissions": ["storage", "unlimitedStorage", "offscreen"], + "permissions": ["storage", "unlimitedStorage", "offscreen", "alarms"], "host_permissions": [""], "externally_connectable": { "matches": [""] diff --git a/apps/extension/src/service-worker.ts b/apps/extension/src/service-worker.ts index 31af0e3a..b8b45792 100644 --- a/apps/extension/src/service-worker.ts +++ b/apps/extension/src/service-worker.ts @@ -96,3 +96,17 @@ const handler = await backOff(() => initHandler(), { }); CRSessionManager.init(PRAX, handler); + +// https://developer.chrome.com/docs/extensions/reference/api/alarms +void chrome.alarms.create('blockSync', { + periodInMinutes: 30, + delayInMinutes: 0, +}); + +chrome.alarms.onAlarm.addListener(alarm => { + if (alarm.name === 'blockSync') { + if (globalThis.__DEV__) { + console.info('Background sync scheduled'); + } + } +});