@manifoldxyz/js-ts-utils
v9.6.2
Published
JS and TS Utils for Manifold Devs
Keywords
Readme
@manifoldxyz/js-ts-utils
A TypeScript utility library providing common helpers and constants for Manifold's frontend applications and services.
What is this library?
This is a shared utility library containing pure JavaScript/TypeScript functions with minimal external dependencies. Use this library when you need common functionality that isn't specific to any single repository.
When to add code here:
- Reusable utility functions needed across multiple Manifold repos
- Common constants (addresses, network configs, app IDs)
- Platform-agnostic helpers (string formatting, URL generation, etc.)
When NOT to add code here:
- Repository-specific logic
- React components or hooks (use
sdk-reactinstead) - Complex business logic with many dependencies
Dependency policy:
- Keep external dependencies minimal
- Avoid heavy frameworks or libraries
- Prefer pure JS/TS implementations when practical
Prerequisites
- Node.js >= 20.0.0
- npm (included with Node.js)
Installation
npm install @manifoldxyz/js-ts-utilsArchitecture
Project Structure
src/
index.ts # Barrel export of all modules as namespaces
lib/
apps/
constants.ts # AppId enum, APP_METADATA, collector/token mint app IDs
index.ts # getInstanceLink, getAppName, isKnownAppId
arweave.ts # Arweave gateway URL utilities
constants.ts # NULL_ADDRESS, NULL_BYTES32
cookies.ts # Browser cookie management (setCookie, getCookie, removeCookie)
countdown.ts # Timer/countdown formatting for UI display
currency.ts # Currency type, ERC20 configs per network, formatCurrency
error.ts # Error coercion utilities (coerceErrorMessageFromUnknown)
media.ts # Content-type detection regexes, SVG encoding
misc.ts # General helpers (sleep, noop, isJSON, poll)
network.ts # NetworkId enum, NETWORK_CONFIGS, chain resolution
platform.ts # NFT marketplace platform definitions with icons/URLs
providerEvents.ts # Web3 wallet provider event debouncing
string.ts # String formatting (abbreviateAddress, classnames/twMerge)
urls.ts # URL generators for marketplaces and block explorers
web3TransactionError.ts # Ethers.js error parsing → TransactionErrors enum
assets/ # SVG logos for marketplace platforms
tests/
*.test.ts # Test files mirror src/lib/ structure
mocks.ts # Shared test mocksBuild System
- Vite builds dual-format output (ESM + CJS) to
dist/ - vite-plugin-dts generates TypeScript declarations
- Each module has its own entry point — individually importable via package.json
exportsmap - Path alias
@→./src(configured in tsconfig.json and vitest.config.ts)
Supported Networks (NetworkId enum)
Mainnet (1), Optimism (10), Base (8453), Sepolia (11155111), Shape (360), ApeChain (33139)
Modules
Apps
Manifold Studio app ID constants and instance link helpers.
import { Apps } from '@manifoldxyz/js-ts-utils';
// or
import { AppId, getInstanceLink, getAppName } from '@manifoldxyz/js-ts-utils/apps';
Apps.AppId.Claim // 2522713783
Apps.getAppName(AppId.Claim) // "Edition Page"
Apps.getInstanceLink({ preview, workspaceSlug }) // "https://manifold.xyz/@workspace/id/123"Constants
Common blockchain constants.
import { Constants } from '@manifoldxyz/js-ts-utils';
// or
import { NULL_ADDRESS, NULL_BYTES32 } from '@manifoldxyz/js-ts-utils/constants';
Constants.NULL_ADDRESS // "0x0000000000000000000000000000000000000000"
Constants.NULL_BYTES32 // "0x0000000000000000000000000000000000000000000000000000000000000000"Cookies
Browser cookie management utilities.
import { Cookies } from '@manifoldxyz/js-ts-utils';
// or
import { setCookie, getCookie, removeCookie } from '@manifoldxyz/js-ts-utils/cookies';
Cookies.setCookie('name', 'value', 7) // expires in 7 days
Cookies.getCookie('name') // "value"
Cookies.removeCookie('name')Countdown
Timer and countdown utilities for UI display.
import { Countdown } from '@manifoldxyz/js-ts-utils';
// or
import { getCountdownFromTimestamp, getCountdownFromDuration } from '@manifoldxyz/js-ts-utils/countdown';
Countdown.getCountdownFromTimestamp(Date.now() + 86400000) // "01D : 00H : 00M : 00S"
Countdown.getCountdownFromDuration(3600000, false) // "01H : 00M : 00S"Currency
Currency definitions, ERC20 addresses, and display formatting.
import { Currency } from '@manifoldxyz/js-ts-utils';
// or
import { CURRENCIES, formatCurrencyDisplay, getERC20Address } from '@manifoldxyz/js-ts-utils/currency';
Currency.CURRENCIES.USDC // { coinGeckoId, symbol, erc20: { [networkId]: { address, decimals } } }
Currency.formatCurrencyDisplay('1000000', 'USDC', 1) // "1.00"Media
Media type detection and SVG encoding utilities.
import { Media } from '@manifoldxyz/js-ts-utils';
// or
import { isVideo, isImage, isAudio, is3DModel, encodeSVGDataString } from '@manifoldxyz/js-ts-utils/media';
Media.isVideo.test('video/mp4') // true
Media.isImage.test('image/png') // true
Media.encodeSVGDataString(svgData) // encoded SVG for img srcMisc
General purpose utilities.
import { Misc } from '@manifoldxyz/js-ts-utils';
// or
import { sleep, noop, isJSON, poll } from '@manifoldxyz/js-ts-utils/misc';
await Misc.sleep(1000) // wait 1 second
Misc.isJSON('{"valid": true}') // true
await Misc.poll({ fetch, validate, interval: 1000, maxAttempts: 10, errorMessage: '...' })Network
Blockchain network configurations, IDs, and utilities.
import { Network } from '@manifoldxyz/js-ts-utils';
// or
import { NetworkId, NETWORK_CONFIGS, isSupportedNetwork, isTestnet } from '@manifoldxyz/js-ts-utils/network';
Network.NetworkId.Mainnet // 1
Network.NetworkId.Base // 8453
Network.NETWORK_CONFIGS[NetworkId.Mainnet] // { chainId, rpcUrls, nativeCurrency, ... }
Network.isSupportedNetwork(1) // true
Network.isTestnet(11155111) // true (Sepolia)
Network.getDisplayNameForNetworkId(1) // "ethereum"
Network.resolveChainIdByName('base') // 8453Platform
NFT marketplace platform definitions with icons and URL generators.
import { Platform } from '@manifoldxyz/js-ts-utils';
// or
import { Platform as PlatformEnum, PLATFORM_MAP } from '@manifoldxyz/js-ts-utils/platform';
Platform.Platform.OpenSea // enum value
Platform.PLATFORM_MAP[Platform.OpenSea] // { iconSrc, name, url: (props) => string }ProviderEvents
Web3 wallet provider event handling.
import { ProviderEvents } from '@manifoldxyz/js-ts-utils';
// or
import setProviderEventsHandler from '@manifoldxyz/js-ts-utils/providerEvents';
ProviderEvents.default(() => {
// Called when wallet address, chain, or provider changes
console.log('Provider changed');
});StringUtils
String manipulation and formatting utilities.
import { StringUtils } from '@manifoldxyz/js-ts-utils';
// or
import { abbreviateAddress, classnames } from '@manifoldxyz/js-ts-utils/stringUtils';
StringUtils.abbreviateAddress('0x1234567890abcdef1234567890abcdef12345678') // "0x1234...5678"
StringUtils.abbreviate('hello world', 3, 3) // "hel...rld"
StringUtils.classnames('btn', isActive && 'btn-active') // Tailwind class mergingURLs
URL generators for NFT marketplaces and block explorers.
import { URLs } from '@manifoldxyz/js-ts-utils';
// or
import { getOpenSeaTokenURL, getEtherscanAddressURL } from '@manifoldxyz/js-ts-utils/urls';
URLs.getOpenSeaTokenURL(1, contractAddress, tokenId)
URLs.getEtherscanAddressURL(1, address)
URLs.getLooksRareTokenURL(1, contractAddress, tokenId)
URLs.getRaribleTokenURL(1, contractAddress, tokenId)Web3TransactionError
Ethers.js error parsing utilities.
import { Web3TransactionError } from '@manifoldxyz/js-ts-utils';
// or
import { parseEthersError, TransactionErrors } from '@manifoldxyz/js-ts-utils/web3TransactionError';
const errorType = Web3TransactionError.parseEthersError(error);
if (errorType === Web3TransactionError.TransactionErrors.REJECTED) {
// User rejected the transaction
}Commands
npm run test # run the test suite in watch mode (vitest)
npm run build # build the library in ./dist (vite)
npm run format # run prettier on the files
npm run coverage # run tests with coverage reporting (v8)
npm run lint # run eslint
npm run lint:fix # run eslint with auto-fixExternal Dependencies
Internal Packages
| Package | Version | Purpose |
|---------|---------|---------|
| @manifoldxyz/frontend-provider-types | ^2.0.0 | Web3 wallet provider type definitions |
| @manifoldxyz/contract-abis | ^1.0.0 | Contract ABI types (dev only) |
| @manifoldxyz/eslint-config | ^1.2.3 | Shared ESLint configuration (dev only) |
| @manifoldxyz/lint-configs | ^1.1.1 | Shared lint configurations (dev only) |
| @manifoldxyz/studio-apps-client | ^2.1.1 | Studio apps client types (dev only, type imports restricted) |
Third-Party Services
| Package | Purpose | Config |
|---------|---------|--------|
| ethers v6 + @ethersproject/* v5 | Ethereum blockchain interaction, BigNumber math, address utils | — |
| clsx + tailwind-merge | CSS class name merging with Tailwind dedup | — |
| decimal.js | Precise decimal arithmetic for currency formatting | — |
| posthog-js | Analytics telemetry (dev only, type imports restricted at runtime) | — |
External APIs (used in utility functions)
| Service | Module | Usage |
|---------|--------|-------|
| Arweave Gateway | arweave.ts | URL generation for Arweave-stored NFT assets |
| OpenSea | urls.ts | Token/collection URL generation |
| LooksRare | urls.ts | Token URL generation |
| Rarible | urls.ts | Token URL generation |
| Magic Eden | urls.ts | Token URL generation |
| Etherscan/Block Explorers | urls.ts | Address/transaction URL generation |
Note: This is a pure utility library — it generates URLs but does not make HTTP requests to these services (except
misc.ts:poll()which is a generic polling helper used by consumers).
Contributing
Please make a Pull Request for all proposed changes. Your pull request should always include unit test additions or modifications. Your pull request must pass all unit tests and linting tests. Once reviewed and passing, you can merge.
An example PR: https://github.com/manifoldxyz/js-ts-utils/pull/1
Adding a New Module
- Create source file:
src/lib/foo.ts - Barrel export in
src/index.ts: addimport * as Foo from './lib/foo'and include inexport {} - Vite build entry in
vite.config.ts: addfoo: resolve(__dirname, 'src/lib/foo.ts') - Package exports in
package.json: add"./foo"entry withimport,require,typesfields - Bump version in
package.json - Create tests:
tests/foo.test.ts
Releasing
- Bump the version in package.json
- Any merge or commit of that change to main will trigger the CI release action
- This will create a new version on npm matching the package.json (will not overwrite) and will create a new GH release for the version (will overwrite)
Coverage
If you run npm run coverage and the file you are modifying now has either less coverage or does not have near 90% coverage, please add the missing coverage.
Migration Guide
7.1.0 -> 7.2.0
- Breaking:
getInstanceLink's first argument is now an object withpreviewandworkspaceSlugproperties - Breaking:
PLATFORM_MAP[Platform.Manifold].urlgenerates new Manifold.xyz links if contract id and workspace identifier are provided
3.0.x -> 4.0.0
- Breaking:
getNetworkNameForNetworkIdis nowgetDisplayNameForNetworkId
2.0.0 -> 2.1.0
- New: Added
Telemetrymodule (since removed) - New: Added
Appsmodule
1.3.2 -> 1.4.0
- Breaking:
getManifoldGalleryBaseURLis nowgetManifoldMarketplaceBaseURL - Breaking:
getManifoldGalleryTokenURLis nowgetManifoldMarketplaceTokenURL - Breaking:
PLATFORM_MAP[Platform.Manifold].urlgenerates new Manifold.gallery links
< 1.0.0 -> 1.0.0
If you are not using "type": "module" in your package.json, you will have to use the CommonJS builds of this library which are only available in version 1.0.0 and greater.
0.2.x -> 0.3.x
This library now uses ESM.
networkmodule:- Breaking: Types are now
PascalCaseand singular instead ofALL_CAPS_SNAKE_CASEand plural - Breaking:
SUPPORTED_NETWORKS_ARRAYis now aconstarray with properly inferred types - Breaking:
NETWORK_IDSandNETWORK_NAMESenums replaced byNetworkIdenum - New: Added
MAIN_NETWORKS,TEST_NETWORKSarrays with corresponding types - New: Added
resolveChainIdByNamefunction
- Breaking: Types are now
