The Particle Auth Flutter SDK enables full-stack integration of Particle Auth into applications built on Flutter. This includes everything from the initial configuration of Particle’s Wallet-as-a-Service to specific interactions.In this case, Flutter can be leveraged in either Android or iOS environments, both to the same degree. This is done primarily through Dart.
Platform-specific configuration instructions, alongside examples of utilization, can be found below.
Interaction with the Particle Auth Flutter SDK follows a standard approach consistent with other Particle Auth SDKs, though notable differences exist within the configuration process.
The configuration process for this SDK varies significantly depending on whether you’re using Flutter for Android or iOS.
To begin, you’ll need to head over to the Particle dashboard and retrieve your projectId, clientKey, and appId.
Follow the quickstart tutorial to set up a project and find the required keys:
Create a new
project.
Adding the Particle Auth Flutter SDK to your application
Additionally, regardless of platform, you’ll need to begin by adding particle_auth_core to your Flutter application; this is a requirement before moving onto platform-specific configuration.
If you’re building an Android application with Flutter, follow the steps below to configure Particle Auth. To begin, you’ll need to go ahead and open your build.gradle file, often found at the following file path: ${project name}/android/app/build.gradleWithin your build.gradle file, you’ll need to add four new lines to ensure Particle Auth runs appropriately:
minSdkVersion, which in most cases will be set to 23.
manifestPlaceholders["PN_PROJECT_ID"], the projectId previously retrieved from the Particle dashboard.
manifestPlaceholders["PN_PROJECT_CLIENT_KEY"], the clientKey previously retrieved from the Particle dashboard.
manifestPlaceholders["PN_APP_ID"], the appId previously retrieved from the Particle dashboard.
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.
Finally, for dependency management, within build.gradle you’ll need to ensure that the repositories object in both buildscript and allprojects has maven { setUrl("https://jitpack.io") } present, such as is shown below.
If you’re building an iOS application with Flutter, this also entails a unique and iOS-specific configuration process. Before beginning, 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 apps/{project name}.xcworkspace.At the root of your Xcode project, create a new file, ParticleNetwork-Info.plist. Ensure this is marked under Target Membership.Now, with a fresh ParticleNetwork-Info.plist file, go ahead and fill it in with the following:
Similar to the Android configuration, you’ll need to fill in PROJECT_UUID (projectId), PROJECT_CLIENT_KEY, and PROJECT_APP_UUID (appId) with the corresponding values retrieved from the Particle dashboard.To enable Face ID for your app, add a usage description to your Info.plist file by including the following code:
Info.plist
Copy
<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_auth_core is properly imported. Head over to the linked guide to complete this, if you haven’t already.
Another important note before continuing.
Our SDK is a static library (XCFramework). When using the Particle Auth Flutter SDK, you’ll need to specify that you’re using a static framework through the following:
Copy
post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES' end endend
Before using the full extent of the SDK, you’ll need to initialize it with init, passing in the specific chain to which you intend to primarily onboard within Particle’s Wallet-as-a-Service. This is represented as an object containing chain info (often derived from ChainInfo.{Chain}).
Copy
// Set relevant project info, retrieved from https://dashboard.particle.networkParticleInfo.set(projectId, clientKey);// Inititilze ParticleAuth and ParticleAuthCore.ParticleBase.init(ChainInfo.Ethereum, env);ParticleAuthCore.init()
After installing, configuring, and initializing Particle Auth, initiate the login process by using ParticleAuthCore.connect. This triggers a social login prompt, and upon successful authentication, a user account is created, unlocking the full SDK functionality.ParticleAuthCore.connect takes the following parameters:
Field
Type
Description
loginType
LoginType
The specific social login to be used. This can be either .email, .phone, .google, .apple, .jwt, .facebook, .twitter, .discord, .github, .twitch, .microsoft or linkedin.
account
String?
(Optional) When type is set to either .email, .phone, or .jwt, you can use the account parameter to pass in an expected email, phone number, or JWT. This is optional for the former two, but required for .jwt. If passing a phone number, it must be in E.164 format.
prompt
SocialLoginPrompt?
(Optional) Changes what the OAuth provider prompts a user to do; either .none, .consent, or .select_account. Only Google, Discord and Microsoft support it.
The methods of authentication visible on the authentication popup UI. By default, this will be exclusive to the chosen social login method, although by passing in additional types, you can expand the UI to include the ability to login with those as an alternative to type.
You can use your existing user base (account system) or a custom authentication method with Particle Connect through JWT. Click here to learn how to configure JWT.
Copy
// Google or other social loginfinal userInfo = await ParticleAuthCore.connect(LoginType.google, prompt: SocialLoginPrompt.select_account);// Email or phone login, facilitated through Particle's UIfinal userInfo = await ParticleAuthCore.connect(LoginType.email, supportAuthTypes: SupportAuthType.values, prompt: SocialLoginPrompt.select_account);// Custom authentication via JWTfinal userInfo = await ParticleAuthCore.connect(LoginType.jwt, account: jwt);// Configuration of a custom email or phone login page, programmatically driving verification codesfinal result = await ParticleAuthCore.sendEmailCode("user@example.com");final result = await ParticleAuthCore.sendPhoneCode("+11234567890"); // Must be in E.164 format// After a code is sent, the user should enter it within your UI, upon which you can use it for connectionfinal userInfo = await ParticleAuthCore.connectWithCode(email: "user@example.com", code: code);final userInfo = await ParticleAuthCore.connectWithCode(phone: "+11234567890", code: code);
There may be scenarios where it is important to know whether a current session (a user) is logged in with Particle Auth. This is achieved through ParticleAuthCore.isConnected (server-side check).
Copy
final isConnected = await ParticleAuthCore.isConnected();
To request an EIP191 signature from a user’s embedded wallet, you can use either the Evm.personalSign or Evm.personalSignUnique method.If you need the same message to return a unique signature each time, use the Evm.personalSignUnique method. Otherwise, the Evm.personalSign method is generally recommended. On Solana, you can call Solana.signMessage, you can pass in a UTF-8/readable string.
Field
Type
Description
message
String
On Evm requires a hexadeciaml string, on Solana, requires a UTF-8/readable string
This is a Solana-specific method for signing a transaction without sending it. Similar to message signing, this will prompt a signature in-UI with details about the transaction.Programmatically, the proposed transaction should be formatted as a (converted to a) base58 string. Passing in an object directly will not work in this case.
Field
Type
Description
transaction
String
Requires a base58 string
Copy
final signature = await Solana.signTransaction(transaction);
Following the method above, you can use Solana.signAllTransactions to propose a collection of Solana transactions for signature, rather than just a single transaction.
For more generalized transaction execution, Evm.sendTransaction and sendTransactionandSolana.signAndSendTransaction` will be the primary smethods used in virtually every scenario.This will propose a signature (on both EVM and Solana) and then immediately push it to the network once confirmed.
Field
Type
Description
transaction
String
On Evm requires a hexadeciaml string, on Solana, requires a base58 string
Copy
final signature = await Evm.sendTransaction(transaction);final signature = await Solana.signAndSendTransaction(transaction);
To request an EIP712 signature from a user’s embedded wallet, you can use the Evm.signTypedData or Evm.signTypedDataUnique method.If you need the same message to return a unique signature each time, use the Evm.signTypedDataUnique method. Otherwise, the Evm.signTypedData method is generally recommended.
Field
Type
Description
message
String
Requires a hexadeciaml string
Copy
// your typed data is a json stringString typedDataHex = "0x${StringUtils.toHexString(typedData)}";String signature = await Evm.signTypedData(typedDataHex);String signature = await Evm.signTypedDataUnique(typedDataHex);
To change the chain after it’s initially defined in init, you can use ParticleBase.setChainInfo for a synchronous update or ParticleAuthCore.switchChain for an asynchronous update, both typically using ChainInfo.{Chain}.
Another important component of integrating the Particle Auth SDK (Wallet-as-a-Service) is the (optional) security account requirements enforced upon application users.For all Particle accounts, various security options are available, including:
Master Password: A non-recoverable password required upon login.
Payment Password: A PIN required for transaction signatures.
With the SDK, you can determine how often a user is prompted to configure their security settings. This control is facilitated by ParticleBase.setSecurityAccountConfig, where you pass in a SecurityAccountConfig object with two parameters:
Field
Type
Description
promptSettingWhenSign
int
The security account config prompts (default is 1).
promptMasterPasswordSettingWhenLogin
int
The master password prompts (default is 0).
0 means a prompt is never shown requesting this setting.
1 means a prompt is shown only upon the first startup.
2 means a prompt is shown every time.
3 means force set payment password before sign.
Copy
final config = SecurityAccountConfig(1, 2);ParticleBase.setSecurityAccountConfig(config);
Following the above, if you’d like to force the opening of account/security settings (in-UI), you can do so with ParticleAuthCore.openAccountAndSecurity.
Has Master Password, Payment Password, Security Account
Similarly to the isConnected function covered prior, there are various scenarios in which knowing whether or not a user has specific security settings enabled may be useful.In the case of the Particle Auth Flutter SDK, this can happen in one of two ways:With the built-in ParticleAuthCore.hasMasterPassword, ParticleAuthCore.hasPaymentPassword, and ParticleAuthCore.changeMasterPassword methods.
You can forcibly set a specific appearance within the UI using ParticleBase.setAppearance. By default, it will follow the current system setting.
Field
Type
Description
appearance
Appearance
The specific appearance to be used. This can be either .system, .dark, .light.
Copy
// This is the default settingParticleBase.setAppearance(Appearance.system);// Dark modeParticleBase.setAppearance(Appearance.dark);// Light modeParticleBase.setAppearance(Appearance.light);
You can forcibly set a specific language to be used within the UI using ParticleBase.setLanguage, with the retrieval of the currently active language facilitated by ParticleBase.getLanguage. By default, this is set to English.
Field
Type
Description
language
Language
The specific language to be used. This can be either .en, .ja, .zh_hans, .zh_hant, .ko.
Silently sign messages/transactions, this switch will work if the following conditions are met:
your account is connected with JWT
your account does not set payment password
SecurityAccountConfig.promptSettingWhenSign is 0, you can call ParticleBase.setSecurityAccountConfig to update its value.
Copy
// Enable blind signingParticleAuthCore.setBlindEnable(enable);// Retrieve a Boolean representing whether or not blind signing is enabledfinal result = ParticleAuthCore.getBlindEnable();
Filter Unsupported Countries (Phone Authentication)
If necessary, you can restrict specific countries from authenticating via phone number; upon entering a phone number originating from a country specified here, the login modal will block the user.
In addition to ParticleAuthCore for authentication and interaction with Particle’s Wallet-as-a-Service, the Flutter SDK also includes a class, EvmService, for general interaction with EVM chains.
EvmService.writeContract allows you to execute a write contract call defined by a specific method and set of parameters. This requires a corresponding ABI, contract address, and requester public address.
Field
Type
Description
address
String
The user’s public address.
contractAddress
String
The contract address.
methodName
String
The method name that defined in the contract, such as mint, balanceOf.
parameters
List<Object>
The parameters of this method.
abiJsonString
String
The abi json string of this method.
gasFeeLevel
GasFeeLevel
(Optional) The gas fee level, high, medium or low, default is high.
Copy
String contractAddress = "Your contract address";String methodName = "Your method name"; // This is your contract method name, like balanceOf, mint.List<Object> params = <Object>["0x1"]; // This is the method params, each parameter requires a hexadecimal string.// ABI json string for the contract in question.// For example,// [{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"quantity\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]const abiJsonString = null;final result = EvmService.writeContract(publicAddress, contractAddress, methodName, params, abiJsonString, gasFeeLevel: GasFeeLevel.high);
EvmService.readContract allows you to execute a read-only contract call defined by a specific method and set of parameters. This requires a corresponding ABI, contract address, and requester public address.
Field
Type
Description
address
String
The user’s public address.
contractAddress
String
The contract address.
methodName
String
The method name that defined in the contract, such as mint, balanceOf.
parameters
List<Object>
The parameters of this method.
abiJsonString
String
The abi json string of this method.
Copy
String publicAddress = "your public address";String contractAddress = "your contract address";String methodName ="your method name"; // ex: balanceOf, mintList<Object> parameters = <Object>["0x1"]; // This is the method params, each parameter requires a hexadecimal string.// ex: [{"inputs":[{"internalType":"uint256","name":"quantity","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"}]const abiJsonString = null;final result = await EvmService.readContract(publicAddress, contractAddress, methodName, parameters, abiJsonString);
EvmService.createTransaction facilitates the construction of a transaction object derived from the standard from, to (receiver in this example), amount (value), and data fields. This transaction, once constructed with EvmService.createTransaction, can be passed for in-UI proposal with ParticleAuthCore.sendTransaction.
Field
Type
Description
from
String
The user’s public address.
data
String
The transaction’s data.
value
BigInt
The native amount.
to
String
If you send a erc20, erc721, erc1155 or interact with a contract, this is the contract address, if you send native, this is receiver address.
gasFeeLevel
GasFeeLevel
(Optional) the gas fee level, high, medium or low, default is high.
Copy
String from = "Your public address";String receiver = "Receiver address"String contractAddress = "Contract address"BigInt amount = BigInt.from(1000000000000000);String to = contractAddress;final data = await EvmService.erc20Transfer(contractAddress, receiver, amount);final transaction = await EvmService.createTransaction(from, data, amount, to, gasFeeLevel: GasFeeLevel.high);
Given a standard transaction structure (a detached set of values as shown below), you can estimate the gas consumption for a specified transaction using the EvmService.ethEstimateGas method.This acts as a wrapper for eth_estimateGas to simulate and retrieve the estimated gas required.
Copy
final gasLimit = await EvmService.ethEstimateGas(from, to, value, data);
To retrieve categorized gas price suggestions (3 categories scaling from low to high) based upon current network conditions, you can call EvmService.suggestedGasFees.
Copy
final gasFees = await EvmService.suggestedGasFees();
EvmService also extends to Data API methods such as getTokensAndNFTs, which returns a highly detailed JSON list of ERC20 tokens and ERC721 NFTs belonging to a specified address.This is accessible through EvmService.getTokensAndNFTs, passing in the public address to retrieve the tokens and NFTs. Also, you can retrieve tokens from getTokens or NFTs from getNFTs
Field
Type
Description
address
String
The user’s public address.
tokenAddresses
List<String>
The specific tokens’ addresses
Copy
final result = await EvmService.getTokensAndNFTs(publicAddress, []);final result = await EvmService.getTokens(publicAddress, []);final result = await EvmService.getNFTs(publicAddress, []);
Similar to the former method, EvmService.getTransactionsByAddress enables the retrieval of a detailed JSON response containing a complete list of transactions involving a specified address.
Copy
final result = await EvmService.getTransactionsByAddress(publicAddress);
In addition to ParticleAuth for authentication and interaction with Particle’s Wallet-as-a-Service, the Flutter SDK also includes a class, SolanaService, for general interaction with Solana chains.
SolanaService also extends to Data API methods such as getTokensAndNFTs, which returns a highly detailed JSON list of SPL tokens and NFTs belonging to a specified address. This is accessible through SolanaService.getTokensAndNFTs, passing in the public address to retrieve the tokens and NFTs of.
Field
Type
Description
address
String
The user’s public address.
parseMetadataUri
bool
if parse the nft meta data.
Copy
final result = await SolanaService.getTokensAndNFTs(publicAddress, true);
SolanaService.serializeSolTransaction facilitates the construction of a SOL transaction object,SolanaService.serializeSplTokenTransaction facilitates the construction of a Spl-token transaction object,SolanaService.serializeWSolTokenTransaction facilitates the construction of a unwrap WSOL transaction object.These transactions, once constructed, can be passed for in-UI proposal with Solana.signAndSendTransaction.
Copy
final transaction = SerializeSOLTransaction();transaction.lamports = TestAccount.solana.amount.toInt();transaction.receiver = TestAccount.solana.publicAddress;transaction.sender = publicAddress;final result = await SolanaService.serializeSolTransaction(transaction);final serializedTransaction = result["transaction"]["serialized"];