Skip to content

Commit

Permalink
add recovery to flutter wallet sdk (#288)
Browse files Browse the repository at this point in the history
* add recovery to flutter wallet sdk

* add stellar to flutter wallet sdk

* update flutter wallet sdk version nr
  • Loading branch information
christian-rogobete authored Jan 22, 2024
1 parent db612a1 commit 6a96e93
Show file tree
Hide file tree
Showing 5 changed files with 338 additions and 4 deletions.
27 changes: 27 additions & 0 deletions docs/building-apps/wallet/component/dart/configClient.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { CodeExample } from "@site/src/components/CodeExample";

### Configuring the Client

The Flutter Wallet SDK uses the standard Client from the [http package](https://pub.dev/packages/http) for all network requests (excluding Horizon, where the Flutter Stellar SDK's HTTP client is used).

Optionally, you can set your own client from [http package](https://pub.dev/packages/http) to be used across the app.

The client can be globally configured:

<CodeExample>

```dart
import 'package:http/http.dart';
// ...
// init and configure your HTTP client
// var myClient = ...
// set as default HTTP client
var appConfig = ApplicationConfiguration(defaultClient: myClient);
var walletCustomClient = Wallet(StellarConfiguration.testNet, applicationConfiguration: appConfig);
```

</CodeExample>

Some [test cases](https://github.com/Soneso/stellar_wallet_flutter_sdk/tree/main/test) of this SDK use for example the `MockClient`.
4 changes: 2 additions & 2 deletions docs/building-apps/wallet/component/dart/install.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { CodeExample } from "@site/src/components/CodeExample";

```dart
// pubspec.yaml
stellar_wallet_flutter_sdk: ^0.0.2
stellar_flutter_sdk: ^1.6.9
stellar_wallet_flutter_sdk: ^0.1.0
stellar_flutter_sdk: ^1.7.1
```

</CodeExample>
Expand Down
13 changes: 11 additions & 2 deletions docs/building-apps/wallet/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import DartInstall from "./component/dart/install.mdx";
import KtHttpConfig from "./component/kt/httpConfig.mdx";
import KtConfigClient from "./component/kt/configClient.mdx";
import TsConfigClient from "./component/ts/configClient.mdx";
import DartConfigClient from "./component/dart/configClient.mdx";

<Header WIPLangs={["dart"]} />

Expand Down Expand Up @@ -40,7 +41,7 @@ let wallet = walletSdk.Wallet.TestNet();
```

```dart
var wallet = Wallet(StellarConfiguration.testNet);
var wallet = Wallet.testNet;
```

</CodeExample>
Expand All @@ -67,7 +68,11 @@ var wallet = Wallet(StellarConfiguration.publicNet);

<LanguageSpecific kt={<KtHttpConfig />} />

<LanguageSpecific kt={<KtConfigClient />} ts={<TsConfigClient />} />
<LanguageSpecific
kt={<KtConfigClient />}
ts={<TsConfigClient />}
dart={<DartConfigClient />}
/>

## Stellar Basics

Expand All @@ -85,6 +90,10 @@ val stellar = wallet.stellar()
const stellar = wallet.stellar();
```

```dart
var stellar = wallet.stellar();
```

</CodeExample>

This example will create a Stellar class that manages the connection to Horizon service.
Expand Down
85 changes: 85 additions & 0 deletions docs/building-apps/wallet/sep30.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const recoveryKp = wallet.stellar().account().createKeypair();
val recoveryKp = wallet.stellar().account().createKeyPair()
```

```dart
var accountKp = wallet.stellar().account().createKeyPair();
var deviceKp = wallet.stellar().account().createKeyPair();
var recoveryKp = wallet.stellar().account().createKeyPair();
```

</CodeExample>

The `accountKp` is the wallet's main account. The `deviceKp` we will be adding to the wallet as a signer so a device (eg. a mobile device a wallet is hosted on) can take control of the account. And the `recoveryKp` will be used to identify the key with the recovery servers.
Expand Down Expand Up @@ -65,6 +71,15 @@ val servers = mapOf(first to firstServer, second to secondServer)
val recovery = wallet.recovery(servers)
```

```dart
var first = RecoveryServerKey("first");
var second = RecoveryServerKey("second");
var firstServer = RecoveryServer("https://recovery.example1.com", "https://auth.example1.com", "recovery.example1.com");
var secondServer = RecoveryServer("https://recovery.example2.com", "https://auth.example2.com", "recovery.example2.com");
var servers = {first:firstServer, second:secondServer};
var recovery = wallet.recovery(servers);
```

</CodeExample>

Next, we need to define SEP-30 identities. In this example we are going to create an identity for both servers. Registering an identity tells the recovery server what identities are allowed to access the account.
Expand Down Expand Up @@ -107,6 +122,19 @@ const identity2 = {
)
```

```dart
var identity1 = [
RecoveryAccountIdentity(RecoveryRole.owner, [
RecoveryAccountAuthMethod(RecoveryType.stellarAddress, recoveryKp.address)
])
];
var identity2 = [
RecoveryAccountIdentity(RecoveryRole.owner,
[RecoveryAccountAuthMethod(RecoveryType.email, "[email protected]")])
];
```

</CodeExample>

Here, stellar key and email are used as recovery methods. Other recovery servers may support phone as a recovery method as well.
Expand Down Expand Up @@ -141,6 +169,18 @@ const recoverableWallet = await recovery.createRecoverableWallet(config);
)
```

```dart
var recoverableWallet = await recovery.createRecoverableWallet(
RecoverableWalletConfig(
accountKp,
deviceKp,
AccountThreshold(10, 10, 10),
{first: identity1, second: identity2},
SignerWeight(10, 5)
)
);
```

</CodeExample>

With the given parameters, this function will create a transaction that will:
Expand All @@ -166,6 +206,12 @@ await stellar.submitTransaction(recoverableWallet.transaction);
wallet.stellar().submitTransaction(tx)
```

```dart
var transaction = recoverableWallet.transaction;
transaction.sign(accountKp.keyPair, flutter_sdk.Network.TESTNET);
await wallet.stellar().submitTransaction(transaction);
```

</CodeExample>

## Get Account Info
Expand All @@ -184,6 +230,11 @@ const authToken = await recovery
val auth1 = recovery.sep10Auth(first).authenticate(recoveryKp)
```

```dart
var sep10 = await recovery.sep10Auth(first);
var authToken = await sep10.authenticate(recoveryKp);
```

</CodeExample>

Next, get account info using auth tokens:
Expand All @@ -202,6 +253,10 @@ const accountResp = await recovery.getAccountInfo(accountKp, {
println("Recoverable info: $accountInfo")
```

```dart
var accountInfo = await recovery.getAccountInfo(accountKp, {first: authToken.jwt});
```

</CodeExample>

Our second identity uses an email as an auth method. For that we can't use a [SEP-10] auth token for that server. Instead we need to use a token that ties the email to the user. For example, Firebase tokens are a good use case for this. To use this, the recovery signer server needs to be prepared to handle these kinds of tokens.
Expand All @@ -228,6 +283,10 @@ const accountResp = await recovery.getAccountInfo(accountKp, {
println("Recoverable info: $accountInfo")
```

```dart
var accountInfo = await recovery.getAccountInfo(accountKp, {second: <other token string>});
```

</CodeExample>

## Recover Wallet
Expand All @@ -254,6 +313,14 @@ const firebaseToken = AuthToken.from(<firebase token string>)
val firebaseToken = AuthToken.from(<firebase token string>)
```

```dart
var sep10 = await recovery.sep10Auth(first);
var authToken = await sep10.authenticate(recoveryKp);
var auth1 = authToken.jwt;
var auth2 = "..."; // get other token e.g. firebase token
```

</CodeExample>

We need to know the recovery signer addresses that will be used to sign the transaction. You can get them from either the recoverable wallet object we created earlier (`recoverableWallet.signers`), or via fetching account info from recovery servers.
Expand All @@ -269,6 +336,10 @@ const recoverySignerAddress2 = recoverableWallet.signers[1];
val recoverySigners = recoverableWallet.signers
```

```dart
var recoverySigners = recoverableWallet.signers;
```

</CodeExample>

Next, create a new device key and retrieve a signed transaction that replaces the device key:
Expand Down Expand Up @@ -312,6 +383,16 @@ const recoverTxn = await recovery.replaceDeviceKey(
)
```

```dart
var newKey = wallet.stellar().account().createKeyPair();
var serverAuth = {
first: RecoveryServerSigning(recoverySigners[0], auth1),
second: RecoveryServerSigning(recoverySigners[1], auth2)
};
var signedReplaceKeyTx = await recovery.replaceDeviceKey(accountKp, newKey, serverAuth);
```

</CodeExample>

Calling this function will create a transaction that locks the previous device key and replaces it with your new key (having the same weight as the old one). Both recovery signers will have signed the transaction.
Expand All @@ -337,6 +418,10 @@ await stellar.submitTransaction(recoverTxn);
wallet.stellar().submitTransaction(signedReplaceKeyTransaction)
```

```dart
await wallet.stellar().submitTransaction(signedReplaceKeyTx);
```

</CodeExample>

[sep-30]: https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0030.md
Loading

0 comments on commit 6a96e93

Please sign in to comment.