Skip to content

Commit

Permalink
anchor handling improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-rogobete committed Aug 24, 2023
1 parent 9a3c06e commit 9707d6e
Show file tree
Hide file tree
Showing 26 changed files with 229 additions and 136 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [1.6.2] - 24.Aug.2023.
- anchor handling improvements
- preparations for web support
-
## [1.6.1] - 27.Jul.2023.
- xdr fixes: XdrSCNoceKey, data_io
- soroban contract source code loading
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The Soneso open source Stellar SDK for Flutter is build with Dart and provides A
1. Add the dependency to your pubspec.yaml file:
```
dependencies:
stellar_flutter_sdk: ^1.6.1
stellar_flutter_sdk: ^1.6.2
```
2. Install it (command line or IDE):
```
Expand Down
Binary file modified documentation/sdk_api_doc.zip
Binary file not shown.
1 change: 0 additions & 1 deletion lib/src/muxed_account.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// found in the LICENSE file.

import 'key_pair.dart';
import 'util.dart';
import 'xdr/xdr_type.dart';
import 'xdr/xdr_account.dart';
import 'xdr/xdr_data_io.dart';
Expand Down
1 change: 0 additions & 1 deletion lib/src/requests/liquidity_pools_request_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import '../responses/liquidity_pool_response.dart';
import 'dart:async';
import '../responses/response.dart';
import 'request_builder.dart';
import '../util.dart';

class LiquidityPoolsRequestBuilder extends RequestBuilder {
static const String RESERVES_PARAMETER_NAME = "reserves";
Expand Down
1 change: 0 additions & 1 deletion lib/src/responses/offer_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import 'response.dart';
import '../assets.dart';
import '../key_pair.dart';

/// Represents an offer response received from the horizon server. Offers are statements about how much of an asset an account wants to buy or sell.
/// See: <a href="https://developers.stellar.org/api/resources/offers/" target="_blank">Offer documentation</a>
Expand Down
1 change: 0 additions & 1 deletion lib/src/responses/order_book_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import 'response.dart';
import '../assets.dart';
import '../price.dart';
import '../util.dart';

/// Represents an order book response received from the horizon server. An order book is a collections of offers for a specific pair of assets.
/// See: <a href="https://developers.stellar.org/api/aggregations/order-books/" target="_blank">Order book documentation</a>
Expand Down
4 changes: 4 additions & 0 deletions lib/src/sep/0001/stellar_toml.dart
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ class StellarToml {
currency.isAssetAnchored = item['is_asset_anchored'];
currency.anchorAssetType = item['anchor_asset_type'];
currency.anchorAsset = item['anchor_asset'];
currency.attestationOfReserve = item['attestation_of_reserve'];
currency.redemptionInstructions = item['redemption_instructions'];

var collateralAddresses = item['collateral_addresses'];
Expand Down Expand Up @@ -438,6 +439,9 @@ class Currency {
/// If anchored token, code / symbol for asset that token is anchored to. E.g. USD, BTC, SBUX, Address of real-estate investment property.
String? anchorAsset;

/// URL to attestation or other proof, evidence, or verification of reserves, such as third-party audits.
String? attestationOfReserve;

/// If anchored token, these are instructions to redeem the underlying asset from tokens.
String? redemptionInstructions;

Expand Down
3 changes: 2 additions & 1 deletion lib/src/sep/0009/standard_kyc_fields.dart
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ class OrganizationKYCFields {
/// Organization contact phone
String? phone;

Map<String, String>? fields() {
Map<String, String> fields() {
final fields = <String, String>{};
if (name != null) {
fields['organization.name'] = name!;
Expand Down Expand Up @@ -324,6 +324,7 @@ class OrganizationKYCFields {
if (phone != null) {
fields['organization.phone'] = phone!;
}
return fields;
}

Map<String, Uint8List> files() {
Expand Down
104 changes: 81 additions & 23 deletions lib/src/sep/0010/webauth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ import '../../xdr/xdr_transaction.dart';
import '../0001/stellar_toml.dart';

class WebAuth {
String? _authEndpoint;
String? _serverSigningKey;
Network? _network;
String? _serverHomeDomain;
http.Client httpClient = new http.Client();
String _authEndpoint;
String _serverSigningKey;
Network _network;
String _serverHomeDomain;
late http.Client httpClient;
int gracePeriod = 60 * 5;

/// Constructor
Expand All @@ -34,7 +34,13 @@ class WebAuth {
/// - Parameter serverSigningKey: The server public key, taken from stellar.toml.
/// - Parameter serverHomeDomain: The server home domain of the server where the stellar.toml was loaded from
WebAuth(this._authEndpoint, this._network, this._serverSigningKey,
this._serverHomeDomain);
this._serverHomeDomain, {http.Client? httpClient}) {
if (httpClient != null) {
this.httpClient = httpClient;
} else {
this.httpClient = http.Client();
}
}

/// Creates a WebAuth instance by loading the needed data from the stellar.toml file hosted on the given domain.
/// e.g. fromDomain("soneso.com", Network.TESTNET)
Expand All @@ -51,14 +57,14 @@ class WebAuth {
);

if (toml.generalInformation.webAuthEndpoint == null) {
throw Exception("No WEB_AUTH_ENDPOINT found in stellar.toml");
throw NoWebAuthEndpointFoundException(domain);
}
if (toml.generalInformation.signingKey == null) {
throw Exception("No auth server SIGNING_KEY found in stellar.toml");
throw NoWebAuthServerSigningKeyFoundException(domain);
}

return new WebAuth(toml.generalInformation.webAuthEndpoint, network,
toml.generalInformation.signingKey, domain);
return new WebAuth(toml.generalInformation.webAuthEndpoint!, network,
toml.generalInformation.signingKey!, domain, httpClient: httpClient);
}

/// Get JWT token for wallet.
Expand All @@ -85,13 +91,12 @@ class WebAuth {
clientDomainAccountId = clientDomainAccountKeyPair.accountId;
} else if (clientDomainSigningDelegate != null) {
if (clientDomain == null) {
throw Exception(
"The clientDomain is required if clientDomainSigningDelegate is provided");
throw MissingClientDomainException();
}
final StellarToml clientToml =
await StellarToml.fromDomain(clientDomain, httpClient: httpClient);
if (clientToml.generalInformation.signingKey == null) {
throw Exception("No client domain SIGNING_KEY found in stellar.toml");
throw NoClientDomainSigningKeyFoundException(clientDomain);
}
clientDomainAccountId = clientToml.generalInformation.signingKey;
}
Expand Down Expand Up @@ -128,7 +133,7 @@ class WebAuth {

String? transaction = challengeResponse.transaction;
if (transaction == null) {
throw Exception("Error parsing challenge response");
throw MissingTransactionInChallengeResponseException();
}
return transaction;
}
Expand Down Expand Up @@ -203,13 +208,13 @@ class WebAuth {
}
}

if (i == 0 && dataName != _serverHomeDomain! + " auth") {
if (i == 0 && dataName != _serverHomeDomain + " auth") {
throw ChallengeValidationErrorInvalidHomeDomain(
"invalid home domain in operation $i");
}
final dataValue = op.body.manageDataOp!.dataValue!.dataValue;
if (i > 0 && dataName == "web_auth_domain") {
final uri = Uri.parse(_authEndpoint!);
final uri = Uri.parse(_authEndpoint);
if (uri.host != String.fromCharCodes(dataValue)) {
throw ChallengeValidationErrorInvalidWebAuthDomain(
"invalid web auth domain in operation $i");
Expand Down Expand Up @@ -240,9 +245,9 @@ class WebAuth {
}
final firstSignature = envelopeXdr.v1!.signatures[0];
// validate signature
final serverKeyPair = KeyPair.fromAccountId(_serverSigningKey!);
final serverKeyPair = KeyPair.fromAccountId(_serverSigningKey);
final transactionHash =
AbstractTransaction.fromEnvelopeXdr(envelopeXdr).hash(_network!);
AbstractTransaction.fromEnvelopeXdr(envelopeXdr).hash(_network);
final valid = serverKeyPair.verify(
transactionHash, firstSignature.signature!.signature!);
if (!valid) {
Expand All @@ -260,7 +265,7 @@ class WebAuth {
}

final txHash =
AbstractTransaction.fromEnvelopeXdr(envelopeXdr).hash(_network!);
AbstractTransaction.fromEnvelopeXdr(envelopeXdr).hash(_network);

List<XdrDecoratedSignature> signatures =
List<XdrDecoratedSignature>.empty(growable: true);
Expand All @@ -276,7 +281,7 @@ class WebAuth {
/// In case of success, it returns the jwt token obtained from the web auth server.
Future<String> sendSignedChallengeTransaction(
String base64EnvelopeXDR) async {
Uri serverURI = Uri.parse(_authEndpoint!);
Uri serverURI = Uri.parse(_authEndpoint);

Map<String, String> headers = {...RequestBuilder.headers};
headers.putIfAbsent("Content-Type", () => "application/json");
Expand Down Expand Up @@ -314,11 +319,10 @@ class WebAuth {
Future<ChallengeResponse> getChallengeResponse(String accountId,
[int? memo, String? homeDomain, String? clientDomain]) async {
if (memo != null && accountId.startsWith("M")) {
throw new Exception(
"memo cannot be used if accountId is a muxed account");
throw NoMemoForMuxedAccountsException();
}

Uri serverURI = Uri.parse(_authEndpoint!);
Uri serverURI = Uri.parse(_authEndpoint);
try {
_ChallengeRequestBuilder requestBuilder =
new _ChallengeRequestBuilder(httpClient, serverURI);
Expand Down Expand Up @@ -500,3 +504,57 @@ class SubmitCompletedChallengeErrorResponseException implements Exception {

String get error => _error;
}

class NoWebAuthEndpointFoundException implements Exception {
String domain;

NoWebAuthEndpointFoundException(this.domain);

String toString() {
return "No WEB_AUTH_ENDPOINT found in stellar.toml for domain: $domain";
}
}

class NoWebAuthServerSigningKeyFoundException implements Exception {
String domain;

NoWebAuthServerSigningKeyFoundException(this.domain);

String toString() {
return "No auth server SIGNING_KEY found in stellar.toml for domain: $domain";
}
}

class NoClientDomainSigningKeyFoundException implements Exception {
String domain;

NoClientDomainSigningKeyFoundException(this.domain);

String toString() {
return "No client domain SIGNING_KEY found in stellar.toml for domain: $domain";
}
}

class MissingClientDomainException implements Exception {
MissingClientDomainException();

String toString() {
return "The clientDomain is required if clientDomainSigningDelegate is provided";
}
}

class MissingTransactionInChallengeResponseException implements Exception {
MissingTransactionInChallengeResponseException();

String toString() {
return "Missing transaction in challenge response";
}
}

class NoMemoForMuxedAccountsException implements Exception {
NoMemoForMuxedAccountsException();

String toString() {
return "Memo cannot be used if account is a muxed account";
}
}
Loading

0 comments on commit 9707d6e

Please sign in to comment.