+
{cloneElement(svgElement, props)}
) : (
- cloneElement(svgElement, props)
+ cloneElement(svgElement, { ...props, onClick: onClickRef.current })
);
}
diff --git a/libs/icons/src/WalletFillIcon.tsx b/libs/icons/src/WalletFillIcon.tsx
new file mode 100644
index 0000000000..70b7548a88
--- /dev/null
+++ b/libs/icons/src/WalletFillIcon.tsx
@@ -0,0 +1,13 @@
+//
+import { createIcon } from './create-icon';
+import { IconBase } from './types';
+
+const WalletFillIcon = (props: IconBase) => {
+ return createIcon({
+ ...props,
+ d: 'M2.005 9h19a1 1 0 011 1v10a1 1 0 01-1 1h-18a1 1 0 01-1-1V9zm1-6h15v4h-16V4a1 1 0 011-1zm12 11v2h3v-2h-3z',
+ displayName: 'WalletFillIcon',
+ });
+};
+
+export default WalletFillIcon;
diff --git a/libs/icons/src/WalletLineIcon.tsx b/libs/icons/src/WalletLineIcon.tsx
index e4f9331871..951c7fb938 100644
--- a/libs/icons/src/WalletLineIcon.tsx
+++ b/libs/icons/src/WalletLineIcon.tsx
@@ -1,11 +1,12 @@
import { createIcon } from './create-icon';
import { IconBase } from './types';
-export const WalletLineIcon = (props: IconBase) => {
+const WalletLineIcon = (props: IconBase) => {
return createIcon({
...props,
- viewBox: '0 0 24 25',
- d: 'M18 7.5h3a1 1 0 011 1v12a1 1 0 01-1 1H3a1 1 0 01-1-1v-16a1 1 0 011-1h15v4zm-14 2v10h16v-10H4zm0-4v2h12v-2H4zm11 8h3v2h-3v-2z',
+ d: 'M18.005 7h3a1 1 0 011 1v12a1 1 0 01-1 1h-18a1 1 0 01-1-1V4a1 1 0 011-1h15v4zm-14 2v10h16V9h-16zm0-4v2h12V5h-12zm11 8h3v2h-3v-2z',
displayName: 'WalletLineIcon',
});
};
+
+export default WalletLineIcon;
diff --git a/libs/icons/src/chains/athena-orbit.svg b/libs/icons/src/chains/orbit-athena.svg
similarity index 100%
rename from libs/icons/src/chains/athena-orbit.svg
rename to libs/icons/src/chains/orbit-athena.svg
diff --git a/libs/icons/src/chains/demeter-orbit.svg b/libs/icons/src/chains/orbit-demeter.svg
similarity index 100%
rename from libs/icons/src/chains/demeter-orbit.svg
rename to libs/icons/src/chains/orbit-demeter.svg
diff --git a/libs/icons/src/chains/hermes-orbit.svg b/libs/icons/src/chains/orbit-hermes.svg
similarity index 100%
rename from libs/icons/src/chains/hermes-orbit.svg
rename to libs/icons/src/chains/orbit-hermes.svg
diff --git a/libs/icons/src/hooks/useDynamicSVGImport.tsx b/libs/icons/src/hooks/useDynamicSVGImport.tsx
index d1a80842fd..a43c74a796 100644
--- a/libs/icons/src/hooks/useDynamicSVGImport.tsx
+++ b/libs/icons/src/hooks/useDynamicSVGImport.tsx
@@ -32,7 +32,7 @@ export interface DynamicSVGImportOptions {
* @returns `error`, `loading` and `SvgIcon` in an object
*/
export function useDynamicSVGImport(
- name: string,
+ name?: string,
options: DynamicSVGImportOptions = {}
) {
const [importedIcon, setImportedIcon] = useState<
@@ -43,7 +43,11 @@ export function useDynamicSVGImport(
const { onCompleted, onError } = options;
- const _name = useMemo(() => name.trim().toLowerCase(), [name]);
+ const _name = useMemo(
+ () =>
+ typeof name === 'string' ? name.trim().toLowerCase() : 'placeholder',
+ [name]
+ );
const type = useMemo(() => options.type ?? 'token', [options]);
useEffect(() => {
diff --git a/libs/icons/src/index.ts b/libs/icons/src/index.ts
index 8ddb1ee19c..25de1e134f 100644
--- a/libs/icons/src/index.ts
+++ b/libs/icons/src/index.ts
@@ -1,4 +1,7 @@
+export { default as AccountCircleLineIcon } from './AccountCircleLineIcon';
export * from './AddBoxLineIcon';
+export * from './AddCircleFillIcon';
+export * from './AddCircleLineIcon';
export * from './ArrowDropDownFill';
export * from './ArrowDropUpFill';
export * from './ArrowLeft';
@@ -12,23 +15,24 @@ export * from './BlockIcon';
export * from './BookOpenLineIcon';
export * from './ChainIcon';
export * from './CheckboxBlankCircleLine';
-export * from './CheckboxCircleLine';
export * from './CheckboxCircleFill';
+export * from './CheckboxCircleLine';
export * from './CheckboxFill';
export * from './ChevronDown';
export * from './ChevronLeft';
export * from './ChevronRight';
export * from './ChevronUp';
+export { default as ClipboardLineIcon } from './ClipboardLineIcon';
export * from './Close';
export * from './CloseCircleLineIcon';
export * from './CoinIcon';
export * from './Common2Icon';
export * from './CommonWealth';
-export * from './Copyright';
-export * from './CornerDownRightLine';
-export * from './CopyLinkFill';
export * from './ContrastLine';
export * from './ContrastTwoLine';
+export * from './CopyLinkFill';
+export * from './Copyright';
+export * from './CornerDownRightLine';
export * from './DatabaseLine';
export * from './DefaultTokenIcon';
export * from './DeleteBinIcon';
@@ -50,11 +54,14 @@ export * from './FilterIcon2';
export * from './FlaskLineIcon';
export * from './FoldersFillIcon';
export * from './ForumIcon';
+export { default as GasStationFill } from './GasStationFill';
export * from './GithubFill';
export * from './GraphIcon';
export * from './GridFillIcon';
export * from './HamburgerMenu';
export * from './HelpLineIcon';
+export * from './IndeterminateCircleFillIcon';
+export * from './IndeterminateCircleLineIcon';
export * from './InformationLine';
export * from './InformationLineFill';
export * from './KeyIcon';
@@ -65,14 +72,17 @@ export * from './Mail';
export * from './Memu';
export * from './MoonLine';
export * from './QRCode';
-export * from './RefreshIcon';
+export { default as RefreshLineIcon } from './RefreshLineIcon';
export * from './Save';
export * from './SaveWithBg';
export * from './Search';
export * from './SendPlanLineIcon';
-export * from './ShieldedAssetDark';
-export * from './ShieldedAssetLight';
-export * from './ShieldKeyholeIcon';
+export { default as SettingsFillIcon } from './SettingsFillIcon';
+export { default as ShieldKeyholeFillIcon } from './ShieldKeyholeFillIcon';
+export * from './ShieldKeyholeLineIcon';
+export { default as ShieldKeyholeLineIcon } from './ShieldKeyholeLineIcon';
+export { default as ShieldedAssetIcon } from './ShieldedAssetIcon';
+export { default as ShieldedCheckLineIcon } from './ShieldedCheckLineIcon';
export * from './ShuffleLine';
export * from './SosLineIcon';
export * from './SparklingIcon';
@@ -87,20 +97,24 @@ export * from './TwitterFill';
export * from './UploadCloudIcon';
export * from './UsageGuideIcon';
export * from './UserStarFillIcon';
-export * from './WalletLineIcon';
+export { default as WalletFillIcon } from './WalletFillIcon';
+export { default as WalletLineIcon } from './WalletLineIcon';
export * from './YouTubeFill';
// Wallet icons
export * from './wallets';
// imagre URIs
-export * from './AlertFill';
export * from './Alert';
+export * from './AlertFill';
export * from './PartyFill';
// Tangle Icons
export * from './Tangle';
export * from './TangleIcon';
+export * from './StatusIndicator';
+export { default as StatusIndicator } from './StatusIndicator';
+
// Proposal Badges
export * from './ProposalBadge';
diff --git a/libs/icons/src/tokens/placeholder.svg b/libs/icons/src/tokens/placeholder.svg
new file mode 100644
index 0000000000..7f056bf011
--- /dev/null
+++ b/libs/icons/src/tokens/placeholder.svg
@@ -0,0 +1,11 @@
+
diff --git a/libs/icons/src/tokens/sep.svg b/libs/icons/src/tokens/sep.svg
new file mode 100644
index 0000000000..0e2c496b34
--- /dev/null
+++ b/libs/icons/src/tokens/sep.svg
@@ -0,0 +1,12 @@
+
diff --git a/libs/icons/src/types.ts b/libs/icons/src/types.ts
index 0efdc917f9..4b0992cdaa 100644
--- a/libs/icons/src/types.ts
+++ b/libs/icons/src/types.ts
@@ -26,5 +26,5 @@ export interface TokenIconBase
/**
* The symbol for the cryptocurrency to get the icon
*/
- name: string;
+ name?: string;
}
diff --git a/libs/note-manager/src/note-manager.ts b/libs/note-manager/src/note-manager.ts
index bc0472c61e..69aa9e9226 100644
--- a/libs/note-manager/src/note-manager.ts
+++ b/libs/note-manager/src/note-manager.ts
@@ -19,7 +19,6 @@ import {
import { hexToU8a } from '@webb-tools/utils';
import { Backend } from '@webb-tools/wasm-utils';
import { BehaviorSubject } from 'rxjs';
-import { parseUnits } from 'viem';
type DefaultNoteGenInput = Pick<
NoteGenInput,
@@ -149,7 +148,8 @@ export class NoteManager {
let currentAmount = ZERO_BIG_INT;
const currentNotes: Note[] = [];
- for (const note of notes) {
+ const sortedNotes = NoteManager.sortNotes(notes);
+ for (const note of sortedNotes) {
if (currentAmount >= targetAmount) {
break;
}
@@ -166,6 +166,41 @@ export class NoteManager {
return new Keypair(`0x${secrets[2]}`);
}
+ /**
+ * Sort the notes by indx in ascending order
+ * and the zero and undefined index will be put at the end
+ * @param notes the notes to sort
+ */
+ static sortNotes(notes: ReadonlyArray
): ReadonlyArray {
+ return notes.slice().sort((a, b) => {
+ // Place undefined values at the end
+ if (!a.note.index) {
+ return 1;
+ }
+
+ if (!b.note.index) {
+ return -1;
+ }
+
+ const aIndex = BigInt(a.note.index);
+ const bIndex = BigInt(b.note.index);
+
+ // Place zero values before undefined but after other numbers
+ if (aIndex === ZERO_BIG_INT) {
+ return 1;
+ }
+
+ if (bIndex === ZERO_BIG_INT) {
+ return -1;
+ }
+
+ // Regular ascending sort for other numbers
+ const idx = aIndex - bIndex;
+
+ return idx > 0 ? 1 : idx < 0 ? -1 : 0;
+ });
+ }
+
get $notesUpdated() {
return this.notesUpdatedSubject.asObservable();
}
@@ -291,6 +326,11 @@ export class NoteManager {
const noteIndex = targetNotes.findIndex(
(managedNote) => managedNote.serialize() === note.serialize()
);
+
+ if (noteIndex === -1) {
+ return;
+ }
+
targetNotes.splice(noteIndex, 1);
if (targetNotes.length != 0) {
this.notesMap.set(resourceIdStr, targetNotes);
diff --git a/libs/polkadot-api-provider/src/webb-provider.ts b/libs/polkadot-api-provider/src/webb-provider.ts
index ee2c2aa0a5..434e1739e5 100644
--- a/libs/polkadot-api-provider/src/webb-provider.ts
+++ b/libs/polkadot-api-provider/src/webb-provider.ts
@@ -423,7 +423,8 @@ export class WebbPolkadot
if (!leavesFromRelayers) {
tx?.next(TransactionState.FetchingLeaves, {
start: 0, // Dummy values
- currentRange: [0, 0], // Dummy values
+ current: 0, // Dummy values
+ end: 0,
});
// check if we already cached some values.
@@ -586,7 +587,7 @@ export class WebbPolkadot
const api = provider || this.api;
const treeData = await api.query.merkleTreeBn254.trees(treeId);
if (treeData.isNone) {
- throw WebbError.from(WebbErrorCodes.TreeNotFound);
+ throw WebbError.from(WebbErrorCodes.AnchorIdNotFound);
}
const treeMedata = treeData.unwrap();
diff --git a/libs/polkadot-api-provider/src/webb-provider/relayer-manager.ts b/libs/polkadot-api-provider/src/webb-provider/relayer-manager.ts
index c8888f8485..a9f95f049c 100644
--- a/libs/polkadot-api-provider/src/webb-provider/relayer-manager.ts
+++ b/libs/polkadot-api-provider/src/webb-provider/relayer-manager.ts
@@ -23,10 +23,10 @@ import { ChainType, Note, calculateTypedChainId } from '@webb-tools/sdk-core';
export class PolkadotRelayerManager extends WebbRelayerManager<'polkadot'> {
supportedPallet = 'VAnchorBn254';
- async mapRelayerIntoActive(
+ mapRelayerIntoActive(
relayer: OptionalRelayer,
typedChainId: number
- ): Promise {
+ ): OptionalActiveRelayer {
if (!relayer) {
return null;
}
diff --git a/libs/polkadot-api-provider/src/webb-provider/vanchor-actions.ts b/libs/polkadot-api-provider/src/webb-provider/vanchor-actions.ts
index da18cd9c31..1a1bd9ea9d 100644
--- a/libs/polkadot-api-provider/src/webb-provider/vanchor-actions.ts
+++ b/libs/polkadot-api-provider/src/webb-provider/vanchor-actions.ts
@@ -48,6 +48,8 @@ import { firstValueFrom } from 'rxjs';
import * as snarkjs from 'snarkjs';
import { ApiPromise } from '@polkadot/api';
+import type { HexString } from '@polkadot/util/types';
+import { NeighborEdge } from '@webb-tools/abstract-api-provider/vanchor/types';
import { bridgeStorageFactory } from '@webb-tools/browser-utils';
import { ZERO_BIG_INT } from '@webb-tools/dapp-config';
import assert from 'assert';
@@ -97,8 +99,6 @@ export class PolkadotVAnchorActions extends VAnchorActions<
payload: TransactionPayloadType,
wrapUnwrapAssetId: string
): Promise> | never {
- tx.next(TransactionState.PreparingTransaction, undefined);
-
// If the wrapUnwrapAssetId is empty, we use the bridge fungible token
if (!wrapUnwrapAssetId) {
const activeBridge = this.inner.state.activeBridge;
@@ -130,7 +130,7 @@ export class PolkadotVAnchorActions extends VAnchorActions<
activeRelayer: ActiveWebbRelayer,
txArgs: ParametersOfTransactMethod<'polkadot'>,
changeNotes: Note[]
- ): Promise {
+ ): Promise {
const [tx, anchorId, rawInputUtxos, rawOutputUtxos, ...restArgs] = txArgs;
const relayedVAnchorWithdraw = await activeRelayer.initWithdraw('vAnchor');
@@ -178,8 +178,6 @@ export class PolkadotVAnchorActions extends VAnchorActions<
},
} satisfies WithdrawRelayerArgs<'substrate', CMDSwitcher<'substrate'>>);
- let txHash = '';
-
// Subscribe to the relayer's transaction status.
relayedVAnchorWithdraw.watcher.subscribe(async ([results, message]) => {
switch (results) {
@@ -230,12 +228,9 @@ export class PolkadotVAnchorActions extends VAnchorActions<
// Send the transaction to the relayer.
relayedVAnchorWithdraw.send(relayTxPayload, chainId);
- const results = await relayedVAnchorWithdraw.await();
- if (results) {
- const [, message] = results;
- txHash = message ?? '';
- tx.txHash = txHash;
- }
+ const [, txHash = ''] = await relayedVAnchorWithdraw.await();
+ tx.txHash = txHash;
+ return ensureHex(txHash);
}
async transact(
@@ -306,6 +301,10 @@ export class PolkadotVAnchorActions extends VAnchorActions<
return ensureHex(txHash);
}
+ async waitForFinalization(hash: `0x${string}`): Promise {
+ throw WebbError.from(WebbErrorCodes.NotImplemented);
+ }
+
async isPairRegistered(
treeId: string,
account: string,
@@ -423,6 +422,13 @@ export class PolkadotVAnchorActions extends VAnchorActions<
};
}
+ async getLatestNeighborEdges(
+ fungibleId: number,
+ typedChainId?: number | undefined
+ ): Promise {
+ throw WebbError.from(WebbErrorCodes.NotImplemented);
+ }
+
// ------------------ Private ------------------
private async prepareDepositTransaction(
@@ -889,9 +895,9 @@ export class PolkadotVAnchorActions extends VAnchorActions<
): Promise<{ leafIndex: number; utxo: Utxo; amount: BN }> | never {
if (tx) {
tx.next(TransactionState.FetchingLeaves, {
- end: undefined,
- currentRange: [0, 1],
- start: 0,
+ start: 0, // Dummy value
+ end: 0, // Dummy value
+ current: 0, // Dummy value
});
}
@@ -915,7 +921,7 @@ export class PolkadotVAnchorActions extends VAnchorActions<
).unwrapOr(null);
if (!destTree) {
- throw WebbError.from(WebbErrorCodes.TreeNotFound);
+ throw WebbError.from(WebbErrorCodes.AnchorIdNotFound);
}
destRelayedRoot = destTree.root.toHex();
diff --git a/libs/react-hooks/src/currency/useBalancesFromNotes.tsx b/libs/react-hooks/src/currency/useBalancesFromNotes.tsx
index 861bbbcc1c..662a2ea2fa 100644
--- a/libs/react-hooks/src/currency/useBalancesFromNotes.tsx
+++ b/libs/react-hooks/src/currency/useBalancesFromNotes.tsx
@@ -5,14 +5,26 @@ import { CurrencyRole } from '@webb-tools/dapp-types';
import { ResourceId, calculateTypedChainId } from '@webb-tools/sdk-core';
import { hexToU8a } from '@webb-tools/utils';
import { useMemo } from 'react';
-import { formatUnits } from 'viem';
import { useNoteAccount } from '../useNoteAccount';
+/**
+ * The type of the balances from notes
+ * Record of balances (currencyId => Record)
+ */
+export type BalancesFromNotesType = {
+ [currencyId: number]: {
+ [typedChainId: number]: bigint;
+ };
+};
+
/**
* The return type of the useBalancesFromNotes
* Record of balances (currencyId => Record)
*/
-type UseBalancesFromNotesReturnType = Record>;
+type UseBalancesFromNotesReturnType = {
+ balances: BalancesFromNotesType;
+ initialized: boolean;
+};
/**
* Get the balances of each fungible currency
@@ -22,7 +34,7 @@ type UseBalancesFromNotesReturnType = Record>;
export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
const { apiConfig } = useWebContext();
- const { allNotes } = useNoteAccount();
+ const { allNotes, allNotesInitialized } = useNoteAccount();
const allFungibles = useMemo(() => {
return Currency.fromArray(
@@ -30,7 +42,7 @@ export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
);
}, [apiConfig]);
- return useMemo(() => {
+ const balances = useMemo(() => {
return Array.from(allNotes.entries()).reduce(
(acc, [resourceIdStr, notes]) => {
try {
@@ -74,13 +86,8 @@ export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
// then create a new record with the amount of the note
// on the current chain and return
if (!existedRecord) {
- const amount = +formatUnits(
- BigInt(note.amount),
- +note.denomination
- );
-
acc[fungible.id] = {
- [typedChainId]: amount,
+ [typedChainId]: BigInt(note.amount),
};
return;
@@ -94,14 +101,9 @@ export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
// then add the amount of the note to the existed amount
// and return
if (existedAmount) {
- const amount = +formatUnits(
- BigInt(note.amount),
- +note.denomination
- );
-
acc[fungible.id] = {
...existedRecord,
- [typedChainId]: existedAmount + amount,
+ [typedChainId]: existedAmount + BigInt(note.amount),
};
return;
@@ -110,14 +112,9 @@ export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
// If the amount on the current chain does not exist
// then create a new record with the amount of the note
// on the current chain and return
- const amount = +formatUnits(
- BigInt(note.amount),
- +note.denomination
- );
-
acc[fungible.id] = {
...existedRecord,
- [typedChainId]: amount,
+ [typedChainId]: BigInt(note.amount),
};
});
} catch (error) {
@@ -126,7 +123,12 @@ export const useBalancesFromNotes = (): UseBalancesFromNotesReturnType => {
return acc;
},
- {} as Record>
+ {} as BalancesFromNotesType
);
}, [allFungibles, allNotes, apiConfig]);
+
+ return {
+ balances,
+ initialized: allNotesInitialized,
+ };
};
diff --git a/libs/react-hooks/src/currency/useCurrenciesBalances.tsx b/libs/react-hooks/src/currency/useCurrenciesBalances.tsx
index b165b394ec..36e6743aa4 100644
--- a/libs/react-hooks/src/currency/useCurrenciesBalances.tsx
+++ b/libs/react-hooks/src/currency/useCurrenciesBalances.tsx
@@ -1,34 +1,48 @@
import { Currency } from '@webb-tools/abstract-api-provider';
import { useWebContext } from '@webb-tools/api-provider-environment';
import { calculateTypedChainId } from '@webb-tools/sdk-core';
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
+
+export type UseCurrenciesBalancesReturnType = {
+ balances: Record;
+ isLoading: boolean;
+};
/**
* Fetch the balances of the currencies list
* @param currencies the currencies list to fetching the balance
+ * @param typedChainId the typed chain id (if not provided, will use the active chain)
+ * @param address the address to fetch the balance (if not provided, will use the active account)
* @returns an object where the key is currency id and the value is currency balance
*/
export const useCurrenciesBalances = (
- currencies: Currency[]
-): Record => {
+ currencies: Currency[],
+ typedChainId?: number,
+ address?: string
+): UseCurrenciesBalancesReturnType => {
const { activeApi, activeChain, activeAccount } = useWebContext();
// Balances object map currency id and its balance
const [balances, setBalances] = useState>({});
+ const [isLoading, setIsLoading] = useState(true);
+
useEffect(() => {
let isSubscribe = true;
- if (!activeApi || !activeChain) {
+ const typedChainIdToUse =
+ typedChainId ??
+ (activeChain &&
+ calculateTypedChainId(activeChain.chainType, activeChain.id));
+
+ if (!activeApi || typeof typedChainIdToUse !== 'number') {
+ setIsLoading(false);
return;
}
const subscriptions = currencies.map((currency) => {
return activeApi.methods.chainQuery
- .tokenBalanceByCurrencyId(
- calculateTypedChainId(activeChain.chainType, activeChain.id),
- currency.id
- )
+ .tokenBalanceByCurrencyId(typedChainIdToUse, currency.id, address)
.subscribe((currencyBalance) => {
if (isSubscribe) {
setBalances((prev) => {
@@ -49,7 +63,20 @@ export const useCurrenciesBalances = (
isSubscribe = false;
subscriptions.forEach((subscription) => subscription.unsubscribe());
};
- }, [activeApi, activeChain, activeAccount, currencies]);
+ }, [activeApi, activeChain, activeAccount, currencies, typedChainId, address]); // prettier-ignore
+
+ const isAllBalancesLoaded = useMemo(
+ () =>
+ currencies.every((currency) => typeof balances[currency.id] === 'number'),
+ [balances, currencies]
+ );
+
+ useEffect(() => {
+ setIsLoading(!isAllBalancesLoaded);
+ }, [isAllBalancesLoaded]);
- return balances;
+ return {
+ balances,
+ isLoading,
+ };
};
diff --git a/libs/react-hooks/src/currency/useCurrencyBalance.tsx b/libs/react-hooks/src/currency/useCurrencyBalance.tsx
index aaf8ee2ed9..af46a58d47 100644
--- a/libs/react-hooks/src/currency/useCurrencyBalance.tsx
+++ b/libs/react-hooks/src/currency/useCurrencyBalance.tsx
@@ -4,28 +4,30 @@ import { calculateTypedChainId } from '@webb-tools/sdk-core';
import { useEffect, useState } from 'react';
export const useCurrencyBalance = (
- currency: Currency | null | undefined,
- address?: string
+ currencyId: Currency['id'] | null | undefined,
+ address?: string,
+ typedChainId?: number
): number | null => {
const { activeAccount, activeApi, activeChain, loading } = useWebContext();
+
const [balance, setBalance] = useState(null);
useEffect(() => {
- if (!activeApi || !activeAccount || !activeChain || !currency || loading) {
+ if (!activeApi || !activeAccount || !activeChain || !currencyId || loading) {
return;
}
+ const typedChainIdToUse =
+ typedChainId ??
+ calculateTypedChainId(activeChain.chainType, activeChain.id);
+
const subscription = activeApi.methods.chainQuery
- .tokenBalanceByCurrencyId(
- calculateTypedChainId(activeChain.chainType, activeChain.id),
- currency.id,
- address
- )
+ .tokenBalanceByCurrencyId(typedChainIdToUse, currencyId, address)
.subscribe((currencyBalance) => {
setBalance(Number(currencyBalance));
});
return () => subscription.unsubscribe();
- }, [activeAccount, activeApi, activeChain, address, currency, loading]);
+ }, [activeAccount, activeApi, activeChain, address, currencyId, loading, typedChainId]); // prettier-ignore
return balance;
};
diff --git a/libs/react-hooks/src/relayer/useRelayers.ts b/libs/react-hooks/src/relayer/useRelayers.ts
index e98226e68e..e0cea37e60 100644
--- a/libs/react-hooks/src/relayer/useRelayers.ts
+++ b/libs/react-hooks/src/relayer/useRelayers.ts
@@ -1,19 +1,12 @@
-import {
- OptionalActiveRelayer,
- RelayersState,
- WebbRelayer,
-} from '@webb-tools/abstract-api-provider';
+import { RelayersState, WebbRelayer } from '@webb-tools/abstract-api-provider';
import { useWebContext } from '@webb-tools/api-provider-environment';
import { useCallback, useEffect, useState } from 'react';
-import { Subscription } from 'rxjs';
type UseRelayersProps = {
typedChainId: number | undefined;
target: string | number | undefined;
};
-type SubscribeReturnType = Omit;
-
export const useRelayers = (props: UseRelayersProps) => {
const { typedChainId, target } = props;
const { activeApi } = useWebContext();
@@ -34,50 +27,44 @@ export const useRelayers = (props: UseRelayersProps) => {
);
useEffect(() => {
- let availableRelayersSubscription: SubscribeReturnType | null = null;
- let activeRelayerSubscription: SubscribeReturnType | null = null;
+ if (!activeApi) {
+ return;
+ }
- // Populate the relayersState
- if (activeApi && typedChainId) {
- activeApi.relayerManager
- .getRelayersByChainAndAddress(typedChainId, String(target))
- .then((r: WebbRelayer[]) => {
- setRelayersState((p) => ({
- ...p,
- loading: false,
- relayers: r,
- }));
- });
+ const relayersSub = activeApi.relayerManager.listUpdated.subscribe(
+ async () => {
+ const typedChainIdToUse =
+ typedChainId ?? activeApi.typedChainidSubject.getValue();
- // Subscription used for listening to changes of the available relayers
- availableRelayersSubscription =
- activeApi?.relayerManager.listUpdated.subscribe(() => {
- activeApi?.relayerManager
- .getRelayersByChainAndAddress(typedChainId, String(target))
- .then((r: WebbRelayer[]) => {
- setRelayersState((p) => ({
- ...p,
- loading: false,
- relayers: r,
- }));
- });
- });
+ const relayers =
+ await activeApi.relayerManager.getRelayersByChainAndAddress(
+ typedChainIdToUse,
+ `${target ?? ''}`
+ );
- // Subscription used for listening to changes of the activeRelayer
- activeRelayerSubscription =
- activeApi?.relayerManager.activeRelayerWatcher.subscribe(
- (next: OptionalActiveRelayer) => {
- setRelayersState((p) => ({
- ...p,
- activeRelayer: next,
- }));
- }
- );
- }
+ setRelayersState((prev) => ({
+ ...prev,
+ loading: false,
+ relayers,
+ }));
+ }
+ );
+
+ const activeSub = activeApi.relayerManager.activeRelayerWatcher.subscribe(
+ (next) => {
+ setRelayersState((prev) => ({
+ ...prev,
+ activeRelayer: next,
+ }));
+ }
+ );
+
+ // trigger the relayer list update on mount
+ activeApi.relayerManager.listUpdated$.next();
return () => {
- availableRelayersSubscription?.unsubscribe();
- activeRelayerSubscription?.unsubscribe();
+ relayersSub.unsubscribe();
+ activeSub.unsubscribe();
};
}, [activeApi, target, typedChainId]);
diff --git a/libs/react-hooks/src/useNoteAccount.tsx b/libs/react-hooks/src/useNoteAccount.tsx
index b6605d1c18..81dab1d0d6 100644
--- a/libs/react-hooks/src/useNoteAccount.tsx
+++ b/libs/react-hooks/src/useNoteAccount.tsx
@@ -21,10 +21,14 @@ type OnTryAgainCB = (
export type UseNoteAccountReturnType = {
/**
* The notes map Map
- *
*/
allNotes: Map;
+ /**
+ * The flag to indicate if all notes are initialized
+ */
+ allNotesInitialized: boolean;
+
/**
* The flag to indicate if the user has a note account
*/
@@ -85,6 +89,7 @@ export const useNoteAccount = (): UseNoteAccountReturnType => {
const [isSyncingNote, setIsSyncingNote] = useState(false);
const [allNotes, setAllNotes] = useState