Working with Particle Wallet within Flutter 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.
- Sign up/log in to the Particle dashboard.
- Create a new project or enter an existing one.
- Create a new application, or skip this step if you already have one.
- 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:
minSdkVersion
, in most cases, this will simply be set to23
.manifestPlaceholders["PN_PROJECT_ID"]
, theprojectId
previously retrieved from the Particle dashboard.manifestPlaceholders["PN_PROJECT_CLIENT_KEY"]
, theclientKey
previously retrieved from the Particle dashboard.manifestPlaceholders["PN_APP_ID"]
, theappId
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.walletConnectProjectId
, wallet connect project id
E.g.:
ParticleWallet.init(WalletMetaData(
"Particle Connect",
"https://connect.particle.network/icons/512.png",
"https://connect.particle.network",
"Particle Connect Flutter Demo",
"WalletConnect project ID"));
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:
tokenAddress
, the address of a token to be auto-filled within the send menu. This can benative
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 bymintAddress
). This can be left asnull
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:
Name | Description | Type | Required |
---|---|---|---|
network | [Solana, Ethereum, Binance Smart Chain, Polygon, Tron, Optimism, etc.] | string | False (True if Particle is not connected) |
fiatCoin | Fiat currency denomination. | string | False |
cryptoCoin | Cryptocurrency denomination. | string | False |
fiatAmt | The amount of fiat to be automatically filled in as the purchase volume. | number | False |
bool | Lock selection of fiat currency in the buy menu. | bool | False |
fixCryptoCoin | Lock selection of cryptocurrency in the buy menu. | bool | False |
fixFiatAmt | Lock selection of fiat amount in the buy menu. | bool | False |
walletAddress | The wallet address to receive the cryptocurrency. | string | False (True if Particle is not connected) |
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:
fromTokenAddress
, the token to swap from.toTokenAddress
, the token to swap to.fromTokenAmount
, the amount offromTokenAddress
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
orfalse
. -
setShowManageWallet
, toggles the display of the wallet management page. It takes a boolean parameter, eithertrue
orfalse
. -
setShowLanguageSetting
, controls the visibility of the language setting option in the settings page. It accepts a boolean value,true
orfalse
. -
setShowAppearanceSetting
, determines whether the appearance setting is shown in the settings page. It takes a boolean value,true
orfalse
. -
setSupportDappBrowser
, configures the availability of the dApp browser feature. It accepts a boolean parameter,true
orfalse
. -
setSupportWalletConnect
, sets whether WalletConnect is supported on the wallet page. It takes a boolean value,true
orfalse
. -
setSupportAddToken
, toggles the option to add tokens, indicated by the variableisShow
. -
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.
Class | Methods | Parameters (* indicates optional) |
---|---|---|
ParticleWallet | init | metaData |
ParticleWallet | navigatorWallet | walletDisplay* |
ParticleWallet | navigatorTokenReceive | tokenAddress* |
ParticleWallet | navigatorTokenSend | tokenAddress*, toAddress_* amount* |
ParticleWallet | navigatorTokenTransactionRecords | tokenAddress* |
ParticleWallet | navigatorNFTSend | mint, tokenId, amount, receiveAddress |
ParticleWallet | navigatorNFTDetails | mint, tokenId |
ParticleWallet | setPayDisabled | disable |
ParticleWallet | getPayDisabled | |
ParticleWallet | setSwapDisabled | disable |
ParticleWallet | getSwapDisabled | |
ParticleWallet | navigatorBuyCrypto | config* |
ParticleWallet | navigatorSwap | fromTokenAddress*, toTokenAddress*, amount* |
ParticleWallet | navigatorDappBrowser | url* |
ParticleWallet | navigatorLoginList | |
ParticleWallet | setShowTestNetwork | enable* |
ParticleWallet | setShowSmartAccountSetting | enable* |
ParticleWallet | setShowManageWallet | enable* |
ParticleWallet | setSupportChain | chainInfos |
ParticleWallet | switchWallet | walletType, publicAddress |
ParticleWallet | setWallet | walletType, publicAddress, pnWalletName* |
ParticleWallet | setSupportDappBrowser | enable* |
ParticleWallet | setShowLanguageSetting | isShow* |
ParticleWallet | setShowAppearanceSetting | isShow* |
ParticleWallet | setSupportAddToken | isShow* |
ParticleWallet | setDisplayTokenAddresses | tokenAddresses |
ParticleWallet | setDisplayNFTContractAddresses | nftContractAddresses |
ParticleWallet | setPriorityTokenAddresses | tokenAddresses |
ParticleWallet | setPriorityNFTContractAddresses | nftContractAddresses |
ParticleWallet | loadCustomUIJsonString | json |
ParticleWallet | setSupportWalletConnect | enable* |
ParticleWallet | setWalletConnectV2ProjectId | walletConnectV2ProjectId |
ParticleWallet | setCustomWalletName | name*, icon* |
ParticleWallet | setCustomLocalizable | localizables |