capsule_flutter
This SDK empowers Flutter developers to build highly functional, deeply expressive wallets powering seamless user experiences.
Features
Capsule
class is the main entry point for the SDK. See implemented methods.- Tested on iOS and Android.
- On iOS, you can use a @test.usecapsule.com email to bypass verification for testing.
Prerequisites
You'll need an API key from the Capsule team. Email us at hello@usecapsule.com if you don't have one yet.
If you're building for iOS, install Xcode.
Install Flutter. Here are the steps on MacOS (see flutter.dev for more info).
mkdir ~/repos
cd repos
git clone git@github.com/flutter/flutter
echo 'export PATH=$PATH:~/repos/flutter/bin' >> ~/.zshenv
source ~/.zshenv
flutter channel stable
flutter doctor
Getting started
Create a mobile application with flutter create
if you don't already have one.
flutter create my_application
cd my_application
From the root of your Flutter application, add the Capsule Flutter SDK:
`flutter pub add 'capsule_flutter:{"git":"https://github.com/capsule-org/flutter-sdk"}'`
(Once the SDK is open source, this will just be flutter pub add capsule_flutter
.)
You can now import the Capsule
class in your Flutter code.
import 'package:capsule_flutter/capsule_flutter.git';
final capsule = Capsule(
environment: Environment.beta,
apiKey: '<YOUR API KEY>',
)..init();
Compile and run.
flutter run
Usage
User Creation
await capsule.createUser('test@example.com');
final webAuthURL = await capsule.verifyEmail('123456');
Use a ChromeSafariBrowser
from the
flutter_inappwebview
package to open the web auth URL, so
that you can close it when authentication is complete.
final browser = ChromeSafariBrowser();
await browser.open(url: Uri.parse(webAuthURL));
do {
// Delay to avoid consuming excessive resources
await Future.delayed(const Duration(seconds: 1));
} while ((!(await _capsule.isSessionActive())));
await browser.close();
Signing a transaction
final result = await _capsule.signMessage(
walletId: wallet.id,
messageBase64: base64Encode(
hex.decode(
// hello
'1c8aff950685c2ed4bc3174f3472287b56d9517b9c948127319a09a7a36deac8',
),
),
);
if (result is SuccessfulSignatureResult) {
// It worked! See `result.signature`
}
Signing using typed data
final signer = CapsuleSigner(capsule);
final msgParams = {
'domain': {
// This defines the network.
'chainId': '4',
// Give a user-friendly name to the specific contract you're signing for.
'name': 'Ether Mail',
// Add a verifying contract to make sure you're establishing contracts with the proper entity.
'verifyingContract': '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
// This identifies the latest version.
'version': '1',
},
// This defines the message you're proposing the user to sign, is dapp-specific, and contains
// anything you want. There are no required fields. Be as explicit as possible when building out
// the message schema.
'message': {
'contents': 'Hello, Bob!',
'attachedMoneyInEth': 4.2,
'from': {
'name': 'Cow',
'wallets': [
'0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
'0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF',
],
},
'to': [
{
'name': 'Bob',
'wallets': [
'0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
'0xB0BdaBea57B0BDABeA57b0bdABEA57b0BDabEa57',
'0xB0B0b0b0b0b0B000000000000000000000000000',
],
},
],
},
// This refers to the keys of the following types object.
'primaryType': 'Mail',
'types': {
// This refers to the domain the contract is hosted on.
'EIP712Domain': [
{'name': 'name', 'type': 'string'},
{'name': 'version', 'type': 'string'},
{'name': 'chainId', 'type': 'uint256'},
{'name': 'verifyingContract', 'type': 'address'},
],
// Not an EIP712Domain definition.
'Group': [
{'name': 'name', 'type': 'string'},
{'name': 'members', 'type': 'Person[]'},
],
// Refer to primaryType.
'Mail': [
{'name': 'from', 'type': 'Person'},
{'name': 'to', 'type': 'Person[]'},
{'name': 'contents', 'type': 'string'},
],
// Not an EIP712Domain definition.
'Person': [
{'name': 'name', 'type': 'string'},
{'name': 'wallets', 'type': 'address[]'},
],
},
};
final result = await signer.signTypedData(
from: wallet.address!,
data: msgParams,
version: SignTypedDataVersion.v4,
);
if (result is SuccessfulSignatureResult) {
// It worked! See `result.signature`
}
Documentation
Check out the Developer Documentation and SDK reference to get started!