Skip to main content

Getting Started

The @lukso/lsp-factory.js package allows simple deployments of ERC725-UniversalProfiles, LSP7-DigitalAssets, and LSP8-IdentifiableDigitalAssets.

Installation

npm install @lukso/lsp-factory.js

Instantiation

import { LSPFactory } from '@lukso/lsp-factory.js';

const provider = 'https://rpc.l14.lukso.network'; // RPC provider url

const lspFactory = new LSPFactory(provider, {
deployKey: '0x...', // Private key of the account which will deploy any smart contract,
chainId: 22, // Chain Id of the network you want to deploy to
});

Using LSPFactory in a dApp

If used in the browser on a dApp's page, pass the ethereum object as the provider parameter to connect to a browser extension like the UniversalProfile browser extension or MetaMask. The browser extension will prompt users to sign the transactions as the LSPFactory deploys the smart contracts.

await ethereum.request({ method: 'eth_requestAccounts', params: [] });

const lspFactory = new LSPFactory(ethereum);

Usage

Deploying a Universal Profile is as simple as running:

const myContracts = await lspFactory.UniversalProfile.deploy({
controllingAccounts: ['0x...'], // Account addresses which will control the UP
lsp3Profile: myLSP3MetaData
});
};

The key lsp3Profile contains the LSP3 Metadata of your Universal Profile. This is the "face" of your Universal Profile and contains all the public information people will see when they view your UP like your name, description and profile image.

const myLSP3MetaData = {
name: 'My Universal Profile',
description: 'My cool Universal Profile',
profileImage: [
{
width: 500,
height: 500,
hashFunction: 'keccak256(bytes)',
// bytes32 hex string of the image hash
hash: '0xfdafad027ecfe57eb4ad047b938805d1dec209d6e9f960fc320d7b9b11cbed14',
url: 'ipfs://QmPLqMFHxiUgYAom3Zg4SiwoxDaFcZpHXpCmiDzxrtjSGp',
},
],
backgroundImage: [
{
width: 500,
height: 500,
hashFunction: 'keccak256(bytes)',
// bytes32 hex string of the image hash
hash: '0xfdafad027ecfe57eb4ad047b938805d1dec209d6e9f960fc320d7b9b11cbed14',
url: 'ipfs://QmPLqMFHxiUgYAom3Zg4SiwoxDaFcZpHXpCmiDzxrtjSGp',
},
],
tags: ['public profile', 'creator'],
links: [
{
title: 'My Website',
url: 'www.my-website.com',
},
],
...
};

When deploying your Universal Profile, your LSP3 data will be automatically uploaded to IPFS.

note

If you already have LSP3 data uploaded, then you can pass an IPFS URL:

const myLSP3MetaData = 'ipfs://QmPzUfdKhY6vfcTNDnitwKnnpm5GqjYSmw9todNVmi4bqy';

To create a anonymous Universal Profile, omit the lsp3Profile value.

info

Anonymous profiles can also be useful if you wish to create the LSP3 metadata later.

You can now continue using your UP address within the dApp:

const myUPAddress = myContracts.ERC725Account.address;

Options

When instantiating LSPFactory options can be passed to specify parameters such as chainId and ipfsGateway.

Instantiating LSPFactory with custom options set
const lspFactory = new LSPFactory(provider, {
deployKey: '0x...',
chainId: 22,
ipfsGateway: 'https://ipfs.infura.io:5001',
});

Deploy Key

deployKey is the private key which should sign the transactions sent by LSPFactory. This account must have enough gas to carry out the transactions.

If no value is set here, LSPFactory will attempt to sign transactions via a browser extension.

Chain Id

chainId is used to specify the network that LSPFactory is interacting with. This is used in the versions file to reference base contracts deployed on the network used for proxy deployment. Defaults to 22.

IPFS Gateway

ipfsGateway is used to specify the IPFS node which should be interacted with for uploading and retrieving metadata. ipfsGateway can be either a URL string or an object as defined by the IPFS-HTTP Client library which is used internally to interact with the IPFS node.

Instantiating LSPFactory with custom ipfsGateway options set
const lspFactory = new LSPFactory(provider, {
deployKey: '0x...',
chainId: 22,
ipfsGateway: {
host: 'ipfs.infura.io',
port: 5001,
protocol: 'https',
},
});

Proxy Deployment

LSPFactory uses proxy deployment of smart contracts to maximise gas efficiency. This can be configured inside the options object when deploying Universal Profiles or Digital Assets.

When using proxy deployment contracts will be deployed as a minimal proxy contract based on EIP1167. This is a lightweight contract that inherits its logic by referencing the address of a contract already deployed on the blockchain. Inheriting allows cheaper deployment of Universal Profiles and Digital Assets because only the proxy contract needs to be deployed.

Base contract addresses for different networks are stored internally in the version file to allow a specific version of an LSP smart contract to be used. If no version is specified, the most recent base contract version will be referenced by the proxy contract.

info

A specific contract version can be used by passing the version parameter in the options object when deploying. If no version is specified the latest base contract address will be used.

LSPFactory will check that there is some bytecode deployed at the base contract address before deploying. If none is found, a new base contract will be deployed and referenced in the proxy contract. This process is helpful when using LSPFactory on a local development network like Hardhat where there will be no pre-deployed base contracts.

When using proxy deployment you can specify the base contract address by passing the version parameter inside the options object. This allows you to deploy a specific contract implementation by using a custom base contract you have deployed.

Reactive deployment

The LSPFactory uses RxJS library to deploy contracts. This can be leveraged for certain front-end behaviors to give better feedback to users when they trigger a deployment from a user interface. For example, you may want to implement a loading bar to tell users how deployment is progressing or display details and addresses of the contracts as they are deployed.

When deploying, pass the deployReactive flag inside the options object when deploying an LSP smart contract to receive an RxJS Observable, which will emit events as your contract is deployed.

info

When deployment is completed, an event containing the final contract addresses will be emitted.

Reactive deployment of a Universal Profile
const observable = await lspFactory.UniversalProfile.deploy({...}, {
deployReactive: true
});

observable.subscribe({
next: (deploymentEvent) => {
console.log(deploymentEvent);
},
error: (error) => {
console.error(error);
},
complete: () => {
console.log('Universal Profile deployment completed');
},
});
Reactive deployment of an LSP7 Digital Asset
const observable = await lspFactory.LSP7DigitalAsset.deploy({...}, {
deployReactive: true
});

observable.subscribe({
next: (deploymentEvent) => {
console.log(deploymentEvent);
},
error: (error) => {
console.error(error);
},
complete: () => {
console.log('Digital Asset deployment completed');
},
});
note

The function defined in next will be called whenever a new deployment event is created. The function defined in complete will be called once after deployment is finished.

Read further specification on the deployment events emitted when deploying Universal Profiles and Digital Assets.