Skip to content

Commit

Permalink
feat(wallet): update balance finder fetch to include all relevant ass…
Browse files Browse the repository at this point in the history
…ets (#4972)

* feat(core): add StardustIndexerClient

* feat(dashboard): add stardust objects from indexer.

* feat: update balance finder fetch to include all relevant assets WIP

* feat(core): enhance StardustIndexerClient with basic output mapping and new types

* feat(dashboard): add NFT resolved outputs retrieval and mapping functions

* refactor(core, dashboard): unify output types and enhance mapping functions

* feat(wallet-dashboard, core): enhance Stardust output handling and add pagination support

* fix(wallet): include stardustIndexerClient to fetch shared objects in balance finder

* fix(core, dashboard): pr fixes

* fix(wallet, core): move stardust indexer provider to core

* fix(wallet): improve balance finder logic

* feat(sdk): add metadata configuration for stardustIndexer in .env.defaults

* refactor(core): rename limit parameter to page_size in StardustIndexerClient

* refactor(core): update PageParams interface and adjust pagination parameters in StardustIndexerClient

* refactor(core): update return_amount

* refactor(core): update StardustIndexerClient methods and rename hook for clarity

* refactor(dashboard): remove unused variables in useGetAllStardustSharedObjects hook

* fix: add missing 0x to stardust package id

* refactor(core, dashboard): update Stardust package ID format, improve metadata handling in hooks, rename variables.

* fix(wallet): flagged as address to import

* fix(wallet): add constant to set a limiit of the objects to fetch in the balance finder

* fix build

* remove debris

* fix(wallet): rename boolean objects

---------

Co-authored-by: Panteleymonchuk <[email protected]>
Co-authored-by: Begoña Alvarez <[email protected]>
Co-authored-by: evavirseda <[email protected]>
  • Loading branch information
4 people authored Jan 30, 2025
1 parent 619919c commit a54fd6b
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 5 deletions.
4 changes: 3 additions & 1 deletion apps/wallet/src/shared/accounts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ import { type CoinBalance } from '@iota/iota-sdk/client';
export interface AddressFromFinder {
publicKey: string;
bipPath: Bip44Path;
// TODO: extend this balance in the future to include eg staking, vesting schedules, assets, ...
hasTimelockedObjects: boolean;
hasStardustObjects: boolean;
hasAssets: boolean;
balance: CoinBalance;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ const findBalanceFactory = (
coinObjectCount: 2,
coinType: '0x2::iota::IOTA',
},
hasAssets: false,
hasStardustObjects: false,
hasTimelockedObjects: false,
});
}

Expand All @@ -33,6 +36,9 @@ const findBalanceFactory = (
coinObjectCount: 0,
coinType: '0x2::iota::IOTA',
},
hasAssets: false,
hasStardustObjects: false,
hasTimelockedObjects: false,
});
};
};
Expand Down
74 changes: 73 additions & 1 deletion apps/wallet/src/ui/app/accounts-finder/accountsFinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ import type { IotaClient } from '@iota/iota-sdk/client';
import { getEmptyBalance } from './helpers';
import type { FindBalance } from './types';
import { Ed25519PublicKey } from '@iota/iota-sdk/keypairs/ed25519';
import {
COIN_TYPE,
STARDUST_BASIC_OUTPUT_TYPE,
STARDUST_NFT_OUTPUT_TYPE,
type StardustIndexerClient,
TIMELOCK_IOTA_TYPE,
TIMELOCK_STAKED_TYPE,
} from '@iota/core';

export enum AllowedAccountSourceTypes {
MnemonicDerived = 'mnemonic-derived',
Expand All @@ -31,6 +39,7 @@ export interface AccountFinderConfigParams {
changeIndex: number;
}) => Promise<string>;
client: IotaClient;
stardustIndexerClient: StardustIndexerClient | null;
bip44CoinType: AllowedBip44CoinTypes;
accountSourceType: AllowedAccountSourceTypes;
algorithm?: SearchAlgorithm;
Expand Down Expand Up @@ -71,6 +80,8 @@ const CHANGE_INDEXES: { [key in AllowedBip44CoinTypes]: number[] } = {
[AllowedBip44CoinTypes.IOTA]: [0, 1],
};

const NUMBER_OF_OBJECTS_TO_FETCH = 1;

export class AccountsFinder {
private accountGapLimit: number = 0;
private addressGapLimit: number = 0;
Expand All @@ -81,11 +92,13 @@ export class AccountsFinder {
private coinType: string;
private getPublicKey;
private client: IotaClient;
private stardustIndexerClient: StardustIndexerClient | null;
private accounts: AccountFromFinder[] = []; // Found accounts with balances.

constructor(config: AccountFinderConfigParams) {
this.getPublicKey = config.getPublicKey;
this.client = config.client;
this.stardustIndexerClient = config.stardustIndexerClient;
this.bip44CoinType = config.bip44CoinType;
this.coinType = config.coinType;
this.changeIndexes = config.changeIndexes || CHANGE_INDEXES[config.bip44CoinType];
Expand Down Expand Up @@ -186,15 +199,74 @@ export class AccountsFinder {

const publicKeyB64 = await this.getPublicKey(params);
const publicKey = new Ed25519PublicKey(publicKeyB64);
const address = publicKey.toIotaAddress();

const foundBalance = await this.client.getBalance({
owner: publicKey.toIotaAddress(),
owner: address,
coinType: this.coinType,
});

const ownedAsset = await this.client.getOwnedObjects({
owner: address,
filter: {
MatchNone: [
{ StructType: COIN_TYPE },
{ StructType: TIMELOCK_IOTA_TYPE },
{ StructType: TIMELOCK_STAKED_TYPE },
{ StructType: STARDUST_BASIC_OUTPUT_TYPE },
{ StructType: STARDUST_NFT_OUTPUT_TYPE },
],
},
limit: NUMBER_OF_OBJECTS_TO_FETCH,
});

const ownedTimelockedObject = await this.client.getOwnedObjects({
owner: address,
filter: {
MatchAny: [
{ StructType: TIMELOCK_IOTA_TYPE },
{ StructType: TIMELOCK_STAKED_TYPE },
],
},
limit: NUMBER_OF_OBJECTS_TO_FETCH,
});

const hasTimelockedObjects = ownedTimelockedObject.data.length > 0;

const ownedStardustObjects = await this.client.getOwnedObjects({
owner: address,
filter: {
MatchAny: [
{ StructType: STARDUST_BASIC_OUTPUT_TYPE },
{ StructType: STARDUST_NFT_OUTPUT_TYPE },
],
},
limit: NUMBER_OF_OBJECTS_TO_FETCH,
});

let hasStardustObjects = ownedStardustObjects.data.length > 0;
if (!hasStardustObjects && this.stardustIndexerClient) {
// Fetch Basic Outputs from Stardust Indexer
let sharedStardustObjects =
(await this.stardustIndexerClient?.getBasicResolvedOutputs(address, {
pageSize: NUMBER_OF_OBJECTS_TO_FETCH,
})) ?? [];
if (sharedStardustObjects.length === 0) {
// Fetch Nft Outputs from Stardust Indexer
sharedStardustObjects =
(await this.stardustIndexerClient?.getNftResolvedOutputs(address, {
pageSize: NUMBER_OF_OBJECTS_TO_FETCH,
})) ?? [];
}
hasStardustObjects = sharedStardustObjects.length > 0;
}

return {
publicKey: publicKeyB64,
balance: foundBalance || emptyBalance,
hasAssets: ownedAsset.data.length > 0,
hasTimelockedObjects,
hasStardustObjects,
};
};
}
3 changes: 3 additions & 0 deletions apps/wallet/src/ui/app/accounts-finder/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,7 @@ export type FindBalance = (params: {
}) => Promise<{
publicKey: string;
balance: CoinBalance;
hasAssets: boolean;
hasTimelockedObjects: boolean;
hasStardustObjects: boolean;
}>;
14 changes: 11 additions & 3 deletions apps/wallet/src/ui/app/accounts-finder/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ async function searchBalances({
accountIndex,
changeIndex,
},
hasTimelockedObjects: foundBalance.hasAssets,
hasStardustObjects: foundBalance.hasTimelockedObjects,
hasAssets: foundBalance.hasStardustObjects,
});
}
return {
Expand Down Expand Up @@ -222,8 +225,8 @@ export function mergeAccounts(accounts1: AccountFromFinder[], accounts2: Account
return transformFromBipMap(bipMap);
}

// Diff the found and persisted accounts so we know
// what addresses have not persisted yet and have balance.
// Diff the found and persisted accounts so we know
// what addresses have not persisted yet and have relevant assets or balance.
export function diffAddressesBipPaths(
foundAccounts: AccountFromFinder[],
persistedAccounts: AccountFromFinder[],
Expand All @@ -234,7 +237,12 @@ export function diffAddressesBipPaths(
const foundBipMapKeys = Object.entries(foundBipMap);
const persistedBipMapKeys = Object.keys(persistedBipMap);
const diffBipPaths = foundBipMapKeys.filter(
([key, address]) => !persistedBipMapKeys.includes(key) && hasBalance(address.balance),
([key, address]) =>
!persistedBipMapKeys.includes(key) &&
(hasBalance(address.balance) ||
address.hasAssets ||
address.hasTimelockedObjects ||
address.hasStardustObjects),
);

return diffBipPaths.map(([_, account]) => account);
Expand Down
3 changes: 3 additions & 0 deletions apps/wallet/src/ui/app/hooks/useAccountsFinder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { makeDerivationPath } from '_src/background/account-sources/bip44Path';
import { Ed25519PublicKey } from '@iota/iota-sdk/keypairs/ed25519';
import { IOTA_BIP44_COIN_TYPE } from '../redux/slices/iota-objects/coin';
import { IOTA_TYPE_ARG } from '@iota/iota-sdk/utils';
import { useStardustIndexerClientContext } from '@iota/core';

export interface UseAccountFinderOptions {
accountSourceType: AllowedAccountSourceTypes;
Expand All @@ -35,10 +36,12 @@ export function useAccountsFinder({
const backgroundClient = useBackgroundClient();
const ledgerIotaClient = useIotaLedgerClient();
const client = useIotaClient();
const { stardustIndexerClient } = useStardustIndexerClientContext();

const accountFinder = useMemo(() => {
return new AccountsFinder({
client,
stardustIndexerClient,
accountSourceType,
bip44CoinType,
coinType,
Expand Down

0 comments on commit a54fd6b

Please sign in to comment.