Dynamic Package
Please be aware that our Flutter SDK is in open alpha at the moment!
Available now:
- email login (headless)
- sms login (headless)
- auth flow UI
- profile UI
- EVM embedded wallets
- web3dart integration
Coming next:
- social login
- solana embedded wallets
Installation
Simply run the following in your terminal:
flutter pub add dynamic_sdk
This will add a line like this to your package’s pubspec.yaml (and run an implicit flutter pub get):
dependencies:
dynamic_sdk: ^0.0.1-alpha.2
Set up
Getting started with DynamicSDK
takes only three steps:
1. Initialize your client
First you have to start the client singleton with your data in ClientProps
;
import 'package:dynamic_sdk/dynamic_sdk.dart';
void main() {
WidgetsFlutterBinding.ensureInitialized();
DynamicSDK.init(
props: ClientProps(
environmentId: 'your-environment-id',
appLogoUrl: 'your-logo-url',
appName: 'your-app-name',
),
);
runApp(const MyApp());
}
2. Wait for the SDK to load
Add the DynamicSDK.instance.dynamicWidget
and wait for the SDK to loaded using the DynamicSDK.instance.sdk.readyChanges
stream;
class MyApp extends StatelessWidget {
const MyApp({super.key});
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: Stack(
children: [
// Make sure the SDK is ready before using it
StreamBuilder<bool?>(
stream: DynamicSDK.instance.sdk.readyChanges,
builder: (context, snapshot) {
final sdkReady = snapshot.data ?? false;
return sdkReady
? const MyHomePage(title: 'Flutter Demo Home Page')
: const SizedBox.shrink();
},
),
// DynamicSDK widget must be available all the time
DynamicSDK.instance.dynamicWidget,
],
),
);
}
}
3. Do your stuff
That’s it! Now you are good to go! See below how to authenticate using our UI:
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Column(
children: [
// Listen to auth token changes
StreamBuilder<String?>(
stream: DynamicSDK.instance.auth.tokenChanges,
builder: (context, snapshot) {
final authToken = snapshot.data;
// Show the auth token when logged in
return authToken != null
? Column(
children: [
const LogoutButton(),
const SizedBox(height: 24),
Text('AUTH TOKEN: $authToken'),
],
)
// Show Dynamic UI for sign in
: const LoginButton();
},
),
],
),
],
),
),
),
);
}
}
// Show Dynamic UI for sign in
class LoginButton extends StatelessWidget {
const LoginButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => DynamicSDK.instance.ui.showAuth(),
child: const Text('Dynamic Login'),
);
}
}
// Headless logout function
class LogoutButton extends StatelessWidget {
const LogoutButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => DynamicSDK.instance.auth.logout(),
child: const Text('Logout'),
);
}
}
Available modules
Let’s walk you through the available modules and how to use most of the features.
SDK Module
- Get to know when the SDK is ready to be used by listening to
readyChanges
stream.
StreamBuilder<bool?>(
stream: DynamicSDK.instance.sdk.readyChanges,
builder: (context, snapshot) {
final sdkReady = snapshot.data ?? false;
return sdkReady
? const MyHomePage(title: 'Flutter Demo Home Page')
: const SizedBox.shrink();
},
),
User Interface Module
- Use our interface to sign in
class LoginButton extends StatelessWidget {
const LoginButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => DynamicSDK.instance.ui.showAuth(),
child: const Text('Dynamic Login'),
);
}
}
- Use our interface to see the user’s profile
class UserProfileButton extends StatelessWidget {
const UserProfileButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => DynamicSDK.instance.ui.showUserProfile(),
child: const Text('Show Profile'),
);
}
}
Auth Module (headless authentication)
- Headless e-mail sign in
class EmailLoginButton extends StatelessWidget {
const EmailLoginButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async => await DynamicSDK.instance.auth.email.sendOTP(
'[email protected]'
),
child: const Text('Email Login'),
);
}
}
- Headless SMS sign in
class SMSLoginButton extends StatelessWidget {
const SMSLoginButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () async => await DynamicSDK.instance.auth.sms.sendOTP(
PhoneData(
phone: phone, // User's phone number
iso2: 'US',
dialCode: '+1',
),
),
child: const Text('SMS Login'),
);
}
}
- Verity OTP
class VerifyOTPButton extends StatelessWidget {
const VerifyOTPButton({
super.key,
});
Widget build(BuildContext context) {
return ElevatedButton(
// For email use await DynamicSDK.instance.auth.email.verifyOTP(code),
onPressed: () async => await DynamicSDK.instance.auth.sms.verifyOTP(code), // Verification code
child: const Text('Verify Code'),
);
}
}
Wallets Module
- Get network
Future<String> getNetworkInfo({required BaseWallet wallet}) async {
final network = await DynamicSDK.instance.wallets.getNetwork(wallet: wallet);
final name = getNetworkName(network.value);
return name;
}
String getNetworkName(networkId) {
final evm = DynamicSDK.instance.networks.evm;
bool isEvm = evm.any((network) => network.networkId == networkId);
if (isEvm) {
final network = evm.firstWhere(
(network) {
return network.networkId == networkId;
},
);
return network.name;
} else {
return networkId;
}
}
- Switch networks
void switchNetwork({
required BaseWallet wallet,
required int chainId,
}) async {
await DynamicSDK.instance.wallets.switchNetwork(
wallet: wallet,
network: Network(chainId),
);
}
- Sign message
Future<String?> signMessage({
required String message,
required BaseWallet wallet,
}) async {
try {
final signedMessage = await DynamicSDK.instance.wallets.signMessage(
message: message,
wallet: wallet,
);
return signedMessage;
} catch (e) {
print(e);
rethrow;
}
}
Other methods like getBalance
and setPrimary
are as straight forward as the ones above.
You can read more about our client package here.
Was this page helpful?