Web

This documentation for the Particle Network Javascript SDK will get you started in minutes!

Particle Network SDK allows you to easily integrate your app with the EVM and Solana blockchain, whether you already have a dApp integrated with web3 or are starting from scratch. Particle Network provides a smooth and delightful experience for both you and your app's users.

Demo

Live Demo: https://web-demo.particle.network/

Github: https://github.com/Particle-Network/particle-web-demo

Getting Startedโ€‹

Step 1: Include Particle Network SDK Script

Download Particle Network SDK to your project via Yarn

yarn add @particle-network/auth

//if you need support evm-chains
yarn add @particle-network/provider

//if you need support solana chain
yarn add @particle-network/solana-wallet
browser

<script src="https://static.particle.network/sdks/web/auth/1.2.2/auth.min.js"></script>
<!-- Optional: Add EVM Chains suport -->
<script src="https://static.particle.network/sdks/web/provider/1.2.2/provider.min.js"></script>
<!-- Optional: Add Solana Chain suport -->
<script src="https://static.particle.network/sdks/web/solana-wallet/1.2.2/solana-wallet.min.js"></script>

Step 2: Setup Developer API Key

Before you can add Auth Service to your app, you need to create a Particle project to connect to your app. Visit Particle Dashboard to learn more about Particle projects and apps.

๐Ÿ‘‰ Sign up/log in and create your project now

๐Ÿ‘‰ chainId and chainName configs

import { ParticleNetwork, WalletEntryPosition } from "@particle-network/auth";
import { ParticleProvider } from "@particle-network/provider";
import { SolanaWallet } from "@particle-network/solana-wallet";
import { Ethereum } from "@particle-network/chains";
import Web3 from "web3";

const particle = new ParticleNetwork({
  projectId: "xx",
  clientKey: "xx",
  appId: "xx",
  chainName: Ethereum.name, //optional: current chain name, default Ethereum.
  chainId: Ethereum.id, //optional: current chain id, default 1.
  wallet: {   //optional: by default, the wallet entry is displayed in the bottom right corner of the webpage.
    displayWalletEntry: true,  //show wallet entry when connect particle.
    defaultWalletEntryPosition: WalletEntryPosition.BR, //wallet entry position
    uiMode: "dark",  //optional: light or dark, if not set, the default is the same as web auth.
    supportChains: [{ id: 1, name: "Ethereum"}, { id: 5, name: "Ethereum"}], // optional: web wallet support chains.
    customStyle: {}, //optional: custom wallet style
  },
  securityAccount: { //optional: particle security account config
    //prompt set payment password. 0: None, 1: Once(default), 2: Always
    promptSettingWhenSign: 1,
    //prompt set master password. 0: None(default), 1: Once, 2: Always
    promptMasterPasswordSettingWhenLogin: 1
  },
});

const particleProvider = new ParticleProvider(particle.auth);
//if you need support solana chain
const solanaWallet = new SolanaWallet(particle.auth);

//if you use web3.js
window.web3 = new Web3(particleProvider);
window.web3.currentProvider.isParticleNetwork // => true

//if you use ethers.js
import { ethers } from "ethers";
const ethersProvider = new ethers.providers.Web3Provider(particleProvider, "any");
const ethersSigner = ethersProvider.getSigner();

Your first Particle Network dApp! ๐ŸŽ‰ You can implement web3 functionalities just like how you would normally with MetaMask.

Have a problem? you can refer to this FAQ.

Web3 Integration

Connect Wallet

In order for web3 to work and grab the end-users' Ethereum wallet addresses, the users have to login first (similar to unlocking account in MetaMask). You can simply trigger the login for users with the web3 function call below. The Auth SDK will save the login status locally. Before calling the login method, it is necessary to determine whether user has been logged successful.

import Web3 from "web3";

if (!particle.auth.isLogin()) {
    // Request user login if needed, returns current user info
    const userInfo = await particle.auth.login();
}

// optional: custom login params.
// support auth types: email,phone,facebook,google,apple,discord,github,twitch,microsoft,linkedin
const userInfo = particle.auth.login({
    // when set social login auth type, will open thirdparty auth page directly.
    preferredAuthType?: AuthType,
    // when set email/phone account and preferredAuthType is email or phone, 
    // Particle Auth will enter directly input verification code page.
    // when set JWT value and preferredAuthType is jwt, Particle Auth will auto login.
    account?: string,
    supportAuthTypes?: string, //need support social login types, split with ','. default value 'all'.
    hideLoading?: boolean, //hide particle loading when use jwt authorization.
    socialLoginPrompt?: string, //social login prompt.  none | consent | select_account
    authorization: { // optional, login with authorize
        message: '0x...', //hex sign message.
        uniq: false, //optional, default false.
    }
  })

Login with Phone and input verification code directly.

const userInfo = await particle.auth.login({
    preferredAuthType: 'phone',
    account: '+14155552671', //phone number must use E.164
  });

Login with Social Account.

const userInfo = await particle.auth.login({
    preferredAuthType: 'google', //support facebook,google,twitter,apple,discord,github,twitch,microsoft,linkedin etc.
  })

Login with JWT

const userInfo = particle.auth.login({
    preferredAuthType: 'jwt',
    account: 'JWT Value',
    hideLoading: true,   //optional: hide particle loading when login.
  })

User login modal can also be triggered through web3 accounts.

import Web3 from "web3";

// Async functions that triggers login modal, if user not already logged in
web3.eth.getAccounts((error, accounts) => {
  if (error) throw error;
  console.log(accounts); // ['0x...']
});

A modal will open to ask users to sign up for an account or login with their mobile phone number/email or social account.

Get Wallet Address

EVM Chains

import Web3 from 'web3';
import { ParticleProvider } from "@particle-network/provider";

const particleProvider = new ParticleProvider(particle.auth);
//init web3 with paricle provider
const web3 = new Web3(particleProvider);
const accounts = await web3.eth.getAccounts();

Solana Chain

import { SolanaWallet } from "@particle-network/solana-wallet";

//when new ParticleNetwork, chainId and chainName use Solana chain config.
const account = await particle.solana.getAddress()

//or get accounts with solanaWallet
const solanaWallet = new SolanaWallet(pn.auth);
const publicKey = solanaWallet.publicKey;
const account = publicKey?.toBase58();

Send Transaction

If you have replaced your web3 provider with Particle Network provider, nothing needs to be changed for web3 send Ether transactions to continue working.

The Particle Network X modal will pop open and ask users to confirm their transaction once this web3 function is called on the client-side.

const txnParams = {
    from: "0xXX",
    to: toAddress,
    value: sendValue
};

//for evm transaction: use web3
window.web3.eth.sendTransaction(txnParams, (error, txnHash) => {
    if (error) throw error;
    console.log(txnHash);
});

//for evm transaction: use particle
const txnHash = await particle.evm.sendTransaction(txnParams);


//for solana transaction: use particle
const result = await particle.solana.signAndSendTransaction(transaction)

//for solana transaction: use particle SolanaWallet
solanWallet.signAndSendTransaction(transaction)

User Signing

This is a relatively advanced use case. If you use the signed typed data JSON RPC endpoint, Particle Network will support this as well.

EVM Chains

import { ParticleProvider } from "@particle-network/provider";
import Web3 from "web3";

window.web3 = new Web3(new ParticleProvider(particle.auth));

const msg = "Hello Particle Network!";
const accounts = await window.web3.eth.getAccounts();

//use web3
window.web3.eth.personal
  .sign(msg, accounts[0])
  .then((result) => {
    console.log("personal_sign", result);
  })
  .catch((error) => {
    console.error("personal_sign", error);
  });
  
// or use particle
const result = await particle.evm.personalSign(`0x${Buffer.from(msg).toString('hex')}`);

Solana Chain

// sign message
const result = await particle.solana.signMessage('base58 string');

// sign transaction
const result = await particle.solana.signTransaction('base58 transaction string');

// sign all transactions
const results = await particle.solana.signAllTransactions([
    'base58 transaction1 string', 
    'base58 transaction2 string'
]);

EVM Uniq Sign

import { ParticleProvider } from "@particle-network/provider";

const message = '0x.......'
const result = await particle.evm.personalSignUniq(message);

//or use particle provider
const provider = new ParticleProvider(particle.auth);
const address = await particle.evm.getAddress();
const result = await provider.request({method: 'personal_sign_uniq', params: [message, address]});

Tips

If you use window.ethereum to call RPC, The following things need to be noted:

Only use the Particle

Use only the Particle wallet and block other plugin wallets. For example, you can directly replace the global variable window.ethereum injected by the Metamask plugin with particleProvider:

window.ethereum = particleProvider;

Co-exists with other wallets

The Particle wallet co-exists with other plug-in wallets. You can create a new Provider object when switching wallets, avoiding contamination of Particle or Ethereum with assignment operations๏ผš

let provider = Object.create(particleProvider);
const ParticleWallet = document.getElementById("ParticleWallet");
const MetaMaskWallet = document.getElementById("MetaMaskWallet");
ParticleWallet.onclick = async () => {
  provider = Object.create(particleProvider);
  ethersProvider = new ethers.providers.Web3Provider(provider, "any");
};
MetaMaskWallet.onclick = async () => {
  if (window.ethereum) {
    provider = Object.create(window.ethereum);
  }
  ethersProvider = new ethers.providers.Web3Provider(provider, "any");
};
const accounts = await provider.request({
  method: "eth_requestAccounts",
});

Particle Network Native

Login

The Auth SDK will save the login status locally. Before calling the login method, it is necessary to determine whether user has been logged successful.

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});

let userInfo;
if (!particle.auth.isLogin()) {
    userInfo = await particle.auth.login(params);
} else {
    userInfo = particle.auth.getUserInfo();
}

Logout

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});

particle.auth.logout().then(() => {
    console.log("logout");
})

Is User Logged In

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});

//check user logged
const result = particle.auth.isLogin()

//check user logged and whether the token is valid, this interface also refresh user
//security account info.
const userInfo = await particle.auth.isLoginAsync()

Get User Info

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});

//get user info(token/wallet/uuid), return null when user not login.
const info = particle.auth.getUserInfo();

Status Events

User can listen particle connect , disconnect and chainChanged events.

// listen connect event
particle.auth.on('connect', (userInfo) => {
    console.log("particle userInfo", userInfo);
});

// listen disconnect event
particle.auth.on('disconnect', () => {
    console.log("particle disconnect");
});

// listen chainChanged event
particle.auth.on('chainChanged', (chain) => {
    console.log("particle chainChanged", chain);
});

Set Auth Theme

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});
particle.setAuthTheme({
  uiMode: "dark",
  displayCloseButton: true,
  displayWallet: true, // display wallet entrance when send transaction.
  modalBorderRadius: 10, // auth & wallet modal border radius. default 10.
});

Set Language

//support languages: en, zh-CN, zh-TW, zh-HK, ja, ko
particle.setLanguage('en');

Set Fiat Coin

// support fiat coin values: 'USD' | 'CNY' | 'JPY' | 'HKD' | 'INR' | 'KRW'
particle.setFiatCoin('USD');

Set ERC-4337

// enable ERC-4337, openWallet will open Account Abstraction Wallet
particle.setERC4337({
    name: 'BICONOMY',
    version: '1.0.0',
});

The name and version are configured when initializing SmartAccount.

Switch Chain Info

import { ParticleNetwork } from "@particle-network/auth";
import { Polygon } from "@particle-network/chains";

const particle = new ParticleNetwork({...});
// you can set chain info when new ParticleNetwork, or call setChainInfo
particle.switchChain({
    name: Polygon.name,
    id: Polygon.id,
})

Security Account

Open user security account dashboard, user can set Master Password, Payment Password, and Link Other accounts.

import { ParticleNetwork } from "@particle-netwok/auth";

// open security account settings
const particle = new ParticleNetwork({...});
particle.auth.openAccountAndSecurity().catch((error) => {
    if (error.code === 4011) {
        //ignore window close
    } else if (error.code === 10005) {
        //invalid token
    } else if (error.code === 8005) {
        //user not login
    }
});

// get security account
const securityAccount = await particle.auth.getSecurityAccount();

// check user master password
particle.auth.hasMasterPassword();

// check user payment password
particle.auth.hasPaymentPassword();

// check user security account
particle.auth.hasSecurityAccount();

Open Particle Web Wallet

When connect particle auth success, you can open particle wallet by below interface.

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});

// Need check login state when open wallet.
// To set target and features for custom window style, same as window.open().
particle.openWallet(target?: string, features?: string)


//open wallet in iframe.
const url = pn.buildWalletUrl({
    //optional: left top menu style, close or fullscreen
    //"fullscreen": wallet will be fullscreen when user click.
    //"close": developer need handle click event
    topMenuType: "close"   
});

const iframe = document.createElement("iframe");
iframe.src = url;
//if topMenuType is "close"
window.addEventListener("message", (event) => {
    if (event.data === "PARTICLE_WALLET_CLOSE_IFRAME") {
        //close click event
    }
})

Open Crypto Token Buy

When initializing the Particle is complete, you can open the Buy Tokens page.

import { ParticleNetwork } from "@particle-network/auth";

const particle = new ParticleNetwork({...});
// open buy
// To set target and features for custom window style, same as window.open().
particle.openBuy(options?: OpenBuyOptions, target?: string, features?: string)

You can customize the open buy page by setting options parameters.

namedescriptiontyperequired

network

[Solana, Ethereum, Binance Smart Chain, Polygon, Tron, Optimism, Arbitrum One]

string

False

fiatCoin

Fiat currency

string

False

cryptoCoin

crypto currency

string

False

fiatAmt

The amount of fiat currency that the user wants to spend.It's just for Buy Crypto

number

False

fixFiatCoin

Prevent user from changing fiat currency

bool

False

fixCryptoCoin

Prevent user from changing fiat cryptocurrency

bool

False

fixFiatAmt

Prevent user from changing amount of fiat currency

bool

False

walletAddress

Wallet address for the predefined cryptocurrency

string

False

If Particle not connected. network and walletAddress are requried.

Custom Wallet Style

When "displayWalletEntry" true, you can custom wallet style by set "customStyle" config, refer to Custom Wallet Style

import { ParticleNetwork, WalletEntryPosition } from "@particle-network/auth";
import { Ethereum, Polygon } from "@particle-network/chains";

const particle = new ParticleNetwork({
  projectId: "xx",
  clientKey: "xx",
  appId: "xx",
  chainName: Ethereum.name, //optional: current chain name, default Ethereum.
  chainId: Ethereum.id, //optional: current chain id, default 1.
  wallet: {   //optional: by default, the wallet entry is displayed in the bottom right corner of the webpage.
    displayWalletEntry: true,  //show wallet entry when connect particle.
    defaultWalletEntryPosition: WalletEntryPosition.BR, //wallet entry position
    uiMode: "light",
    supportChains: [Ethereum, Polygon], // optional: web wallet support chains.
    customStyle: {}, //optional: custom wallet style
  }
});

EVM Web3Modal Integration

If you use web3modal connect wallet, you can use custom provider to add particle auth.

๐Ÿ‘‰ Sample

๐Ÿ‘‰ Source Code

EVM RainbowKit Integration

If you use RainbowKit connect wallet, you can add particle auth quickly.

//install particle rainbowkit extension.
yarn add @particle-network/rainbowkit-ext

Init Particle.

// replace config 'xxx'
new ParticleNetwork({
    appId: 'xxx',
    clientKey: 'xxx',
    projectId: 'xxx',
});

Add Particle to RainbowKit wallet list.

// add particle in group Popular
const popularWallets = {
  groupName: "Popular",
  wallets: [
    particleWallet({ chains, authType: "google" }),
    particleWallet({ chains, authType: "facebook" }),
    particleWallet({ chains, authType: "apple" }),
    particleWallet({ chains }),
    injectedWallet({ chains }),
    rainbowWallet({ chains, projectId: "walletconnect project id" }),
    coinbaseWallet({ appName: "RainbowKit demo", chains }),
    metaMaskWallet({ chains, projectId: "walletconnect project id" }),
    walletConnectWallet({ chains, projectId: "walletconnect project id" }),
  ],
};

๐Ÿ‘‰ Sample

๐Ÿ‘‰ Source Code

Solana Wallet-Adapter Integration

Particle Auth support Solana official component wallet-adapter, you can quickly add Particle Auth to your DApp.

export const Wallet: FC = () => {
    // The network can be set to 'devnet', 'testnet', or 'mainnet-beta'.
    const network = WalletAdapterNetwork.Devnet;

    // You can also provide a custom RPC endpoint.
    const endpoint = useMemo(() => clusterApiUrl(network), [network]);

    const wallets = useMemo(
        () => [
            /**
             * Select the wallets you wish to support, by instantiating wallet adapters here.
             *
             * Common adapters can be found in the npm package `@solana/wallet-adapter-wallets`.
             * That package supports tree shaking and lazy loading -- only the wallets you import
             * will be compiled into your application, and only the dependencies of wallets that
             * your users connect to will be loaded.
             */
            new ParticleAdapter(), //add particle adapter
        ],
        []
    );

    return (
        <ConnectionProvider endpoint={endpoint}>
            <WalletProvider wallets={wallets} autoConnect>
                <WalletModalProvider>
                    <WalletMultiButton />
                    <WalletDisconnectButton />
                    { /* Your app's components go here, nested within the context providers. */ }
                </WalletModalProvider>
            </WalletProvider>
        </ConnectionProvider>
    );
};

For detailed usage, please refer to the wallet-adapter documentation.

Upgrade Guide

If you use Particle Auth SDK v0.x.x and wish to update to the 1.x.x, the process is straightforward. Below are the updated functions for reference.

// old: get user info
particle.auth.userInfo()
// new: get user info
particle.auth.getUserInfo()

// old: open account and security
particle.auth.accountSecurity()
// new: open account and security
particle.auth.openAccountAndSecurity()

// old: get current chain id
particle.auth.chainId()
// new: get current chain id
particle.auth.getChainId()

// old: get current chain info
particle.auth.chain()
// new: get current chain info
particle.auth.getChain()

// old: get wallet by type
particle.auth.wallet(type)
// new: get wallet by type
particle.auth.getWallet(type)

// old: import chain info
import { Ethereum, BSC, Polygon } from '@particle-network/common';
// new: import chain info
import { Ethereum, BNBChain, Polygon } from '@particle-network/chains';

Last updated