Particle Wallet for Flutter

Particle Wallet for Flutter is a standard interface and infrastructure for interacting with both Web2-based and Web3-based wallets, working directly with Particle Connect and Particle Auth. In essence, Particle Wallet provides a UI to send, swap, and purchase cryptocurrency, cross-compatible with multiple different account origins, primarily powered by either Particle Auth (for social logins) or Particle Connect (aggregating both social logins and external Web3 wallets).

A rundown on getting started and utilizing the Particle Wallet Flutter SDK is detailed below.

Repository

All of the Particle Network Flutter SDKs, including Particle Wallet, can be found within the particle-flutter GitHub repository. Before diving in, it may be worth looking through this repository to contextualize usage of the SDK with an understanding of its underlying architecture.


Getting Started

Setting up and getting started with the Particle Wallet Flutter SDK is relatively simple, although it differs depending on whether you use Flutter on Android or iOS. However, for both platforms, the setup should be complete in a few minutes.

To begin, you’ll need to, regardless of platform, head over to the Particle dashboard and retrieve your projectId, clientKey, and appId to connect your Flutter project with the dashboard. This enables configuration, analytics, tracking, etc.

Follow the quickstart tutorial to set up a project and find the required keys: Create a new project.

Adding the Particle Wallet Flutter SDK to your application

Additionally, regardless of platform, you’ll need to begin by adding particle_wallet to your Flutter application. This is a requirement before moving onto platform-specific configuration.

Terminal
flutter pub add particle_wallet

Android configuration

If you’re building an Android application, you must follow the following steps to configure Particle Wallet and prepare for utilization.

Prerequisites

  • minSdkVersion 23 or higher.
  • compileSdkVersion, targetSdkVersion 34 or higher.
  • JavaVersion 17.
  • Jetpack (AndroidX).
  • Android Gradle Plugin Version : 8.5.1 or higher.
  • Gradle Version : 8.9 or higher.

To begin, you’ll need to open your build.gradle file, often found at the following file path: ${project name}/android/app/build.gradle.

Within build.gradle , you’ll need to add four new lines to ensure Particle Wallet runs properly:

  1. minSdkVersion, in most cases, this will simply be set to 23.
  2. manifestPlaceholders["PN_PROJECT_ID"], the projectId previously retrieved from the Particle dashboard.
  3. manifestPlaceholders["PN_PROJECT_CLIENT_KEY"], the clientKey previously retrieved from the Particle dashboard.
  4. manifestPlaceholders["PN_APP_ID"], the appId previously retrieved from the Particle dashboard.
build.gradle
// Example
defaultConfig {
  // Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html)
  applicationId "com.example.particle_auth_test"

  minSdkVersion 23 // Required
  targetSdkVersion flutter.targetSdkVersion
  versionCode flutterVersionCode.toInteger()
  versionName flutterVersionName

  manifestPlaceholders["PN_PROJECT_ID"] = "YOUR PROJECT ID"
  manifestPlaceholders["PN_PROJECT_CLIENT_KEY"] = "YOUR CLIENT KEY"
  manifestPlaceholders["PN_APP_ID"] = "YOUR APP ID"
}

Additionally, staying within your build.gradle file, you’ll need to ensure that you’re using version 17 of Java in both compileOptions and kotlinOptions, alongside enabling dataBinding.

build.gradle
// Example
compileOptions {
  sourceCompatibility JavaVersion.VERSION_17
  targetCompatibility JavaVersion.VERSION_17
}

kotlinOptions {
  jvmTarget = JavaVersion.VERSION_17
}

dataBinding {
  enabled = true
}

iOS configuration

Before beginning to build an iOS application, ensure your project meets the following prerequisites:

  • Xcode 15.0 or later.

  • iOS 14 or later.

With these requirements set, you’ll need to open an exported iOS project and find ios/{project name}.xcworkspace.

At the root of your Xcode project, create a new file, ParticleNetwork-Info.plist. Ensure this is marked under “Target Membership.”

With a fresh ParticleNetwork-Info.plist file, go ahead and fill it in with the following:

ParticleNetwork-Info.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PROJECT_UUID</key>
	<string>YOUR_PROJECT_UUID</string>
	<key>PROJECT_CLIENT_KEY</key>
	<string>YOUR_PROJECT_CLIENT_KEY</string>
	<key>PROJECT_APP_UUID</key>
	<string>YOUR_PROJECT_APP_UUID</string>
</dict>
</plist>

You’ll now need to fill in PROJECT_UUID (projectId), PROJECT_CLIENT_KEY, and PROJECT_APP_UUID (appId) with the corresponding values retrieved from the Particle dashboard.

Next, you’ll need to go to your AppDelegate.swift file to add an import of ParticleConnect (which Particle Wallet is dependent on).

Additionally, within your application’s application method (as shown below), you’ll need to include a handler condition derived from ParticleConnect.handleUrl. This should be as simple as a true return upon a truthy value of ParticleConnect.handleUrl, and a super.application(app, open: url, options: options) return upon a falsy value.

AppDelegate.swift

import ParticleConnect

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
  if ParticleConnect.handleUrl(url) {
      return true
  } else {
      return super.application(app, open: url, options: options)
  }
}

Wrapping up, you’ll need to configure your application’s scheme URL. To configure this, select your application from “TARGETS” under the “Info” section, then click ”+” to add a URL type.

This should be set to “pn” + your projectId (retrieved and configured prior), resulting in a scheme URL that looks like the following:

pn63bfa427-cf5f-4742-9ff1-e8f5a1b9828f

Additionally, head over to your Info.plist file and include the following snippet:

Info.plist
<key>LSApplicationQueriesSchemes</key>
<array>
<string>metamask</string>
<string>phantom</string>
<string>bitkeep</string>
<string>imtokenv2</string>
<string>rainbow</string>
<string>trust</string>
<string>zerion</string>
<string>mathwallet</string>
<string>oneinch</string>
<string>awallet</string>
<string>okex</string>
<string>bnc</string>
</array>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access in order to open photos of barcodes</string>
<key>NSCameraUsageDescription</key>
<string>We use the camera to scan barcodes</string>
<key>NSFaceIDUsageDescription</key>
<string>We use Face ID for secure access to the app.</string>

Finally, you’ll need to edit your Podfile to ensure particle_connect is correctly imported. If you have not already, head over to the linked guide to complete this.


Examples of Utilization

Initialization

Before the SDK is usable, you’ll have to go through initialization. This is required before other methods function. To do this, you’ll need to call ParticleWallet.init.

FieldTypeDescription
nameStringYour project’s name.
iconStringThe link to an icon/logo representing your project - ideally 512x512.
urlStringThe URL for your project’s website.
descriptionStringA short description of your project.

E.g.:

ParticleWallet.init(WalletMetaData(
        "Particle Connect",
        "https://connect.particle.network/icons/512.png",
        "https://connect.particle.network",
        "Particle Connect Flutter Demo"));

Open Wallet

To programmatically force the main wallet page open, you can call ParticleWallet.navigatorWallet. navigatorWallet takes one parameter, a binary selection indicating whether tokens or NFTs are displayed within the main wallet page. WalletDisplay.token sets this to tokens, and WalletDisplay.nft to NFTs. E.g.:

ParticleWallet.navigatorWallet();

Open Receive Token

Similarly, to open a page for receiving a token containing both an address and a corresponding QR code, you can call ParticleWallet.navigatorTokenReceive. This optionally takes a parameter, tokenAddress, representing the specific token you plan to receive, in which the QR code will include its logo at its center. E.g.:

ParticleWallet.navigatorTokenReceive();

ParticleWallet.navigatorTokenReceive(tokenAddress);

Open Send Token

You can also open a send token (token referring to ERC20/SPL/native) page by calling ParticleWallet.navigatorTokenSend. Specifically, navigatorTokenSend optionally takes the following parameters:

FieldTypeDescription
tokenAddressStringThe address of a token to be auto-filled within the send menu. This can be native for a default/native token.
toAddressStringThe recipient’s address.
amountString?(Optional) The volume of tokens (tokenAddress) to be sent.

E.g.:

ParticleWallet.navigatorTokenSend();

ParticleWallet.navigatorTokenSend(tokenAddress: tokenAddress, toAddress: toAddress, amount: amount);

Open Transaction Records

To open the transaction records (history) of a given connected wallet, you can programmatically force this page with ParticleWallet.navigatorTokenTransactionRecords, optionally taking one parameter, tokenAddress. If filled out, this will filter the transaction records to only display entries involving a specified tokenAddress. E.g.:

ParticleWallet.navigatorTokenTransactionRecords();

ParticleWallet.navigatorTokenTransactionRecords(tokenAddress: tokenAddress);

Open NFT Send

Similar to navigatorTokenSend, you can call ParticleWallet.navigatorNFTSend to throw a page explicitly meant for sending a given NFT (one specific token). navigatorNFTSend takes the following parameters:

FieldTypeDescription
mintString(contractAddress) of a given NFT.
tokenIdStringThe token ID of an NFT (within the collection defined by mint). This can be left as null for Solana.
amountString?The volume of NFT (mint) to be sent, ERC172 NFT should set 1
receiveAddressString?The recipient address, a blank string by default.

E.g.:

String mintAddress = "0xD000F000Aa1F8accbd5815056Ea32A54777b2Fc4";
String tokenId = "1412";
ParticleWallet.navigatorNFTSend(mintAddress, tokenId, amount: null, receiveAddress: "");

Open NFT Details

Particle Wallet also natively supports viewing specific NFTs’ traits, description, image, etc. Forcing this menu programmatically can happen through ParticleWallet.navigatorNFTDetails, passing in the contractAddress (mint) of the NFT and the specific tokenId. For Solana, tokenId can be left blank. E.g.:

FieldTypeDescription
mintString(contractAddress) of a given NFT.
tokenIdStringThe token ID of an NFT (within the collection defined by mint). This can be left as null for Solana.
String mint = "0xD000F000Aa1F8accbd5815056Ea32A54777b2Fc4";
String tokenId = "1412";
ParticleWallet.navigatorNFTDetails(mint, tokenId);

Open Buy Crypto

Particle Wallet also has a native onramp aggregator, allowing users to bring fiat on-chain through various onramp providers. Opening this programmatically can happen through ParticleWallet.navigatorBuyCrypto, passing in several optional parameters to customize the values used within the onramp. Upon calling, this will return a popup or total redirect over to a configuration of https://ramp.particle.network.

The specific parameters that can be used within ParticleWallet.navigatorBuyCrypto are listed below:

FieldTypeDescription
walletAddressString?(Optional) The wallet address to receive the cryptocurrency, default is current user address.
cryptoCoinString?(Optional) Cryptocurrency denomination. Default is current chain native token symbol.
fiatCoinString?(Optional) Fiat currency denomination. Default is current fiat coin.
fiatAmtint?(Optional) The amount of fiat to be automatically filled in as the purchase volume.
chainInfoChainInfo?(Optional) The chainInfo, default is current chainInfo.
fixFiatCoinbool(Optional) Lock selection of fiat coin in the buy menu, default is false.
fixFiatAmtbool(Optional) Lock selection of fiat amount in the buy menu, default is false.
fixCryptoCoinbool(Optional) Lock selection of crypto coin in the buy menu, default is false.
themeTheme(Optional) The buy page theme, dark or light, default is curreny appearance.
languageLanguage?(Optional) The buy page lanuage, default is current language.
modalStyleIOSModalPresentStyle?(Optional) Control iOS presentation style, default is pageSheet.
final config = BuyCryptoConfig(walletAddress:"Wallet Address", cryptoCoin:"USDT", fiatCoin:"USD", fiatAmt:1000,  chainInfo: ChainInfo.Ethereum);
ParticleWallet.navigatorBuyCrypto(config: config);

Open Swap

Particle Wallet has a native swap page (retrieves multiple quotes from different providers, routing the swap through the best one) for Mainnets (Solana and EVM). Throwing this menu can be done through ParticleWallet.navigatorSwap, which alone will open the default swap menu without values filled in, although you can pass in several optional parameters, including:

FieldTypeDescription
fromTokenAddressString?(Optional) The swap pair from token address.
toTokenAddressString?(Optional) The swap pair to token address.
amountString?(Optional) The swap from token amount, should pass the minimal unit string, for example 0.01 ETH, it’s decimals is 18, should pass “10000000000000000”.

E.g.:

ParticleWallet.navigatorSwap();

ParticleWallet.navigatorSwap(fromTokenAddress, toTokenAddress, amount);

Open DApp Browser

Particle Wallet also includes a dApp Browser, enabling users to open different dApps (web apps) and automatically connect with the account loaded into the instance of Particle Wallet. This enables account usage across any web-based dApp. This can be programmatically opened through ParticleWallet.navigatorDappBrowser, taking one parameter, url, which will dictate the specific site opened. E.g.:

const url = "https://opensea.io";
ParticleWallet.navigatorDappBrowser(url: url);

Set Supported Chains

To set the specific supported chain(s) available within the chain selection menu on Particle Wallet, you can use ParticleWallet.setSupportChain, which takes an array of ChainInfo objects. Each object (representing different chains) will directly enable an additional chain within the wallet interface.

If you add a Testnet to this list and pass it to setSupportChain, you’ll also need to ensure that ParticleWallet.setShowTestNetwork is set to true (by passing in true). E.g.:

List<ChainInfo> chainInfos = <ChainInfo>[];
chainInfos.add(ChainInfo.Ethereum);
chainInfos.add(ChainInfo.Polygon);
chainInfos.add(ChainInfo.BNBChain);
ParticleWallet.setSupportChain(chainInfos);

Switch Wallets

Additionally, to switch the current wallet type (walletType) active within the Particle Wallet interface, you’ll need to call ParticleWallet.switchWallet by passing in a specified walletType (of type WalletType) and associated publicAddress.

WalletType contains the following:

  • authCore, social logins through Particle Auth.
  • evmPrivateKey, custom EVM wallet imports/exports.
  • solanaPrivateKey, custom Solana wallet imports/exports.
  • metaMask.
  • rainbow.
  • trust.
  • imToken.
  • bitget.
  • walletConnect.
  • zerion.
  • math.
  • zengo.
  • alpha.
  • okx.
  • phantom, intended for Solana.

E.g.:

WalletType walletType = WalletType.authCore;
await ParticleWallet.switchWallet(walletType, publicAddress);

(Optional) Custom WalletConnect Projcet ID

//call before ParticleConnect.init
ParticleWallet.setWalletConnectProjectId("Your WalletConnect Project ID, from https://cloud.walletconnect.com")

Custom UI

Additional interface customizations can be manually set through a variety of methods on ParticleWallet. Each of these will change a specific configuration or UI element present within the Particle Wallet interface. These methods include:

  • setSwapDisabled, whether or not the “Swap” functionality is displayed within the interface. This takes one parameter, either true or false, with the default being false.

  • setPayDisabled, whether or not the “Buy” functionality is displayed within the interface. This takes one parameter, either true or false, with the default being false.

  • setBridgeDisabled, whether or not the “Bridge” functionality is displayed within the interface. This takes one parameter, either true or false, with the default being false.

  • setShowTestNetwork, configures the visibility of the Testnets within the interface. It accepts a boolean value, true or false.

  • setShowManageWallet, toggles the display of the wallet management page. It takes a boolean parameter, either true or false.

  • setShowLanguageSetting, controls the visibility of the language setting option in the settings page. It accepts a boolean value, true or false.

  • setShowAppearanceSetting, determines whether the appearance setting is shown in the settings page. It takes a boolean value, true or false.

  • setSupportDappBrowser, configures the availability of the dApp browser feature. It accepts a boolean parameter, true or false.

  • setSupportWalletConnect, sets whether WalletConnect is supported on the wallet page. It takes a boolean value, true or false.

  • setSupportAddToken, toggles the option to add tokens, indicated by the variable isShow.

  • setDisplayTokenAddresses, specifies token addresses to be displayed. It accepts a list of token addresses.

  • setPriorityTokenAddresses, sets specific tokens as a priority, making them appear at the top of the list. It requires a list of token addresses.

  • setDisplayNFTContractAddresses, configures the wallet to display NFTs from specified contract addresses. It accepts a list of NFT contract addresses.

  • setPriorityNFTContractAddresses, prioritizes specific NFT contract addresses to be shown at the top of the list. It takes a list of NFT contract addresses.

  • loadCustomUIJsonString, allows setting a custom UI theme by passing a JSON string. This string can be customized according to the user’s preference.

E.g.:

ParticleWallet.setShowTestNetwork(true);

ParticleWallet.setShowManageWallet(true);

ParticleWallet.setShowLanguageSetting(true);

ParticleWallet.showAppearanceSetting(true);

ParticleWallet.setSupportDappBrowser(false);

ParticleWallet.setSupportWalletConnect(true);

ParticleWallet.setSupportAddToken(isShow);

ParticleWallet.setShowSmartAccountSetting(false);

List<String> tokenAddresses = <String>[
  "0x303b35f48684bea50D0e7D1AcDdeaf78A7188798"
];


List<String> tokenAddresses = <String>[
  "0x303b35f48684bea50D0e7D1AcDdeaf78A7188798"
];

ParticleWallet.setDisplayTokenAddresses(tokenAddresses);

ParticleWallet.setPriorityTokenAddresses(tokenAddresses);

List<String> nftContractAddresses = <String>[
  "0xD18e451c11A6852Fb92291Dc59bE35a59d143836"
];

ParticleWallet.setDisplayNFTContractAddresses(nftContractAddresses);

ParticleWallet.setPriorityNFTContractAddresses(nftContractAddresses);


// Example https://github.com/Particle-Network/particle-ios/blob/main/Demo/Demo/customUIConfig.json
const json = "";
ParticleWallet.loadCustomUIJsonString(json);

ParticleWallet.setCustomWalletName("Your Wallet Name", "your wallet icon url");

// in Android platform, call setWallet and set your wallet name.
ParticleWallet.setWallet(walletType, pubAddress!, "Your wallet name");

// you can replace localizable strings that appeared in
// yourIOSBuild/Pods/ParticleWalletGUI/XCFrameworks/ParticleWalletGUI/ParticleWalletGUI.bundle/en.lproj/Locallizable.strings.
if (Platform.isIOS) {
  Map<String, String> enLocalizables = <String, String>{
    "network fee": "Service Fee",
    "particle auth wallet": "Your wallet name"
  };

  Map<Language, Map<String, String>> localizables = <Language, Map<String, String>> {
    Language.en:  enLocalizables
  };

  ParticleWallet.setCustomLocalizable(localizables);
}