Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
48e42c5
[wallet/common/symbol] feat: add TokenModule
OlegMakarenko Jul 3, 2026
7b408d5
[wallet/symbol/mobile] feat: add CreateMosaic screen
OlegMakarenko Jul 3, 2026
dbc2a64
[wallet/symbol/mobile] feat: add custom input components, add validat…
OlegMakarenko Jul 6, 2026
fc96953
[wallet/symbol/mobile] task: refactor ustils
OlegMakarenko Jul 7, 2026
27fa4a9
[wallet/symbol/mobile] task: refactor MosaicPreviewCard component
OlegMakarenko Jul 7, 2026
174cdca
[wallet/symbol/mobile] task: restructure mosaic utils
OlegMakarenko Jul 7, 2026
85bc3ab
[wallet/symbol/mobile] task: update JS-Doc
OlegMakarenko Jul 7, 2026
fff98d4
[wallet/common/symbol] fix: handle empty mosaic flags
OlegMakarenko Jul 9, 2026
17966f7
[wallet/common/symbol] feat: add mosaic owners fetch method to Mosaic…
OlegMakarenko Jul 14, 2026
92e940c
[wallet/common/symbol] feat: add disabled state to SelectToken component
OlegMakarenko Jul 14, 2026
35386c8
[wallet/common/symbol] feat: add RevokeMosaic screen
OlegMakarenko Jul 14, 2026
e12f329
[wallet/symbol/mobile] feat: add ModifyMosaic screen
OlegMakarenko Jul 23, 2026
315597d
[wallet/symbol/mobile] feat: add SelectTransactionSender isMultisigDi…
OlegMakarenko Jul 23, 2026
88abeed
[wallet/symbol/mobile] task: remove multisig support from the mosaic …
OlegMakarenko Jul 23, 2026
cdd6777
[wallet/symbol/mobile] task: refactor MosaicPreviewCard and SupplyDel…
OlegMakarenko Jul 23, 2026
334b1b6
[wallet/symbol/mobile] task: update TokenDetails to render creator ac…
OlegMakarenko Jul 23, 2026
19d3c77
[wallet/symbol/mobile] task: update layout, fix tests
OlegMakarenko Jul 23, 2026
1112bd0
[wallet/symbol/mobile] task: update mosaic image on Actions screen
OlegMakarenko Jul 23, 2026
c09bf6f
[wallet/symbol/mobile] task: update mosaic default flag values
OlegMakarenko Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 73 additions & 35 deletions wallet/common/symbol/src/api/MosaicService.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
import {
addressFromRaw,
isRestrictableFlag,
isRevokableFlag,
isSupplyMutableFlag,
isTransferableFlag
} from '../utils';
import { addressFromRaw, createSearchUrl, getMosaicAmount, mosaicInfoFromDTO } from '../utils';
import _ from 'lodash';
import { absoluteToRelativeAmount } from 'wallet-common-core';

/** @typedef {import('../types/Mosaic').Mosaic} Mosaic */
/** @typedef {import('../types/Mosaic').MosaicInfo} MosaicInfo */
/** @typedef {import('../types/Mosaic').MosaicOwner} MosaicOwner */
/** @typedef {import('../types/Network').NetworkProperties} NetworkProperties */
/** @typedef {import('../types/SearchCriteria').SearchCriteria} SearchCriteria */

export class MosaicService {
#api;
Expand Down Expand Up @@ -53,34 +50,10 @@ export class MosaicService {
});

// Create map <id, info> from response
const mosaicInfosEntires = data.map(mosaicInfos => {
const duration = parseInt(mosaicInfos.mosaic.duration);
const startHeight = parseInt(mosaicInfos.mosaic.startHeight);
const endHeight = startHeight + duration;
const isUnlimitedDuration = duration === 0;
const creator = addressFromRaw(mosaicInfos.mosaic.ownerAddress);
const supply = absoluteToRelativeAmount(parseInt(mosaicInfos.mosaic.supply), mosaicInfos.mosaic.divisibility);
const { flags } = mosaicInfos.mosaic;

return [
mosaicInfos.mosaic.id,
{
id: mosaicInfos.mosaic.id,
divisibility: mosaicInfos.mosaic.divisibility,
names: [],
duration,
startHeight,
endHeight,
isUnlimitedDuration,
creator,
supply,
isSupplyMutable: isSupplyMutableFlag(flags),
isTransferable: isTransferableFlag(flags),
isRestrictable: isRestrictableFlag(flags),
isRevokable: isRevokableFlag(flags)
}
];
});
const mosaicInfosEntires = data.map(mosaicInfos => [
mosaicInfos.mosaic.id,
mosaicInfoFromDTO(mosaicInfos.mosaic)
]);
const mosaicInfos = Object.fromEntries(mosaicInfosEntires);

// Find namespace ids if there are some in the mosaic list. Mosaic infos are not available for namespace ids
Expand Down Expand Up @@ -114,4 +87,69 @@ export class MosaicService {

return { ...mosaicInfos, ...remainedMosaicInfos };
};

/**
* Fetches the list of mosaics created by a given account from the node.
* @param {NetworkProperties} networkProperties - Network properties.
* @param {string} address - The mosaic creator address.
* @param {SearchCriteria} [searchCriteria] - Search criteria.
* @returns {Promise<MosaicInfo[]>} - The created mosaics.
*/
fetchAccountMosaics = async (networkProperties, address, searchCriteria) => {
const endpoint = createSearchUrl(networkProperties.nodeUrl, '/mosaics', searchCriteria, {
ownerAddress: address
});
const { data } = await this.#makeRequest(endpoint);
const mosaicInfos = data.map(mosaicDTO => mosaicInfoFromDTO(mosaicDTO.mosaic));
const mosaicIds = mosaicInfos.map(mosaicInfo => mosaicInfo.id);
const mosaicNames = await this.#api.namespace.fetchMosaicNames(networkProperties, mosaicIds);

return mosaicInfos.map(mosaicInfo => ({
...mosaicInfo,
names: mosaicNames[mosaicInfo.id] || []
}));
};

/**
* Fetches the list of accounts holding a given mosaic from the node.
* @param {NetworkProperties} networkProperties - Network properties.
* @param {string} mosaicId - The mosaic id to search holders for.
* @param {SearchCriteria} [searchCriteria] - Search criteria.
* @returns {Promise<MosaicOwner[]>} - The mosaic owners with their held amounts in relative units.
*/
fetchMosaicOwners = async (networkProperties, mosaicId, searchCriteria) => {
const endpoint = createSearchUrl(networkProperties.nodeUrl, '/accounts', searchCriteria, {
mosaicId
});
const { data } = await this.#makeRequest(endpoint);

if (!data.length)
return [];

const divisibility = await this.#fetchMosaicDivisibility(networkProperties, mosaicId);

return data.map(accountDTO => ({
address: addressFromRaw(accountDTO.account.address),
amount: absoluteToRelativeAmount(getMosaicAmount(accountDTO.account.mosaics, mosaicId), divisibility)
}));
};

/**
* Fetches the divisibility of a single mosaic directly from the node, skipping name and namespace resolution.
* @param {NetworkProperties} networkProperties - Network properties.
* @param {string} mosaicId - The mosaic id.
* @returns {Promise<number>} - The mosaic divisibility.
*/
#fetchMosaicDivisibility = async (networkProperties, mosaicId) => {
const endpoint = `${networkProperties.nodeUrl}/mosaics`;
const [mosaicInfoDTO] = await this.#makeRequest(endpoint, {
method: 'POST',
body: JSON.stringify({ mosaicIds: [mosaicId] }),
headers: {
'Content-Type': 'application/json'
}
});

return mosaicInfoDTO.mosaic.divisibility;
};
}
13 changes: 11 additions & 2 deletions wallet/common/symbol/src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,22 @@ export const TransactionBundleType = {
MULTISIG_TRANSFER: 'multisig-transfer',
MULTISIG_ACCOUNT_MODIFICATION: 'multisig-account-modification',
DELEGATED_HARVESTING: 'delegated-harvesting',
MULTISIG_DELEGATED_HARVESTING: 'multisig-delegated-harvesting'
MULTISIG_DELEGATED_HARVESTING: 'multisig-delegated-harvesting',
TOKEN_CREATION: 'token-creation',
MULTISIG_TOKEN_CREATION: 'multisig-token-creation',
TOKEN_SUPPLY_CHANGE: 'token-supply-change',
MULTISIG_TOKEN_SUPPLY_CHANGE: 'multisig-token-supply-change',
TOKEN_REVOCATION: 'token-revocation',
MULTISIG_TOKEN_REVOCATION: 'multisig-token-revocation'
};

export const MULTISIG_BUNDLE_TYPES = [
TransactionBundleType.MULTISIG_TRANSFER,
TransactionBundleType.MULTISIG_ACCOUNT_MODIFICATION,
TransactionBundleType.MULTISIG_DELEGATED_HARVESTING
TransactionBundleType.MULTISIG_DELEGATED_HARVESTING,
TransactionBundleType.MULTISIG_TOKEN_CREATION,
TransactionBundleType.MULTISIG_TOKEN_SUPPLY_CHANGE,
TransactionBundleType.MULTISIG_TOKEN_REVOCATION
];

export const HarvestingStatus = {
Expand Down
Loading