Deploy Universal Profiles, LSP7 tokens, and LSP8 NFTs on LUKSO and other EVM chains — all in a single function call.
Instead of manually deploying and wiring up multiple contracts, lsp-factory.js handles everything atomically:
- Universal Profiles — smart accounts with built-in access control (LSP6 KeyManager) and notification hooks (LSP1 Universal Receiver)
- LSP7 Digital Assets — fungible tokens (think ERC-20 but richer)
- LSP8 Identifiable Digital Assets — NFTs (think ERC-721 with better metadata)
Deployments use viem and LSP23LinkedContractsFactory — so linked contracts (e.g., a Universal Profile + its Key Manager) are always deployed together in a single transaction.
Requirements: Node.js >= 22 · TypeScript >= 5.9
| Network | Chain ID |
|---|---|
| LUKSO Mainnet | 42 |
| LUKSO Testnet | 4201 |
| Ethereum Mainnet | 1 |
| BASE | 8453 |
All factory contracts are deployed at the same deterministic address on every supported chain (0x2300000A84D25dF63081feAa37ba6b62C4c89a30).
npm install @lukso/lsp-factory.jsimport { createPublicClient, createWalletClient, http } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { luksoTestnet } from 'viem/chains'; // swap for any supported chain
import { LSPFactory } from '@lukso/lsp-factory.js';
const account = privateKeyToAccount('0x...');
const factory = new LSPFactory(
createPublicClient({ chain: luksoTestnet, transport: http() }),
createWalletClient({ account, chain: luksoTestnet, transport: http() }),
);Deploys a Universal Profile + Key Manager atomically, sets up controller permissions and a Universal Receiver Delegate.
const { LSP0ERC725Account, LSP6KeyManager } = await factory.UniversalProfile.deploy({
controllerAddresses: ['0x...'], // wallet(s) that will control this profile
});
console.log('Profile:', LSP0ERC725Account.address);
console.log('Key Manager:', LSP6KeyManager.address);With profile metadata (name, avatar, description via LSP3):
import { ERC725 } from '@erc725/erc725.js';
import LSP3ProfileSchema from '@erc725/erc725.js/schemas/LSP3ProfileMetadata.json';
const { values } = new ERC725(LSP3ProfileSchema).encodeData([
{ keyName: 'LSP3Profile', value: { json: metadata, url: 'ipfs://...' } },
]);
await factory.UniversalProfile.deploy(
{ controllerAddresses: ['0x...'], lsp3DataValue: values[0] },
{ salt: '0x...' }, // optional: makes the address deterministic
);With custom controller permissions:
import { ERC725 } from '@erc725/erc725.js';
await factory.UniversalProfile.deploy({
controllerAddresses: [
'0xAdmin...', // gets ALL_PERMISSIONS by default
{
address: '0xAgent...',
permissions: ERC725.encodePermissions({ SUPER_SETDATA: true }),
},
],
});Pre-compute addresses before deploying:
const { upAddress, keyManagerAddress } = await factory.UniversalProfile.computeAddress(
{ controllerAddresses: ['0x...'] },
{ salt: '0x...' },
);const { LSP7DigitalAsset } = await factory.LSP7DigitalAsset.deploy({
name: 'My Token',
symbol: 'MTK',
controllerAddress: '0x...', // token owner
tokenType: 0, // 0 = Token · 1 = NFT · 2 = Collection
isNFT: false, // true = non-divisible (0 decimals)
});
console.log('Token:', LSP7DigitalAsset.address);With on-chain metadata:
await factory.LSP7DigitalAsset.deploy({
name: 'My Token',
symbol: 'MTK',
controllerAddress: '0x...',
tokenType: 0,
isNFT: false,
digitalAssetMetadata: {
verification: { method: 'keccak256(bytes)', data: '0x...' },
url: 'ipfs://Qm...',
},
});const { LSP8IdentifiableDigitalAsset } = await factory.LSP8IdentifiableDigitalAsset.deploy({
name: 'My Collection',
symbol: 'MNFT',
controllerAddress: '0x...',
tokenType: 1, // 0 = Token · 1 = NFT · 2 = Collection
tokenIdFormat: 1, // 0 = bytes32 · 1 = number · 2 = string · 3 = address · 4 = hash
});
console.log('NFT:', LSP8IdentifiableDigitalAsset.address);All deploy methods accept an optional onDeployEvents callback:
await factory.UniversalProfile.deploy(
{ controllerAddresses: ['0x...'] },
{
onDeployEvents: {
next: (event) => console.log(event.status, event.contractName),
error: (err) => console.error(err),
complete: (contracts) => console.log('Done!', contracts),
},
},
);npm install # install dependencies
npm run lint # check code style
npm run build # compile TypeScript
npm test # run testsSee CONTRIBUTING.md.