Flutter (Dart)

Working with Particle Wallet within Unity applications

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.

  1. Sign up/log in to the Particle dashboard.

  1. Create a new project or enter an existing one.

  1. Create a new application, or skip this step if you already have one.

  1. Retrieve the project ID (projectId), the client key (clientKey), and the application ID (appId).

‎‎

‎‎

‎‎

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.

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.

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.
// 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"] = "EXAMPLE"
  manifestPlaceholders["PN_PROJECT_CLIENT_KEY"] = "EXAMPLE"
  manifestPlaceholders["PN_APP_ID"] = "EXAMPLE"
}

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

// Example
compileOptions {
  sourceCompatibility JavaVersion.VERSION_11
  targetCompatibility JavaVersion.VERSION_11
}

kotlinOptions {
  jvmTarget = JavaVersion.VERSION_11 
}

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:

<?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).

import ParticleConnect

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.

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:

<key>LSApplicationQueriesSchemes</key>
<array>
  <string>imtokenv2</string>
  <string>metamask</string>
  <string>phantom</string>
  <string>bitkeep</string>
  <string>trust</string>
  <string>rainbow</string>
  <string>zerion</string>
  <string>mathwallet</string>
  <string>1inch</string>
  <string>awallet</string>
  <string>okex</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>

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 both ParticleWallet.setWalletConnectV2ProjectId and ParticleWallet.init. setWalletConnectV2ProjectId takes one parameter, a string representing your WalletConnect project ID retrieved from the WalletConnect dashboard.

With setWalletConnectV2ProjectId set, you can also call ParticleWallet.init, passing in a WalletMetaData object (included within the package:particle_wallet/particle_wallet.dart import) containing:

  • name, your project's name.
  • icon, a link to an icon/logo representing your project - ideally 512x512.
  • url, the URL for your project's website.
  • description, a short description of your project.

E.g.:

ParticleWallet.setWalletConnectV2ProjectId(
  "WalletConnect project ID")

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. 0 sets this to tokens, and 1 to NFTs. E.g.:

ParticleWallet.navigatorWallet(0);

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:

  • tokenAddress, the address of a token to be auto-filled within the send menu. This can be native for a default/native token.
  • toAddress, the recipient's address.
  • amount, 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:

  • mintAddress (contractAddress) of a given NFT.
  • tokenId, the token ID of an NFT (within the collection defined by mintAddress). This can be left as null for Solana.
  • receiveAddress, the recipient address, a blank string by default.

E.g.:

ParticleWallet.navigatorNFTSend(mintAddress, tokenId, 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.:

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:

NameDescriptionTypeRequired
network[Solana, Ethereum, Binance Smart Chain, Polygon, Tron, Optimism, etc.]stringFalse (True if Particle is not connected)
fiatCoinFiat currency denomination.stringFalse
cryptoCoinCryptocurrency denomination.stringFalse
fiatAmtThe amount of fiat to be automatically filled in as the purchase volume.numberFalse
boolLock selection of fiat currency in the buy menu.boolFalse
fixCryptoCoinLock selection of cryptocurrency in the buy menu.boolFalse
fixFiatAmtLock selection of fiat amount in the buy menu.boolFalse
walletAddressThe wallet address to receive the cryptocurrency.stringFalse (True if Particle is not connected)
final config = BuyCryptoConfig(walletAddress:"Wallet Address", cryptoCoin:"USDT", fiatCoin:"USD", fiatAmt:1000, network:OpenBuyNetwork.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:

  • fromTokenAddress, the token to swap from.
  • toTokenAddress, the token to swap to.
  • fromTokenAmount, the amount of fromTokenAddress to be automatically reflected within the UI.

E.g.:

ParticleWallet.navigatorSwap();

ParticleWallet.navigatorSwap(fromTokenAddress, toTokenAddress, fromTokenAmount);

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:

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

E.g.:

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

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:

  • 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.

  • showAppearanceSetting, 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.

  • supportWalletConnect, 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);
}

Master reference

For a direct, raw view into every method provided through ParticleWallet, below is a table containing every relevant one alongside specific parameters and a short description. For methods listed that weren't covered in the above examples, live implementation often mimics the common structure covered throughout this document.

ClassMethodsParameters (* indicates optional)
ParticleWalletinitmetaData
ParticleWalletnavigatorWalletwalletDisplay*
ParticleWalletnavigatorTokenReceivetokenAddress*
ParticleWalletnavigatorTokenSendtokenAddress*, toAddress_* amount*
ParticleWalletnavigatorTokenTransactionRecordstokenAddress*
ParticleWalletnavigatorNFTSendmint, tokenId, amount, receiveAddress
ParticleWalletnavigatorNFTDetailsmint, tokenId
ParticleWalletsetPayDisableddisable
ParticleWalletgetPayDisabled
ParticleWalletsetSwapDisableddisable
ParticleWalletgetSwapDisabled
ParticleWalletnavigatorBuyCryptoconfig*
ParticleWalletnavigatorSwapfromTokenAddress*, toTokenAddress*, amount*
ParticleWalletnavigatorDappBrowserurl*
ParticleWalletnavigatorLoginList
ParticleWalletsetShowTestNetworkenable*
ParticleWalletsetShowSmartAccountSettingenable*
ParticleWalletsetShowManageWalletenable*
ParticleWalletsetSupportChainchainInfos
ParticleWalletswitchWalletwalletType, publicAddress
ParticleWalletsetWalletwalletType, publicAddress, pnWalletName*
ParticleWalletsetSupportDappBrowserenable*
ParticleWalletsetShowLanguageSettingisShow*
ParticleWalletsetShowAppearanceSettingisShow*
ParticleWalletsetSupportAddTokenisShow*
ParticleWalletsetDisplayTokenAddressestokenAddresses
ParticleWalletsetDisplayNFTContractAddressesnftContractAddresses
ParticleWalletsetPriorityTokenAddressestokenAddresses
ParticleWalletsetPriorityNFTContractAddressesnftContractAddresses
ParticleWalletloadCustomUIJsonStringjson
ParticleWalletsetSupportWalletConnectenable*
ParticleWalletsetWalletConnectV2ProjectIdwalletConnectV2ProjectId
ParticleWalletsetCustomWalletNamename*, icon*
ParticleWalletsetCustomLocalizablelocalizables