├── _config.yml ├── example ├── ios │ ├── Flutter │ │ ├── .last_build_id │ │ ├── Debug.xcconfig │ │ ├── Release.xcconfig │ │ └── AppFrameworkInfo.plist │ ├── Runner │ │ ├── Runner-Bridging-Header.h │ │ ├── Assets.xcassets │ │ │ ├── LaunchImage.imageset │ │ │ │ ├── LaunchImage.png │ │ │ │ ├── LaunchImage@2x.png │ │ │ │ ├── LaunchImage@3x.png │ │ │ │ ├── README.md │ │ │ │ └── Contents.json │ │ │ └── AppIcon.appiconset │ │ │ │ ├── Icon-App-20x20@1x.png │ │ │ │ ├── Icon-App-20x20@2x.png │ │ │ │ ├── Icon-App-20x20@3x.png │ │ │ │ ├── Icon-App-29x29@1x.png │ │ │ │ ├── Icon-App-29x29@2x.png │ │ │ │ ├── Icon-App-29x29@3x.png │ │ │ │ ├── Icon-App-40x40@1x.png │ │ │ │ ├── Icon-App-40x40@2x.png │ │ │ │ ├── Icon-App-40x40@3x.png │ │ │ │ ├── Icon-App-60x60@2x.png │ │ │ │ ├── Icon-App-60x60@3x.png │ │ │ │ ├── Icon-App-76x76@1x.png │ │ │ │ ├── Icon-App-76x76@2x.png │ │ │ │ ├── Icon-App-1024x1024@1x.png │ │ │ │ ├── Icon-App-83.5x83.5@2x.png │ │ │ │ └── Contents.json │ │ ├── AppDelegate.swift │ │ ├── Base.lproj │ │ │ ├── Main.storyboard │ │ │ └── LaunchScreen.storyboard │ │ └── Info.plist │ ├── Runner.xcodeproj │ │ ├── project.xcworkspace │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata │ │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ │ └── IDEWorkspaceChecks.plist │ │ └── xcshareddata │ │ │ └── xcschemes │ │ │ └── Runner.xcscheme │ ├── Runner.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcshareddata │ │ │ ├── WorkspaceSettings.xcsettings │ │ │ └── IDEWorkspaceChecks.plist │ └── .gitignore ├── lib │ ├── stellar_quest │ │ ├── stellar_quest.dart │ │ ├── series_1 │ │ │ ├── series_1.dart │ │ │ ├── 03_manage_data.dart │ │ │ ├── 01_create_account.dart │ │ │ ├── 02_send_payment.dart │ │ │ ├── 06_create_sell_offer_custom_asset.dart │ │ │ ├── 04_multisign.dart │ │ │ ├── 08_custom_path_payment.dart │ │ │ ├── 07_payment_with_channel_account.dart │ │ │ └── 05_create_and_send_custom_asset.dart │ │ └── series_2 │ │ │ ├── series_2.dart │ │ │ ├── 08_host_stellar_toml_file.dart │ │ │ ├── 04_create_claimable_balance.dart │ │ │ ├── 07_revoke_sponsorship.dart │ │ │ ├── 01_create_and_fund.dart │ │ │ ├── 05_claim_claimable_balance.dart │ │ │ ├── 06_create_account_sponsored.dart │ │ │ ├── 03_fee_bump_trans.dart │ │ │ └── 02_multi_operational_trans.dart │ └── extensions │ │ ├── extensions.dart │ │ ├── key_pair_extensions.dart │ │ ├── account_response_extensions.dart │ │ ├── submit_transaction_response_extras_extensions.dart │ │ ├── xdr_operation_result_extensions.dart │ │ └── submit_transaction_response_extensions.dart ├── android │ ├── gradle.properties │ ├── .gitignore │ ├── app │ │ ├── src │ │ │ ├── main │ │ │ │ ├── res │ │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ │ └── ic_launcher.png │ │ │ │ │ ├── drawable │ │ │ │ │ │ └── launch_background.xml │ │ │ │ │ └── values │ │ │ │ │ │ └── styles.xml │ │ │ │ ├── kotlin │ │ │ │ │ └── com │ │ │ │ │ │ └── example │ │ │ │ │ │ └── example │ │ │ │ │ │ └── MainActivity.kt │ │ │ │ └── AndroidManifest.xml │ │ │ ├── debug │ │ │ │ └── AndroidManifest.xml │ │ │ └── profile │ │ │ │ └── AndroidManifest.xml │ │ └── build.gradle │ ├── gradle │ │ └── wrapper │ │ │ └── gradle-wrapper.properties │ ├── settings.gradle │ └── build.gradle ├── .metadata ├── README.md ├── .gitignore ├── pubspec.yaml └── health_check_example.dart ├── test ├── wasm │ ├── sep_45_account.wasm │ ├── soroban_auth_contract.wasm │ ├── soroban_events_contract.wasm │ ├── soroban_token_contract.wasm │ ├── soroban_atomic_swap_contract.wasm │ └── soroban_hello_world_contract.wasm ├── tests_util.dart └── contract_bindings │ ├── hello_contract_client.dart │ └── atomic_swap_contract_client.dart ├── lib ├── stub │ ├── web.dart │ └── non-web.dart └── src │ ├── xdr │ ├── xdr_error.dart │ ├── xdr_data_entry.dart │ ├── xdr_bucket.dart │ ├── xdr_memo.dart │ ├── xdr_auth.dart │ └── xdr_network.dart │ ├── asset_type_native.dart │ ├── responses │ ├── health_response.dart │ ├── effects │ │ └── misc_effects_responses.dart │ └── operations │ │ ├── inflation_operation_response.dart │ │ ├── restore_footprint_operation_response.dart │ │ ├── extend_footprint_ttl_operation_response.dart │ │ ├── bump_sequence_operation_response.dart │ │ └── manage_data_operation_response.dart │ ├── requests │ └── health_request_builder.dart │ ├── eventsource │ └── event.dart │ ├── account.dart │ ├── network.dart │ ├── asset_type_credit_alphanum4.dart │ └── asset_type_credit_alphanum12.dart ├── .github ├── ISSUE_TEMPLATE │ ├── config.yml │ ├── feature_request.yml │ └── bug_report.yml └── workflows │ └── docs.yml ├── .metadata ├── pubspec.yaml ├── LICENSE ├── documentation ├── sdk_examples │ ├── send_native_payment.md │ ├── bump_sequence.md │ ├── stream_payments.md │ ├── sep-0030.md │ ├── create_account.md │ ├── merge_account.md │ ├── fee_bump.md │ ├── sep-0001-toml.md │ ├── manage_data.md │ ├── sep-0002-federation.md │ ├── trustline.md │ ├── sep-0010-webauth.md │ ├── muxed_account_payment.md │ └── change_trust.md └── installation.md ├── compatibility ├── rpc │ └── RPC_COMPATIBILITY_MATRIX.md └── sep │ ├── SEP-0046_COMPATIBILITY_MATRIX.md │ ├── SEP-0047_COMPATIBILITY_MATRIX.md │ └── SEP-0002_COMPATIBILITY_MATRIX.md ├── .gitignore ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md └── mentions └── mentions.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-hacker -------------------------------------------------------------------------------- /example/ios/Flutter/.last_build_id: -------------------------------------------------------------------------------- 1 | 23867fb3fa1e216f841efe5b9fb86eac -------------------------------------------------------------------------------- /example/ios/Flutter/Debug.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Flutter/Release.xcconfig: -------------------------------------------------------------------------------- 1 | #include "Generated.xcconfig" 2 | -------------------------------------------------------------------------------- /example/ios/Runner/Runner-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | #import "GeneratedPluginRegistrant.h" 2 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/stellar_quest.dart: -------------------------------------------------------------------------------- 1 | export 'series_1/series_1.dart'; 2 | export 'series_2/series_2.dart'; 3 | -------------------------------------------------------------------------------- /test/wasm/sep_45_account.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/sep_45_account.wasm -------------------------------------------------------------------------------- /test/wasm/soroban_auth_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/soroban_auth_contract.wasm -------------------------------------------------------------------------------- /test/wasm/soroban_events_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/soroban_events_contract.wasm -------------------------------------------------------------------------------- /test/wasm/soroban_token_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/soroban_token_contract.wasm -------------------------------------------------------------------------------- /example/android/gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1536M 2 | android.enableR8=true 3 | android.useAndroidX=true 4 | android.enableJetifier=true -------------------------------------------------------------------------------- /test/wasm/soroban_atomic_swap_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/soroban_atomic_swap_contract.wasm -------------------------------------------------------------------------------- /test/wasm/soroban_hello_world_contract.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/test/wasm/soroban_hello_world_contract.wasm -------------------------------------------------------------------------------- /example/android/.gitignore: -------------------------------------------------------------------------------- 1 | gradle-wrapper.jar 2 | /.gradle 3 | /captures/ 4 | /gradlew 5 | /gradlew.bat 6 | /local.properties 7 | GeneratedPluginRegistrant.java 8 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/android/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/android/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png -------------------------------------------------------------------------------- /lib/stub/web.dart: -------------------------------------------------------------------------------- 1 | // Stub file to to replace foundation.dart in detecting web and non-web platforms. 2 | // kIsWeb should be TRUE in web.dart and FALSE in non-web.dart 3 | 4 | const bool kIsWeb = true; 5 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png -------------------------------------------------------------------------------- /lib/stub/non-web.dart: -------------------------------------------------------------------------------- 1 | // Stub file to to replace foundation.dart in detecting web and non-web platforms. 2 | // kIsWeb should be TRUE in web.dart and FALSE in non-web.dart 3 | 4 | const bool kIsWeb = false; 5 | -------------------------------------------------------------------------------- /example/android/app/src/main/kotlin/com/example/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.example.example 2 | 3 | import io.flutter.embedding.android.FlutterActivity 4 | 5 | class MainActivity: FlutterActivity() { 6 | } 7 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Soneso/stellar_flutter_sdk/HEAD/example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: 💬 Feedback & Discussions 4 | url: https://github.com/Soneso/stellar_flutter_sdk/discussions 5 | about: For open-ended questions, ideas, or general feedback, please use Discussions. 6 | 7 | -------------------------------------------------------------------------------- /example/lib/extensions/extensions.dart: -------------------------------------------------------------------------------- 1 | export 'account_response_extensions.dart'; 2 | export 'key_pair_extensions.dart'; 3 | export 'submit_transaction_response_extensions.dart'; 4 | export 'submit_transaction_response_extras_extensions.dart'; 5 | export 'xdr_operation_result_extensions.dart'; 6 | -------------------------------------------------------------------------------- /example/android/gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Jun 23 08:50:38 CEST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip 7 | -------------------------------------------------------------------------------- /example/lib/extensions/key_pair_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | extension KeyPairX on KeyPair { 4 | XdrSignerKey get xdrSignerKey { 5 | return XdrSignerKey(XdrSignerKeyType.SIGNER_KEY_TYPE_ED25519) 6 | ..ed25519 = xdrPublicKey.getEd25519(); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/lib/extensions/account_response_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | extension AccountResponseX on AccountResponse { 4 | void printBalances() { 5 | balances.forEach((element) { 6 | print("${element.assetCode}: ${element.balance}"); 7 | }); 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | PreviewsEnabled 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: b041144f833e05cf463b8887fa12efdec9493488 8 | channel: stable 9 | 10 | project_type: package 11 | -------------------------------------------------------------------------------- /example/.metadata: -------------------------------------------------------------------------------- 1 | # This file tracks properties of this Flutter project. 2 | # Used by Flutter tool to assess capabilities and perform upgrades etc. 3 | # 4 | # This file should be version controlled and should not be manually edited. 5 | 6 | version: 7 | revision: 1ad9baa8b99a2897c20f9e6e54d3b9b359ade314 8 | channel: stable 9 | 10 | project_type: app 11 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/series_1.dart: -------------------------------------------------------------------------------- 1 | export '01_create_account.dart'; 2 | export '02_send_payment.dart'; 3 | export '03_manage_data.dart'; 4 | export '04_multisign.dart'; 5 | export '05_create_and_send_custom_asset.dart'; 6 | export '06_create_sell_offer_custom_asset.dart'; 7 | export '07_payment_with_channel_account.dart'; 8 | export '08_custom_path_payment.dart'; 9 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/series_2.dart: -------------------------------------------------------------------------------- 1 | export '01_create_and_fund.dart'; 2 | export '02_multi_operational_trans.dart'; 3 | export '03_fee_bump_trans.dart'; 4 | export '04_create_claimable_balance.dart'; 5 | export '05_claim_claimable_balance.dart'; 6 | export '06_create_account_sponsored.dart'; 7 | export '07_revoke_sponsorship.dart'; 8 | export '08_host_stellar_toml_file.dart'; 9 | -------------------------------------------------------------------------------- /example/README.md: -------------------------------------------------------------------------------- 1 | 2 | **This folder contains our demo app.**
3 | **If you are looking for our source code examples, you can find them [here](https://github.com/Soneso/stellar_flutter_sdk/tree/master/documentation/sdk_examples).** 4 | 5 | ## Demo App 6 | 7 | The implementation of the app is currently in progress. 8 | 9 | ## Start the app 10 | 11 | Start the app: flutter run 12 | -------------------------------------------------------------------------------- /example/android/app/src/debug/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/android/app/src/profile/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md: -------------------------------------------------------------------------------- 1 | # Launch Screen Assets 2 | 3 | You can customize the launch screen with your own desired assets by replacing the image files in this directory. 4 | 5 | You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. -------------------------------------------------------------------------------- /example/ios/Runner/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | import UIKit 2 | import Flutter 3 | 4 | @UIApplicationMain 5 | @objc class AppDelegate: FlutterAppDelegate { 6 | override func application( 7 | _ application: UIApplication, 8 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? 9 | ) -> Bool { 10 | GeneratedPluginRegistrant.register(with: self) 11 | return super.application(application, didFinishLaunchingWithOptions: launchOptions) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /example/lib/extensions/submit_transaction_response_extras_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 4 | 5 | extension SubmitTransactionResponseExtrasX on SubmitTransactionResponseExtras { 6 | XdrTransactionResult get resultXdrDecoded { 7 | final result = XdrTransactionResult.decode( 8 | XdrDataInputStream( 9 | base64Decode(resultXdr), 10 | ), 11 | ); 12 | return result; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/drawable/launch_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 12 | 13 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "LaunchImage.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "filename" : "LaunchImage@2x.png", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "filename" : "LaunchImage@3x.png", 16 | "scale" : "3x" 17 | } 18 | ], 19 | "info" : { 20 | "version" : 1, 21 | "author" : "xcode" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /example/ios/.gitignore: -------------------------------------------------------------------------------- 1 | *.mode1v3 2 | *.mode2v3 3 | *.moved-aside 4 | *.pbxuser 5 | *.perspectivev3 6 | **/*sync/ 7 | .sconsign.dblite 8 | .tags* 9 | **/.vagrant/ 10 | **/DerivedData/ 11 | Icon? 12 | **/Pods/ 13 | **/.symlinks/ 14 | profile 15 | xcuserdata 16 | **/.generated/ 17 | Flutter/App.framework 18 | Flutter/Flutter.framework 19 | Flutter/Flutter.podspec 20 | Flutter/Generated.xcconfig 21 | Flutter/app.flx 22 | Flutter/app.zip 23 | Flutter/flutter_assets/ 24 | Flutter/flutter_export_environment.sh 25 | ServiceDefinitions.json 26 | Runner/GeneratedPluginRegistrant.* 27 | 28 | # Exceptions to above rules. 29 | !default.mode1v3 30 | !default.mode2v3 31 | !default.pbxuser 32 | !default.perspectivev3 33 | -------------------------------------------------------------------------------- /example/android/settings.gradle: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Flutter Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | include ':app' 6 | 7 | def localPropertiesFile = new File(rootProject.projectDir, "local.properties") 8 | def properties = new Properties() 9 | 10 | assert localPropertiesFile.exists() 11 | localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } 12 | 13 | def flutterSdkPath = properties.getProperty("flutter.sdk") 14 | assert flutterSdkPath != null, "flutter.sdk not set in local.properties" 15 | apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" 16 | -------------------------------------------------------------------------------- /example/android/build.gradle: -------------------------------------------------------------------------------- 1 | buildscript { 2 | ext.kotlin_version = '1.7.0' 3 | repositories { 4 | google() 5 | mavenCentral() 6 | } 7 | 8 | dependencies { 9 | classpath 'com.android.tools.build:gradle:4.2.2' 10 | classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" 11 | } 12 | } 13 | 14 | allprojects { 15 | repositories { 16 | google() 17 | mavenCentral() 18 | } 19 | } 20 | 21 | rootProject.buildDir = '../build' 22 | subprojects { 23 | project.buildDir = "${rootProject.buildDir}/${project.name}" 24 | } 25 | subprojects { 26 | project.evaluationDependsOn(':app') 27 | } 28 | 29 | task clean(type: Delete) { 30 | delete rootProject.buildDir 31 | } 32 | -------------------------------------------------------------------------------- /pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: stellar_flutter_sdk 2 | description: A Stellar SDK for Flutter, that can query Horizon and Soroban RPC, build, signs and submit transactions to Stellar. Supports many SEPs and can deploy and invoke Soroban Contracts. 3 | version: 2.2.1 4 | homepage: https://github.com/Soneso/stellar_flutter_sdk 5 | 6 | environment: 7 | sdk: ">=3.8.0 <4.0.0" 8 | 9 | dependencies: 10 | flutter: 11 | sdk: flutter 12 | 13 | crypto: ^3.0.6 14 | fixnum: ^1.1.1 15 | http: ^1.5.0 16 | collection: ^1.18.0 17 | toml: ^0.17.0 18 | pointycastle: ^4.0.0 19 | unorm_dart: ^0.3.1+1 20 | decimal: ^3.2.4 21 | pinenacl: ^0.6.0 22 | convert: ^3.1.2 23 | http_parser: ^4.0.2 24 | dio: ^5.9.0 25 | 26 | dev_dependencies: 27 | flutter_test: 28 | sdk: flutter 29 | -------------------------------------------------------------------------------- /example/lib/extensions/xdr_operation_result_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | extension XdrOperationResultX on XdrOperationResult { 4 | void printResult() { 5 | print('CODE: ${discriminant.value}'); 6 | printCreateClaimableBalanceResult(); 7 | printManageSellOfferResult(); 8 | } 9 | 10 | void printCreateClaimableBalanceResult() { 11 | final result = tr?.createClaimableBalanceResult; 12 | if (result == null) { 13 | return; 14 | } 15 | print( 16 | 'CLAIMABLE_BALANCE_ID: ${result.balanceID}', 17 | ); 18 | } 19 | 20 | void printManageSellOfferResult() { 21 | final result = tr?.manageOfferResult?.success; 22 | if (result == null) { 23 | return; 24 | } 25 | print( 26 | 'OFFER_ID: ${result.offer.offer?.offerID}', 27 | ); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /example/.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | 12 | # IntelliJ related 13 | *.iml 14 | *.ipr 15 | *.iws 16 | .idea/ 17 | 18 | # The .vscode folder contains launch configuration and tasks you configure in 19 | # VS Code which you may wish to be included in version control, so this line 20 | # is commented out by default. 21 | #.vscode/ 22 | 23 | # Flutter/Dart/Pub related 24 | **/doc/api/ 25 | .dart_tool/ 26 | .flutter-plugins 27 | .flutter-plugins-dependencies 28 | .packages 29 | .pub-cache/ 30 | .pub/ 31 | /build/ 32 | 33 | # Web related 34 | lib/generated_plugin_registrant.dart 35 | 36 | # Symbolication related 37 | app.*.symbols 38 | 39 | # Obfuscation related 40 | app.*.map.json 41 | 42 | # Exceptions to above rules. 43 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 44 | -------------------------------------------------------------------------------- /example/ios/Flutter/AppFrameworkInfo.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | App 9 | CFBundleIdentifier 10 | io.flutter.flutter.app 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | App 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1.0 23 | MinimumOSVersion 24 | 11.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/03_manage_data.dart: -------------------------------------------------------------------------------- 1 | import 'dart:typed_data'; 2 | 3 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 4 | 5 | import '../../extensions/extensions.dart'; 6 | 7 | Future manageData({ 8 | required StellarSDK sdk, 9 | required Network network, 10 | String? value, 11 | }) async { 12 | final sourceKeyPair = KeyPair.fromSecretSeed( 13 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 14 | ); 15 | 16 | final manageDataBuilder = ManageDataOperationBuilder( 17 | "Hello", 18 | Uint8List.fromList("World".codeUnits), 19 | ); 20 | 21 | final sourceAccount = await sdk.accounts.account( 22 | sourceKeyPair.accountId, 23 | ); 24 | 25 | final transactionBuilder = TransactionBuilder(sourceAccount) 26 | ..addOperation(manageDataBuilder.build()); 27 | 28 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 29 | 30 | final result = await sdk.submitTransaction(transaction); 31 | 32 | result.printResult(); 33 | } 34 | -------------------------------------------------------------------------------- /example/android/app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 15 | 18 | 19 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/01_create_account.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future createAccount({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final newAccountKeyPair = KeyPair.random(); 14 | 15 | final createAccountBuilder = CreateAccountOperationBuilder( 16 | newAccountKeyPair.accountId, 17 | "1000", 18 | ); 19 | 20 | final sourceAccount = await sdk.accounts.account( 21 | sourceKeyPair.accountId, 22 | ); 23 | 24 | final transactionBuilder = TransactionBuilder(sourceAccount) 25 | ..addOperation(createAccountBuilder.build()); 26 | 27 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 28 | 29 | final result = await sdk.submitTransaction(transaction); 30 | 31 | result.printResult(); 32 | } 33 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/02_send_payment.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/extensions.dart'; 4 | 5 | Future sendPayment({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final destinationAccountId = 14 | "GAS4V4O2B7DW5T7IQRPEEVCRXMDZESKISR7DVIGKZQYYV3OSQ5SH5LVP"; 15 | 16 | final paymentBuilder = PaymentOperationBuilder( 17 | destinationAccountId, 18 | Asset.NATIVE, 19 | "10", 20 | ); 21 | 22 | final sourceAccount = await sdk.accounts.account( 23 | sourceKeyPair.accountId, 24 | ); 25 | 26 | final transactionBuilder = TransactionBuilder(sourceAccount) 27 | ..addOperation(paymentBuilder.build()); 28 | 29 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 30 | 31 | final result = await sdk.submitTransaction(transaction); 32 | 33 | result.printResult(); 34 | } 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Soneso 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/08_host_stellar_toml_file.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future hostStellarTomlFile({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 11 | // GAS4N4UW4CU24AIVQIIGDW6ENUYZUVZ7Z3MH5GVYGQHVKXLJ2GBDP6RQ 12 | ); 13 | 14 | // Your domain that contains the .well-known/stellar.toml file. 15 | final domain = "88fhbx.csb.app"; 16 | 17 | final setOptionsBuilder = SetOptionsOperationBuilder()..setHomeDomain(domain); 18 | 19 | final sourceAccount = await sdk.accounts.account( 20 | sourceKeyPair.accountId, 21 | ); 22 | 23 | final transactionBuilder = TransactionBuilder(sourceAccount) 24 | ..addOperation(setOptionsBuilder.build()); 25 | 26 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 27 | 28 | final result = await sdk.submitTransaction(transaction); 29 | 30 | result.printResult(); 31 | } 32 | -------------------------------------------------------------------------------- /test/tests_util.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | class TestUtils { 4 | static void resultDeAndEncodingTest(AbstractTransaction transaction, SubmitTransactionResponse response) { 5 | String? metaXdrStr = response.resultMetaXdr; 6 | if (metaXdrStr != null) { 7 | XdrTransactionMeta? meta = response.getTransactionMetaResultXdr(); 8 | assert(meta != null); 9 | assert(metaXdrStr == meta!.toBase64EncodedXdrString()); 10 | } 11 | 12 | String envelopeXdrStr = response.envelopeXdr!; 13 | XdrTransactionEnvelope envelope = XdrTransactionEnvelope.fromEnvelopeXdrString(envelopeXdrStr); 14 | assert(envelopeXdrStr == envelope.toEnvelopeXdrBase64()); 15 | 16 | String resultXdrStr = response.resultXdr!; 17 | XdrTransactionResult result = XdrTransactionResult.fromBase64EncodedXdrString(resultXdrStr); 18 | assert(resultXdrStr == result.toBase64EncodedXdrString()); 19 | 20 | String? feeMetaXdrStr = response.feeMetaXdr; 21 | if (feeMetaXdrStr != null) { 22 | XdrLedgerEntryChanges changes = response.getFeeMetaXdr()!; 23 | assert(feeMetaXdrStr == changes.toBase64EncodedXdrString()); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/06_create_sell_offer_custom_asset.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future createSellOfferCustomAsset({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final issuingKeyPair = KeyPair.fromSecretSeed( 14 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 15 | ); 16 | 17 | final asset = Asset.createNonNativeAsset( 18 | "JOPM", 19 | issuingKeyPair.accountId, 20 | ); 21 | 22 | final operation = ManageSellOfferOperationBuilder( 23 | asset, 24 | Asset.NATIVE, 25 | "1", 26 | "1", 27 | ); 28 | 29 | final sourceAccount = await sdk.accounts.account( 30 | sourceKeyPair.accountId, 31 | ); 32 | 33 | final transactionBuilder = TransactionBuilder(sourceAccount) 34 | ..addOperation(operation.build()); 35 | 36 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 37 | 38 | final result = await sdk.submitTransaction(transaction); 39 | 40 | result.printResult(); 41 | } 42 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/04_multisign.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/extensions.dart'; 4 | 5 | Future multisign({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAH3BXVHQY4YMJIDQWUALJVNI6J2UAIZNPMC2Z4MV6CXFKAHZ6JGVD5G", 11 | // GDPQJAQXFBRJ3N6EXACC2XXCRSDZHFHTLK3DX4XDYAUWD3HRWTYWADRS 12 | ); 13 | 14 | final extraSignerKeyPair = KeyPair.fromSecretSeed( 15 | "SBK6NJQU5CK2IW7ALJVOE6E3FJ6TBOXDGWWVZR5B6XZCFAPFGNVGDMIJ", 16 | // GDPCNC4AVEAP7HBMIWMTD3D4EQS65EASDZTR3BYGVUBMKGDZGPAXDSNI 17 | ); 18 | 19 | final setOptionsBuilder = SetOptionsOperationBuilder() 20 | ..setSourceAccount(sourceKeyPair.accountId) 21 | ..setSigner(extraSignerKeyPair.xdrSignerKey, 1); 22 | 23 | final sourceAccount = await sdk.accounts.account( 24 | sourceKeyPair.accountId, 25 | ); 26 | 27 | final transactionBuilder = TransactionBuilder(sourceAccount) 28 | ..addOperation(setOptionsBuilder.build()); 29 | 30 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 31 | 32 | final result = await sdk.submitTransaction(transaction); 33 | 34 | result.printResult(); 35 | } 36 | -------------------------------------------------------------------------------- /.github/workflows/docs.yml: -------------------------------------------------------------------------------- 1 | name: Generate and Deploy Documentation 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | workflow_dispatch: 8 | 9 | permissions: 10 | contents: read 11 | pages: write 12 | id-token: write 13 | 14 | concurrency: 15 | group: "pages" 16 | cancel-in-progress: false 17 | 18 | jobs: 19 | build: 20 | runs-on: ubuntu-latest 21 | 22 | steps: 23 | - name: Checkout repository 24 | uses: actions/checkout@v4 25 | 26 | - name: Setup Flutter 27 | uses: subosito/flutter-action@v2 28 | with: 29 | channel: 'stable' 30 | 31 | - name: Install dependencies 32 | run: flutter pub get 33 | 34 | - name: Generate documentation 35 | run: dart doc 36 | 37 | - name: Setup Pages 38 | uses: actions/configure-pages@v4 39 | 40 | - name: Upload artifact 41 | uses: actions/upload-pages-artifact@v3 42 | with: 43 | path: 'doc/api' 44 | 45 | deploy: 46 | environment: 47 | name: github-pages 48 | url: ${{ steps.deployment.outputs.page_url }} 49 | runs-on: ubuntu-latest 50 | needs: build 51 | 52 | steps: 53 | - name: Deploy to GitHub Pages 54 | id: deployment 55 | uses: actions/deploy-pages@v4 56 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/04_create_claimable_balance.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future createClaimableBalance({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 11 | // GAS4N4UW4CU24AIVQIIGDW6ENUYZUVZ7Z3MH5GVYGQHVKXLJ2GBDP6RQ 12 | ); 13 | 14 | final createClaimableBalanceBuilder = CreateClaimableBalanceOperationBuilder( 15 | [ 16 | Claimant( 17 | sourceKeyPair.accountId, 18 | Claimant.predicateNot( 19 | Claimant.predicateBeforeRelativeTime(60), 20 | ), 21 | ) 22 | ], 23 | Asset.NATIVE, 24 | "100", 25 | ); 26 | 27 | final sourceAccount = await sdk.accounts.account( 28 | sourceKeyPair.accountId, 29 | ); 30 | 31 | final transactionBuilder = TransactionBuilder(sourceAccount) 32 | ..addOperation(createClaimableBalanceBuilder.build()); 33 | 34 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 35 | 36 | final result = await sdk.submitTransaction(transaction); 37 | 38 | result.printResult(); 39 | } 40 | -------------------------------------------------------------------------------- /example/lib/extensions/submit_transaction_response_extensions.dart: -------------------------------------------------------------------------------- 1 | import 'dart:convert'; 2 | 3 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 4 | 5 | import 'xdr_operation_result_extensions.dart'; 6 | 7 | extension SubmitTransactionResponseX on SubmitTransactionResponse { 8 | void printResult() { 9 | if (success) { 10 | print('Transaction submitted successfully!'); 11 | final results = resultXdrDecoded.result.results as List?; 12 | if (results == null) { 13 | return; 14 | } 15 | for (var result in results) { 16 | if (result is XdrOperationResult) { 17 | result.printResult(); 18 | } 19 | } 20 | } else { 21 | print('Transaction failed!'); 22 | if (extras?.resultCodes?.transactionResultCode?.isNotEmpty ?? false) { 23 | print(extras?.resultCodes?.transactionResultCode); 24 | } 25 | if (extras?.resultCodes?.operationsResultCodes?.isNotEmpty ?? false) { 26 | extras?.resultCodes?.operationsResultCodes?.forEach(print); 27 | } 28 | } 29 | } 30 | 31 | XdrTransactionResult get resultXdrDecoded { 32 | final result = XdrTransactionResult.decode( 33 | XdrDataInputStream( 34 | base64Decode(resultXdr!), 35 | ), 36 | ); 37 | return result; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/07_revoke_sponsorship.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future revokeSponsorship({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sponsoringKeyPair = KeyPair.fromSecretSeed( 10 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 11 | // GAS4N4UW4CU24AIVQIIGDW6ENUYZUVZ7Z3MH5GVYGQHVKXLJ2GBDP6RQ 12 | ); 13 | 14 | final sponsoredKeyPair = KeyPair.fromSecretSeed( 15 | "SAEK3QP7NNXS7ZI3XVDMSLGWC3TSPNSAELV42GDWVC6NAK7WFM657ARF", 16 | // GDJQPIBYZJKW4GSP6CCNKUFC2F3CUSRA3MY2RNWCRN7HG4RVDFN5EUJT 17 | ); 18 | 19 | final revokeSponsorshipBuilder = RevokeSponsorshipOperationBuilder() 20 | ..revokeAccountSponsorship(sponsoredKeyPair.accountId); 21 | 22 | final sponsoringAccount = await sdk.accounts.account( 23 | sponsoringKeyPair.accountId, 24 | ); 25 | 26 | final transactionBuilder = TransactionBuilder(sponsoringAccount) 27 | ..addOperation(revokeSponsorshipBuilder.build()); 28 | 29 | final transaction = transactionBuilder.build() 30 | ..sign(sponsoringKeyPair, network); 31 | 32 | final result = await sdk.submitTransaction(transaction); 33 | 34 | result.printResult(); 35 | } 36 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/01_create_and_fund.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future createAndFundAccount({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAH3BXVHQY4YMJIDQWUALJVNI6J2UAIZNPMC2Z4MV6CXFKAHZ6JGVD5G", 11 | // GDPQJAQXFBRJ3N6EXACC2XXCRSDZHFHTLK3DX4XDYAUWD3HRWTYWADRS 12 | ); 13 | 14 | final newAccountKeyPair = KeyPair.fromSecretSeed( 15 | "SBK6NJQU5CK2IW7ALJVOE6E3FJ6TBOXDGWWVZR5B6XZCFAPFGNVGDMIJ", 16 | // GDPCNC4AVEAP7HBMIWMTD3D4EQS65EASDZTR3BYGVUBMKGDZGPAXDSNI 17 | ); 18 | 19 | final createAccountBuilder = CreateAccountOperationBuilder( 20 | newAccountKeyPair.accountId, 21 | "5000", 22 | ); 23 | 24 | final sourceAccount = await sdk.accounts.account( 25 | sourceKeyPair.accountId, 26 | ); 27 | 28 | final transactionBuilder = TransactionBuilder(sourceAccount) 29 | ..addOperation(createAccountBuilder.build()) 30 | ..addMemo(MemoHash.string( 31 | "e3366fcb087bdb2381b7069a19405b748da831c18145eba25654d1092e93ef37", 32 | )); 33 | 34 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 35 | 36 | final result = await sdk.submitTransaction(transaction); 37 | 38 | result.printResult(); 39 | } 40 | -------------------------------------------------------------------------------- /documentation/sdk_examples/send_native_payment.md: -------------------------------------------------------------------------------- 1 | 2 | ### Send a native (XLM) payment 3 | 4 | In this example we will send a native payment (XLM - Stellar Lumens) from a sender stellar account to a destination stellar account. 5 | 6 | ```dart 7 | // First create the sender key pair from the secret seed of the sender so we can use it later for signing. 8 | KeyPair senderKeyPair = KeyPair.fromSecretSeed("SAPS66IJDXUSFDSDKIHR4LN6YPXIGCM5FBZ7GE66FDKFJRYJGFW7ZHYF"); 9 | 10 | // Next, we need the account id of the receiver so that we can use to as a destination of our payment. 11 | String destination = "GDXPJR65A6EXW7ZIWWIQPO6RKTPG3T2VWFBS3EAHJZNFW6ZXG3VWTTSK"; 12 | 13 | // Load sender's account data from the stellar network. It contains the current sequence number. 14 | AccountResponse sender = await sdk.accounts.account(senderKeyPair.accountId); 15 | 16 | // Build the transaction to send 100 XLM native payment from sender to destination 17 | Transaction transaction = new TransactionBuilder(sender) 18 | .addOperation(PaymentOperationBuilder(destination,Asset.NATIVE, "100").build()) 19 | .build(); 20 | 21 | // Sign the transaction with the sender's key pair. 22 | transaction.sign(senderKeyPair, Network.TESTNET); 23 | 24 | // Submit the transaction to the stellar network. 25 | SubmitTransactionResponse response = await sdk.submitTransaction(transaction); 26 | if (response.success) { 27 | print("Payment sent"); 28 | } 29 | ``` 30 | -------------------------------------------------------------------------------- /documentation/sdk_examples/bump_sequence.md: -------------------------------------------------------------------------------- 1 | 2 | ### Bump account sequence number 3 | 4 | In this example we will bump the sequence number of an account to a higher number. 5 | 6 | ```dart 7 | // Create a random key pair for a new account. 8 | KeyPair accountKeyPair = KeyPair.random(); 9 | 10 | // Account Id. 11 | String accountId = accountKeyPair.accountId; 12 | 13 | // Create account. 14 | await FriendBot.fundTestAccount(accountId); 15 | 16 | // Load account data to get the current sequence number. 17 | AccountResponse account = await sdk.accounts.account(accountId); 18 | 19 | // Remember current sequence number. 20 | int startSequence = account.sequenceNumber; 21 | 22 | // Prepare the bump sequence operation to bump the sequence number to current + 10. 23 | BumpSequenceOperationBuilder bumpSequenceOpB = 24 | BumpSequenceOperationBuilder(startSequence + BigInt.from(10)); 25 | 26 | // Prepare the transaction. 27 | Transaction transaction = TransactionBuilder(account) 28 | .addOperation(bumpSequenceOpB.build()) 29 | .build(); 30 | 31 | // Sign the transaction. 32 | transaction.sign(accountKeyPair, Network.TESTNET); 33 | 34 | // Submit the transaction. 35 | await sdk.submitTransaction(transaction); 36 | 37 | // Load the account again. 38 | account = await sdk.accounts.account(accountId); 39 | 40 | // Check that the new sequence number has correctly been bumped. 41 | if(startSequence + BigInt.from(10) == account.sequenceNumber) { 42 | print("success"); 43 | } else { 44 | print("failed"); 45 | } 46 | ``` 47 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/08_custom_path_payment.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future customPathPayment({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final issuerAccountId = 14 | "GCDNJUBQSX7AJWLJACMJ7I4BC3Z47BQUTMHEICZLE6MU4KQBRYG5JY6B"; 15 | 16 | final asset = Asset.createNonNativeAsset( 17 | "SRT", 18 | issuerAccountId, 19 | ); 20 | 21 | // Creat a trustline from the receiving account (source) to the issuing account 22 | final trustlineOperationBuilder = ChangeTrustOperationBuilder( 23 | asset, 24 | "200", 25 | ); 26 | 27 | final paymentsOperationBuilder = PathPaymentStrictReceiveOperationBuilder( 28 | Asset.NATIVE, 29 | "200", 30 | sourceKeyPair.accountId, 31 | asset, 32 | "1", 33 | ); 34 | 35 | final sourceAccount = await sdk.accounts.account( 36 | sourceKeyPair.accountId, 37 | ); 38 | 39 | final transactionBuilder = TransactionBuilder(sourceAccount) 40 | ..addOperation(trustlineOperationBuilder.build()) 41 | ..addOperation(paymentsOperationBuilder.build()); 42 | 43 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 44 | 45 | final result = await sdk.submitTransaction(transaction); 46 | 47 | result.printResult(); 48 | } 49 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/05_claim_claimable_balance.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future claimClaimableBalance({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 11 | // GAS4N4UW4CU24AIVQIIGDW6ENUYZUVZ7Z3MH5GVYGQHVKXLJ2GBDP6RQ 12 | ); 13 | // await FriendBot.fundTestAccount(sourceKeyPair.accountId); 14 | 15 | final claimableBalance = await getLatestClaimbaleBalance(sdk, sourceKeyPair); 16 | 17 | final claimClaimableBalanceBuilder = ClaimClaimableBalanceOperationBuilder( 18 | claimableBalance.balanceId, 19 | ); 20 | 21 | final sourceAccount = await sdk.accounts.account( 22 | sourceKeyPair.accountId, 23 | ); 24 | 25 | final transactionBuilder = TransactionBuilder(sourceAccount) 26 | ..addOperation(claimClaimableBalanceBuilder.build()); 27 | 28 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 29 | 30 | final result = await sdk.submitTransaction(transaction); 31 | 32 | result.printResult(); 33 | } 34 | 35 | Future getLatestClaimbaleBalance( 36 | StellarSDK sdk, 37 | KeyPair sourceKeyPair, 38 | ) async { 39 | final claimableBalances = await sdk.claimableBalances 40 | .forClaimant(sourceKeyPair.accountId) 41 | .order(RequestBuilderOrder.DESC) 42 | .execute(); 43 | assert(claimableBalances.records.isNotEmpty); 44 | 45 | return claimableBalances.records.first; 46 | } 47 | -------------------------------------------------------------------------------- /compatibility/rpc/RPC_COMPATIBILITY_MATRIX.md: -------------------------------------------------------------------------------- 1 | # Soroban RPC vs Flutter SDK Compatibility Matrix 2 | 3 | **Generated:** 2025-12-18 14:04:38 4 | 5 | **SDK Version:** 2.2.1 6 | 7 | ## Overall Coverage 8 | 9 | **Coverage:** 100.0% 10 | 11 | - ✅ **Fully Supported:** 12/12 12 | - ⚠️ **Partially Supported:** 0/12 13 | - ❌ **Not Supported:** 0/12 14 | 15 | ## Method Comparison 16 | 17 | | RPC Method | Status | Flutter Method | Required Params | Notes | 18 | |------------|--------|----------------|-----------------|-------| 19 | | `getEvents` | ✅ Fully Supported | `getEvents` | 1/1 | All parameters implemented | 20 | | `getFeeStats` | ✅ Fully Supported | `getFeeStats` | N/A | All parameters implemented | 21 | | `getHealth` | ✅ Fully Supported | `getHealth` | N/A | All parameters implemented | 22 | | `getLatestLedger` | ✅ Fully Supported | `getLatestLedger` | N/A | All parameters implemented | 23 | | `getLedgerEntries` | ✅ Fully Supported | `getLedgerEntries` | 1/1 | All parameters implemented | 24 | | `getLedgers` | ✅ Fully Supported | `getLedgers` | 1/1 | All parameters implemented | 25 | | `getNetwork` | ✅ Fully Supported | `getNetwork` | N/A | All parameters implemented | 26 | | `getTransaction` | ✅ Fully Supported | `getTransaction` | 1/1 | All parameters implemented | 27 | | `getTransactions` | ✅ Fully Supported | `getTransactions` | 1/1 | All parameters implemented | 28 | | `getVersionInfo` | ✅ Fully Supported | `getVersionInfo` | N/A | All parameters implemented | 29 | | `sendTransaction` | ✅ Fully Supported | `sendTransaction` | 1/1 | All parameters implemented | 30 | | `simulateTransaction` | ✅ Fully Supported | `simulateTransaction` | 1/1 | All parameters implemented | 31 | 32 | ## Implementation Gaps 33 | 34 | -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/06_create_account_sponsored.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future createAccountSponsored({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sponsoringKeyPair = KeyPair.fromSecretSeed( 10 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 11 | // GAS4N4UW4CU24AIVQIIGDW6ENUYZUVZ7Z3MH5GVYGQHVKXLJ2GBDP6RQ 12 | ); 13 | 14 | final newSponsoredKeyPair = KeyPair.fromSecretSeed( 15 | "SAEK3QP7NNXS7ZI3XVDMSLGWC3TSPNSAELV42GDWVC6NAK7WFM657ARF", 16 | // GDJQPIBYZJKW4GSP6CCNKUFC2F3CUSRA3MY2RNWCRN7HG4RVDFN5EUJT 17 | ); 18 | 19 | final beginSponsoringBuilder = BeginSponsoringFutureReservesOperationBuilder( 20 | newSponsoredKeyPair.accountId, 21 | ); 22 | 23 | final createAccountBuilder = CreateAccountOperationBuilder( 24 | newSponsoredKeyPair.accountId, 25 | "1", 26 | ); 27 | 28 | final endSponsoringBuilder = EndSponsoringFutureReservesOperationBuilder() 29 | ..setSourceAccount(newSponsoredKeyPair.accountId); 30 | 31 | final sponsoringAccount = await sdk.accounts.account( 32 | sponsoringKeyPair.accountId, 33 | ); 34 | 35 | final transactionBuilder = TransactionBuilder(sponsoringAccount) 36 | ..addOperation(beginSponsoringBuilder.build()) 37 | ..addOperation(createAccountBuilder.build()) 38 | ..addOperation(endSponsoringBuilder.build()); 39 | 40 | final transaction = transactionBuilder.build() 41 | ..sign(sponsoringKeyPair, network) 42 | ..sign(newSponsoredKeyPair, network); 43 | 44 | final result = await sdk.submitTransaction(transaction); 45 | 46 | result.printResult(); 47 | } 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.yml: -------------------------------------------------------------------------------- 1 | name: "Feature Request" 2 | description: Suggest a new feature or improvement for the Flutter Stellar SDK 3 | labels: ["feedback", "enhancement"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | 🙌 Thanks for taking the time to suggest a feature! 9 | Please fill out the sections below to help us understand your request. 10 | 11 | - type: input 12 | id: summary 13 | attributes: 14 | label: "Feature Summary" 15 | description: "Briefly describe the feature you’d like to see." 16 | placeholder: "Example: Add support for [specific operation]" 17 | 18 | - type: textarea 19 | id: motivation 20 | attributes: 21 | label: "Why is this feature needed?" 22 | description: "Tell us what problem this would solve or how it would help developers." 23 | placeholder: "Example: This would make it easier to..." 24 | validations: 25 | required: true 26 | 27 | - type: textarea 28 | id: details 29 | attributes: 30 | label: "Proposed Solution" 31 | description: "Describe how you imagine this feature could be implemented or used." 32 | placeholder: "Example: Provide a helper method like..." 33 | 34 | - type: textarea 35 | id: alternatives 36 | attributes: 37 | label: "Alternatives Considered" 38 | description: "If you’ve thought about other ways to solve this, list them here." 39 | placeholder: "Example: I could work around this by..." 40 | 41 | - type: dropdown 42 | id: priority 43 | attributes: 44 | label: "How important is this feature to you?" 45 | options: 46 | - Nice to have 47 | - Important 48 | - Blocker 49 | default: 0 50 | 51 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/07_payment_with_channel_account.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future paymentWithChannelAccount({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final channelKeyPair = KeyPair.fromSecretSeed( 14 | "SC2CE4BNEGTLQQCT67FKX2YOV4UWFQCY2ZZM7I3EARE7P4CRFDUZN76E", 15 | // GBPETPHGYG3PLWH3YVZB6R4IOTFXKMBTT4JWLUJAMGWBJA5IDFJSMBTH 16 | ); 17 | 18 | final destinationAccountId = 19 | "GAZ5IBV4ESG4U65ILOVWIL6SM5CEK24VSZKCTGBPZTJY2PURM32L7WAJ"; 20 | 21 | final channelAccount = await sdk.accounts.account( 22 | channelKeyPair.accountId, 23 | ); 24 | 25 | // So the payment is send from the source to the destination account. Note 26 | // that the channel account will pay the fee not the source account. Because 27 | // the channel account is the source account of the transaction. 28 | final operation = PaymentOperationBuilder( 29 | destinationAccountId, 30 | Asset.NATIVE, 31 | "5", 32 | )..setSourceAccount(sourceKeyPair.accountId); 33 | 34 | // The source account of the transaction always pays the fee and is called 35 | // channel account. 36 | final transactionBuilder = TransactionBuilder(channelAccount) 37 | ..addOperation(operation.build()); 38 | 39 | final transaction = transactionBuilder.build() 40 | ..sign(sourceKeyPair, network) 41 | ..sign(channelKeyPair, network); 42 | 43 | final result = await sdk.submitTransaction(transaction); 44 | 45 | result.printResult(); 46 | } 47 | -------------------------------------------------------------------------------- /example/ios/Runner/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | example 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | $(FLUTTER_BUILD_NAME) 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(FLUTTER_BUILD_NUMBER) 23 | LSRequiresIPhoneOS 24 | 25 | UILaunchStoryboardName 26 | LaunchScreen 27 | UIMainStoryboardFile 28 | Main 29 | UISupportedInterfaceOrientations 30 | 31 | UIInterfaceOrientationPortrait 32 | UIInterfaceOrientationLandscapeLeft 33 | UIInterfaceOrientationLandscapeRight 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | UIViewControllerBasedStatusBarAppearance 43 | 44 | CADisableMinimumFrameDurationOnPhone 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /documentation/sdk_examples/stream_payments.md: -------------------------------------------------------------------------------- 1 | 2 | ### Stream for payments 3 | 4 | In this example we will listen for received payments for an account. 5 | 6 | ```dart 7 | // Create two accounts, so that we can send a payment. 8 | KeyPair keyPairA = KeyPair.random(); 9 | KeyPair keyPairB = KeyPair.random(); 10 | String accountBId = keyPairB.accountId; 11 | String accountAId = keyPairA.accountId; 12 | await FriendBot.fundTestAccount(accountAId); 13 | await FriendBot.fundTestAccount(accountBId); 14 | 15 | // Load current data of account B. 16 | AccountResponse accountB = await sdk.accounts.account(accountBId); 17 | 18 | // Subscribe to listen for payments for account A. 19 | // If we set the cursor to "now" it will not receive old events such as the create account operation. 20 | StreamSubscription subscription = sdk.payments.forAccount(accountAId).cursor("now").stream().listen((response) { 21 | if (response is PaymentOperationResponse) { 22 | switch (response.assetType) { 23 | case Asset.TYPE_NATIVE: 24 | print("Payment of ${response.amount} XLM from ${response.sourceAccount} received."); 25 | break; 26 | default: 27 | print("Payment of ${response.amount} ${response.assetCode} from ${response.sourceAccount} received."); 28 | } 29 | } 30 | }); 31 | 32 | // Send 10 XLM from account B to account A. 33 | Transaction transaction = new TransactionBuilder(accountB) 34 | .addOperation(PaymentOperationBuilder(accountAId, Asset.NATIVE, "10").build()) 35 | .build(); 36 | transaction.sign(keyPairB, Network.TESTNET); 37 | await sdk.submitTransaction(transaction); 38 | 39 | // When you are done listening to that stream, for any reason, you may close/cancel the subscription. 40 | // In this example we wait 5 seconds for the payment event. 41 | await Future.delayed(const Duration(seconds: 5), () {}); 42 | // Now cancel the subscription. 43 | subscription.cancel(); 44 | ``` 45 | -------------------------------------------------------------------------------- /documentation/sdk_examples/sep-0030.md: -------------------------------------------------------------------------------- 1 | 2 | # SEP-0030 - Account Recovery: multi-party recovery of Stellar accounts 3 | 4 | Enables an individual (e.g., a user or wallet) to regain access to a Stellar account as defined by 5 | [SEP-0030: Account Recovery](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0030.md). 6 | 7 | 8 | ## Create a SEP30RecoveryService instance 9 | 10 | **By providing the recovery server url directly via the constructor:** 11 | 12 | ```dart 13 | final service = SEP30RecoveryService("http://api.stellar-test.org/recovery"); 14 | ``` 15 | 16 | ## Register an account 17 | 18 | ```dart 19 | var request = SEP30Request([senderIdentity, receiverIdentity]); 20 | SEP30AccountResponse response = await service.registerAccount(addressA, request, jwtToken); 21 | ``` 22 | 23 | ## Update identities for an account 24 | 25 | ```dart 26 | var request = SEP30Request([sender2Identity, receiver2Identity]); 27 | SEP30AccountResponse response = await service.updateIdentitiesForAccount(addressA, request, jwtToken); 28 | ``` 29 | 30 | ## Sign a transaction 31 | 32 | ```dart 33 | var transaction = "AAAAAHAHhQtYBh5F2zA6..."; 34 | SEP30SignatureResponse response = await service.signTransaction( 35 | addressA, signingAddress, transaction, jwtToken); 36 | ``` 37 | 38 | ## Get account details 39 | 40 | ```dart 41 | SEP30AccountResponse response = await service.accountDetails(addressA, jwtToken); 42 | ``` 43 | 44 | ## Delete account 45 | 46 | ```dart 47 | SEP30AccountResponse response = await service.deleteAccount(addressA, jwtToken); 48 | ``` 49 | 50 | 51 | ## List accounts 52 | 53 | ```dart 54 | SEP30AccountsResponse response = await service.accounts(jwtToken, 55 | after: "GA5TKKASNJZGZAP6FH65HO77CST7CJNYRTW4YPBNPXYMZAHHMTHDZKDQ"); 56 | ``` 57 | 58 | ### Further readings 59 | 60 | SDK's [SEP-30 test cases](https://github.com/Soneso/stellar_flutter_sdk/blob/master/test/sep0030_test.dart). 61 | 62 | -------------------------------------------------------------------------------- /documentation/installation.md: -------------------------------------------------------------------------------- 1 | ## [Stellar SDK for Flutter](https://github.com/Soneso/stellar_flutter_sdk) Installation Guide 2 | 3 | ### From pub.dev 4 | 1. Add the dependency to your pubspec.yaml file: 5 | ``` 6 | dependencies: 7 | stellar_flutter_sdk: ^0.8.0 8 | ``` 9 | 2. Install it (command line or IDE): 10 | ``` 11 | flutter pub get 12 | ``` 13 | 3. In your source file import the SDK, initialize and use it: 14 | ```dart 15 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 16 | 17 | final StellarSDK sdk = StellarSDK.TESTNET; 18 | 19 | String accountId = "GASYKQXV47TPTB6HKXWZNB6IRVPMTQ6M6B27IM5L2LYMNYBX2O53YJAL"; 20 | AccountResponse account = await sdk.accounts.account(accountId); 21 | print("sequence number: ${account.sequenceNumber}"); 22 | ``` 23 | 24 | ### Manual 25 | 26 | Add the SDK is a Flutter Dart plugin. Here is a step by step that we recommend: 27 | 28 | 1. Clone this repo. 29 | 2. Open the project in your IDE (e.g. Android Studio). 30 | 3. Open the file `pubspec.yaml` and press `Pub get` in your IDE. 31 | 4. Go to the project's `test` directory, run a test from there and you are good to go! 32 | 33 | Add it to your app: 34 | 35 | 5. In your Flutter app add the local dependency in `pubspec.yaml` and then run `pub get`: 36 | ```code 37 | dependencies: 38 | flutter: 39 | sdk: flutter 40 | stellar_flutter_sdk: 41 | path: ../stellar_flutter_sdk 42 | ``` 43 | 6. In your source file import the SDK, initialize and use it: 44 | ```dart 45 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 46 | 47 | final StellarSDK sdk = StellarSDK.TESTNET; 48 | 49 | String accountId = "GASYKQXV47TPTB6HKXWZNB6IRVPMTQ6M6B27IM5L2LYMNYBX2O53YJAL"; 50 | AccountResponse account = await sdk.accounts.account(accountId); 51 | print("sequence number: ${account.sequenceNumber}"); 52 | ``` 53 | To continue learning about the sdk, please have a look to our [Quick start guide](quick_start.md) 54 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | *.class 3 | *.log 4 | *.pyc 5 | *.swp 6 | .DS_Store 7 | .atom/ 8 | .buildlog/ 9 | .history 10 | .svn/ 11 | __pycache__/ 12 | 13 | # IntelliJ related 14 | *.iml 15 | *.ipr 16 | *.iws 17 | .idea/ 18 | 19 | # The .vscode folder contains launch configuration and tasks you configure in 20 | # VS Code which you may wish to be included in version control, so this line 21 | # is commented out by default. 22 | #.vscode/ 23 | 24 | # Flutter/Dart/Pub related 25 | **/doc/api/ 26 | _site/ 27 | .dart_tool/ 28 | .flutter-plugins 29 | .flutter-plugins-dependencies 30 | .packages 31 | .pub-cache/ 32 | .pub/ 33 | build/ 34 | pubspec.lock 35 | package_config.json 36 | 37 | # Android related 38 | **/android/**/gradle-wrapper.jar 39 | **/android/.gradle 40 | **/android/captures/ 41 | **/android/gradlew 42 | **/android/gradlew.bat 43 | **/android/local.properties 44 | **/android/**/GeneratedPluginRegistrant.java 45 | 46 | # iOS/XCode related 47 | **/ios/**/*.mode1v3 48 | **/ios/**/*.mode2v3 49 | **/ios/**/*.moved-aside 50 | **/ios/**/*.pbxuser 51 | **/ios/**/*.perspectivev3 52 | **/ios/**/*sync/ 53 | **/ios/**/.sconsign.dblite 54 | **/ios/**/.tags* 55 | **/ios/**/.vagrant/ 56 | **/ios/**/DerivedData/ 57 | **/ios/**/Icon? 58 | **/ios/**/Pods/ 59 | **/ios/**/.symlinks/ 60 | **/ios/**/profile 61 | **/ios/**/xcuserdata 62 | **/ios/.generated/ 63 | **/ios/Flutter/App.framework 64 | **/ios/Flutter/Flutter.framework 65 | **/ios/Flutter/Flutter.podspec 66 | **/ios/Flutter/Generated.xcconfig 67 | **/ios/Flutter/app.flx 68 | **/ios/Flutter/app.zip 69 | **/ios/Flutter/flutter_assets/ 70 | **/ios/Flutter/flutter_export_environment.sh 71 | **/ios/ServiceDefinitions.json 72 | **/ios/Runner/GeneratedPluginRegistrant.* 73 | 74 | # Exceptions to above rules. 75 | !**/ios/**/default.mode1v3 76 | !**/ios/**/default.mode2v3 77 | !**/ios/**/default.pbxuser 78 | !**/ios/**/default.perspectivev3 79 | !/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages 80 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/03_fee_bump_trans.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/submit_transaction_response_extensions.dart'; 4 | 5 | Future feeBumpTransaction({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SAH3BXVHQY4YMJIDQWUALJVNI6J2UAIZNPMC2Z4MV6CXFKAHZ6JGVD5G", 11 | // GDPQJAQXFBRJ3N6EXACC2XXCRSDZHFHTLK3DX4XDYAUWD3HRWTYWADRS 12 | ); 13 | final destinationKeyPair = KeyPair.fromSecretSeed( 14 | "SC4ZAPNZWUDVJ5MUCUXS7CTBZUZNUOURLWCKQQEFACFQU7B3CMMOKTPW", 15 | // GAGMPYL7DN4F2GPS2QVF2PWP7J2Y77UICLLBBHNTYSLO6V3GGMQCUIRW 16 | ); 17 | final payerKeyPair = KeyPair.fromSecretSeed( 18 | "SBYZTGYUUU2XIY5AFRAQABADYC4WAIDT4XAJGVQFSA7UEA64XLD7KJAJ", 19 | // GAVPCUFA3VKW2UBSLW2GTMWUJ5CHYGAYK67CWQBFALJ3UNC2HCPBOI2D 20 | ); 21 | 22 | await FriendBot.fundTestAccount(sourceKeyPair.accountId); 23 | await FriendBot.fundTestAccount(destinationKeyPair.accountId); 24 | await FriendBot.fundTestAccount(payerKeyPair.accountId); 25 | 26 | final paymentBuilder = PaymentOperationBuilder( 27 | destinationKeyPair.accountId, 28 | Asset.NATIVE, 29 | "10", 30 | ); 31 | 32 | final sourceAccount = await sdk.accounts.account( 33 | sourceKeyPair.accountId, 34 | ); 35 | 36 | final transactionBuilder = TransactionBuilder(sourceAccount) 37 | ..addOperation(paymentBuilder.build()); 38 | 39 | final transaction = transactionBuilder.build()..sign(sourceKeyPair, network); 40 | 41 | final feeBumpTransactionBuilder = FeeBumpTransactionBuilder(transaction) 42 | ..setBaseFee(200) 43 | ..setFeeAccount(payerKeyPair.accountId); 44 | 45 | final feeBumpTransaction = feeBumpTransactionBuilder.build() 46 | ..sign(payerKeyPair, network); 47 | 48 | final result = await sdk.submitFeeBumpTransaction(feeBumpTransaction); 49 | 50 | result.printResult(); 51 | } 52 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_error.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_data_io.dart'; 6 | 7 | class XdrErrorCode { 8 | final _value; 9 | const XdrErrorCode._internal(this._value); 10 | toString() => 'ErrorCode.$_value'; 11 | XdrErrorCode(this._value); 12 | get value => this._value; 13 | 14 | static const ERR_MISC = const XdrErrorCode._internal(0); 15 | static const ERR_DATA = const XdrErrorCode._internal(1); 16 | static const ERR_CONF = const XdrErrorCode._internal(2); 17 | static const ERR_AUTH = const XdrErrorCode._internal(3); 18 | static const ERR_LOAD = const XdrErrorCode._internal(4); 19 | 20 | static XdrErrorCode decode(XdrDataInputStream stream) { 21 | int value = stream.readInt(); 22 | switch (value) { 23 | case 0: 24 | return ERR_MISC; 25 | case 1: 26 | return ERR_DATA; 27 | case 2: 28 | return ERR_CONF; 29 | case 3: 30 | return ERR_AUTH; 31 | case 4: 32 | return ERR_LOAD; 33 | default: 34 | throw Exception("Unknown enum value: $value"); 35 | } 36 | } 37 | 38 | static void encode(XdrDataOutputStream stream, XdrErrorCode value) { 39 | stream.writeInt(value.value); 40 | } 41 | } 42 | 43 | class XdrError { 44 | XdrErrorCode _code; 45 | XdrErrorCode get code => this._code; 46 | set code(XdrErrorCode value) => this._code = value; 47 | 48 | String _msg; 49 | String get msg => this._msg; 50 | set msg(String value) => this._msg = value; 51 | 52 | XdrError(this._code, this._msg); 53 | 54 | static void encode(XdrDataOutputStream stream, XdrError encodedError) { 55 | XdrErrorCode.encode(stream, encodedError.code); 56 | stream.writeString(encodedError.msg); 57 | } 58 | 59 | static XdrError decode(XdrDataInputStream stream) { 60 | return XdrError(XdrErrorCode.decode(stream), stream.readString()); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_1/05_create_and_send_custom_asset.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/extensions.dart'; 4 | 5 | Future createAndSendCustomAsset({ 6 | required StellarSDK sdk, 7 | required Network network, 8 | }) async { 9 | final sourceKeyPair = KeyPair.fromSecretSeed( 10 | "SDLZPXUOODLPPD2XWUM7R6P6RZBZPOYZCFX6NODQMWLRV5OK3BC4PPHH", 11 | ); 12 | 13 | final issuingKeyPair = KeyPair.fromSecretSeed( 14 | "SAW74SJ4ERDAKW4GSL63ASQAN7EVFCI4A44JMRKPPGAP6ROGPBL6SN3J", 15 | ); 16 | 17 | final sourceAccount = await sdk.accounts.account( 18 | sourceKeyPair.accountId, 19 | ); 20 | print("Source account balance:"); 21 | sourceAccount.printBalances(); 22 | print(''); 23 | 24 | var issuingAccount = await sdk.accounts.account( 25 | issuingKeyPair.accountId, 26 | ); 27 | print("Issuing account balance:"); 28 | issuingAccount.printBalances(); 29 | print(''); 30 | 31 | // Add asset and set the issuer account 32 | final asset = Asset.createNonNativeAsset( 33 | "JOPM", 34 | issuingAccount.accountId, 35 | ); 36 | 37 | // Creat a trustline from the receiving account (source) to the issuing account 38 | final trustlineBuilder = ChangeTrustOperationBuilder( 39 | asset, 40 | '922337203685.4775807', 41 | ); 42 | 43 | // Execute a payment from the issuing account to the receiving account (source) 44 | final fundingBuilder = PaymentOperationBuilder( 45 | sourceAccount.accountId, 46 | asset, 47 | "10", 48 | )..setSourceAccount(issuingKeyPair.accountId); 49 | 50 | final transactionBuilder = TransactionBuilder(sourceAccount) 51 | ..addOperation(trustlineBuilder.build()) 52 | ..addOperation(fundingBuilder.build()); 53 | 54 | final transaction = transactionBuilder.build() 55 | ..sign(sourceKeyPair, network) 56 | ..sign(issuingKeyPair, network); 57 | 58 | final result = await sdk.submitTransaction( 59 | transaction, 60 | ); 61 | 62 | result.printResult(); 63 | } 64 | -------------------------------------------------------------------------------- /example/android/app/build.gradle: -------------------------------------------------------------------------------- 1 | def localProperties = new Properties() 2 | def localPropertiesFile = rootProject.file('local.properties') 3 | if (localPropertiesFile.exists()) { 4 | localPropertiesFile.withReader('UTF-8') { reader -> 5 | localProperties.load(reader) 6 | } 7 | } 8 | 9 | def flutterRoot = localProperties.getProperty('flutter.sdk') 10 | if (flutterRoot == null) { 11 | throw new FileNotFoundException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") 12 | } 13 | 14 | def flutterVersionCode = localProperties.getProperty('flutter.versionCode') 15 | if (flutterVersionCode == null) { 16 | flutterVersionCode = '1' 17 | } 18 | 19 | def flutterVersionName = localProperties.getProperty('flutter.versionName') 20 | if (flutterVersionName == null) { 21 | flutterVersionName = '1.0' 22 | } 23 | 24 | apply plugin: 'com.android.application' 25 | apply plugin: 'kotlin-android' 26 | apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle" 27 | 28 | android { 29 | compileSdkVersion 31 30 | 31 | sourceSets { 32 | main.java.srcDirs += 'src/main/kotlin' 33 | } 34 | 35 | lintOptions { 36 | disable 'InvalidPackage' 37 | } 38 | 39 | defaultConfig { 40 | // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). 41 | applicationId "com.example.example" 42 | minSdkVersion 16 43 | targetSdkVersion 31 44 | versionCode flutterVersionCode.toInteger() 45 | versionName flutterVersionName 46 | } 47 | 48 | buildTypes { 49 | release { 50 | // TODO: Add your own signing config for the release build. 51 | // Signing with the debug keys for now, so `flutter run --release` works. 52 | signingConfig signingConfigs.debug 53 | } 54 | } 55 | } 56 | 57 | flutter { 58 | source '../..' 59 | } 60 | 61 | dependencies { 62 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 63 | } 64 | -------------------------------------------------------------------------------- /documentation/sdk_examples/create_account.md: -------------------------------------------------------------------------------- 1 | 2 | ### Create Account 3 | 4 | In this example we will let Friendbot fund a testnet account. In the main net however we need another already existing account to be able to create a new one. 5 | 6 | ### Friendbot (testnet only) 7 | 8 | ```dart 9 | StellarSDK sdk = StellarSDK.TESTNET; 10 | 11 | // Create a random key pair for our new account. 12 | KeyPair keyPair = KeyPair.random(); 13 | 14 | // Ask the Friendbot to create our new account in the stellar network (only available in testnet). 15 | bool funded = await FriendBot.fundTestAccount(keyPair.accountId); 16 | 17 | // Load the data of the new account from stellar. 18 | AccountResponse account = await sdk.accounts.account(keyPair.accountId); 19 | ``` 20 | 21 | ### Create Account Operation 22 | 23 | ```dart 24 | StellarSDK sdk = StellarSDK.TESTNET; 25 | 26 | // Build a key pair from the seed of an existing account. We will need it for signing. 27 | KeyPair existingAccountKeyPair = KeyPair.fromSecretSeed("SAPS66IJDXUSFDSDKIHR4LN6YPXIGCM5FBZ7GE66FDKFJRYJGFW7ZHYF"); 28 | 29 | // Existing account id. 30 | String existingAccountId = existingAccountKeyPair.accountId; 31 | 32 | // Create a random keypair for a new account to be created. 33 | KeyPair newAccountKeyPair = KeyPair.random(); 34 | 35 | // Load the data of the existing account so that we receive it's current sequence number. 36 | AccountResponse existingAccount = await sdk.accounts.account(existingAccountId); 37 | 38 | // Build a transaction containing a create account operation to create the new account. 39 | // Starting balance: 10 XLM. 40 | Transaction transaction = new TransactionBuilder(existingAccount) 41 | .addOperation(new CreateAccountOperationBuilder(newAccountKeyPair.accountId, "10").build()) 42 | .build(); 43 | 44 | // Sign the transaction with the key pair of the existing account. 45 | transaction.sign(existingAccountKeyPair, Network.TESTNET); 46 | 47 | // Submit the transaction to stellar. 48 | await sdk.submitTransaction(transaction); 49 | 50 | // Load the data of the new created account. 51 | AccountResponse newAccount = await sdk.accounts.account(newAccountKeyPair.accountId); 52 | 53 | ``` -------------------------------------------------------------------------------- /documentation/sdk_examples/merge_account.md: -------------------------------------------------------------------------------- 1 | 2 | ### Merge account 3 | 4 | In this example we will merge an account Y into another account X. After merging, account Y will not exist any more and account X will posses the funds of accountY. 5 | 6 | First we create two random accounts (X and Y) by asking Freindbot. Then we merge Y into X and check the result. 7 | 8 | ```dart 9 | // Create random key pairs for two accounts. 10 | KeyPair keyPairX = KeyPair.random(); 11 | KeyPair keyPairY = KeyPair.random(); 12 | 13 | // Account Ids. 14 | String accountXId = keyPairX.accountId; 15 | String accountYId = keyPairY.accountId; 16 | 17 | // Create both accounts. 18 | await FriendBot.fundTestAccount(accountXId); 19 | await FriendBot.fundTestAccount(accountYId); 20 | 21 | // Prepare the operation for merging account Y into account X. 22 | AccountMergeOperationBuilder accMergeOp = 23 | AccountMergeOperationBuilder(accountXId); 24 | 25 | // Load the data of account Y so that we have it's current sequence number. 26 | AccountResponse accountY = await sdk.accounts.account(accountYId); 27 | 28 | // Build the transaction to merge account Y into account X. 29 | Transaction transaction = TransactionBuilder(accountY) 30 | .addOperation(accMergeOp.build()) 31 | .build(); 32 | 33 | // Account Y signs the transaction - R.I.P :) 34 | transaction.sign(keyPairY, Network.TESTNET); 35 | 36 | // Submit the transaction. 37 | SubmitTransactionResponse response = await sdk.submitTransaction(transaction); 38 | 39 | if (response.success) { 40 | print("successfully merged"); 41 | } 42 | 43 | // Check that account Y has been removed. 44 | await sdk.accounts.account(accountYId).then((response) { 45 | print("account still exists: ${accountYId}"); 46 | }).catchError((error) { 47 | print(error.toString()); 48 | if(error is ErrorResponse && error.code == 404) { 49 | print("success, account not found"); 50 | } 51 | }); 52 | 53 | // Check if accountX received the funds from accountY. 54 | AccountResponse accountX = await sdk.accounts.account(accountXId); 55 | for (Balance balance in accountX.balances) { 56 | if (balance.assetType == Asset.TYPE_NATIVE) { 57 | print("X has ${double.parse(balance.balance)} XLM"); 58 | break; 59 | } 60 | } 61 | ``` 62 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.yml: -------------------------------------------------------------------------------- 1 | name: "Bug Report" 2 | description: Report a bug or unexpected behavior in the Flutter Stellar SDK 3 | labels: ["bug"] 4 | body: 5 | - type: markdown 6 | attributes: 7 | value: | 8 | ⚠️ Thanks for helping us improve the SDK! 9 | Please provide as much detail as possible so we can reproduce and fix the issue. 10 | 11 | - type: input 12 | id: summary 13 | attributes: 14 | label: "Bug Summary" 15 | description: "Briefly describe the issue." 16 | placeholder: "Example: Transaction fails when submitting XDR" 17 | 18 | - type: textarea 19 | id: steps 20 | attributes: 21 | label: "Steps to Reproduce" 22 | description: "List the steps needed to reproduce the problem." 23 | placeholder: | 24 | 1. Run `...` 25 | 2. Call `...` 26 | 3. See error message 27 | validations: 28 | required: true 29 | 30 | - type: textarea 31 | id: expected 32 | attributes: 33 | label: "Expected Behavior" 34 | description: "What did you expect to happen?" 35 | placeholder: "Example: The transaction should be accepted by Horizon." 36 | 37 | - type: textarea 38 | id: actual 39 | attributes: 40 | label: "Actual Behavior" 41 | description: "What actually happened?" 42 | placeholder: "Example: Horizon returns 400 Bad Request." 43 | 44 | - type: textarea 45 | id: logs 46 | attributes: 47 | label: "Error Messages / Logs" 48 | description: "Paste any relevant error messages or logs." 49 | render: shell 50 | 51 | - type: input 52 | id: version 53 | attributes: 54 | label: "SDK Version" 55 | description: "Which version of the SDK are you using?" 56 | placeholder: "Example: 2.1.3" 57 | 58 | - type: input 59 | id: flutter 60 | attributes: 61 | label: "Flutter/Dart Version" 62 | description: "Which version of Flutter and Dart are you using?" 63 | placeholder: "Example: Flutter 3.24.0 • Dart 3.5.0" 64 | 65 | - type: input 66 | id: platform 67 | attributes: 68 | label: "Platform" 69 | description: "Which platform(s) are affected?" 70 | placeholder: "Example: Android 14 emulator, iOS 17 device, Web" 71 | 72 | -------------------------------------------------------------------------------- /lib/src/asset_type_native.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr/xdr_asset.dart'; 6 | import 'assets.dart'; 7 | 8 | /// Represents the native Stellar asset (XLM/lumens). 9 | /// 10 | /// The native asset is the built-in cryptocurrency of the Stellar network. 11 | /// Unlike other assets, it doesn't require a trustline and is used to pay 12 | /// transaction fees and minimum account balances. 13 | /// 14 | /// See [Stellar developer docs](https://developers.stellar.org) 15 | /// for more information. 16 | class AssetTypeNative extends Asset { 17 | /// Creates an instance of the native Stellar asset (XLM). 18 | /// 19 | /// The native asset requires no parameters as there is only one native 20 | /// asset on the Stellar network (lumens/XLM). It doesn't require a trustline 21 | /// and is automatically available to all accounts. 22 | /// 23 | /// Example: 24 | /// ```dart 25 | /// Asset xlm = AssetTypeNative(); 26 | /// ``` 27 | AssetTypeNative(); 28 | 29 | @override 30 | String get type => Asset.TYPE_NATIVE; 31 | 32 | /// Compares this instance to another for equality. 33 | /// 34 | /// Returns `true` if [object] is of the same type and all fields are equal, `false` otherwise. 35 | @override 36 | bool operator ==(Object object) { 37 | return object is AssetTypeNative; 38 | } 39 | 40 | /// Returns the hash code for this instance based on its fields. 41 | @override 42 | int get hashCode { 43 | return 0; 44 | } 45 | 46 | /// Converts this asset to its XDR Asset representation. 47 | /// 48 | /// Returns: XDR Asset for the native asset (XLM). 49 | @override 50 | XdrAsset toXdr() { 51 | return XdrAsset(XdrAssetType.ASSET_TYPE_NATIVE); 52 | } 53 | 54 | /// Converts this asset to its XDR ChangeTrustAsset representation. 55 | /// 56 | /// Returns: XDR ChangeTrustAsset for the native asset (XLM). 57 | @override 58 | XdrChangeTrustAsset toXdrChangeTrustAsset() { 59 | return XdrChangeTrustAsset(XdrAssetType.ASSET_TYPE_NATIVE); 60 | } 61 | 62 | /// Converts this asset to its XDR TrustlineAsset representation. 63 | /// 64 | /// Returns: XDR TrustlineAsset for the native asset (XLM). 65 | @override 66 | XdrTrustlineAsset toXdrTrustLineAsset() { 67 | return XdrTrustlineAsset(XdrAssetType.ASSET_TYPE_NATIVE); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /lib/src/responses/health_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'response.dart'; 6 | 7 | /// Represents health response received from the horizon server. 8 | /// Health endpoint provides information about the current status of the Horizon server. 9 | /// The actual Horizon API returns: {"database_connected": true, "core_up": true, "core_synced": true} 10 | class HealthResponse extends Response { 11 | /// Indicates whether the Horizon database is connected. 12 | final bool databaseConnected; 13 | 14 | /// Indicates whether the Stellar Core instance is up and running. 15 | final bool coreUp; 16 | 17 | /// Indicates whether the Stellar Core instance is synced with the network. 18 | final bool coreSynced; 19 | 20 | /// Creates a HealthResponse from Horizon API health check data. 21 | /// 22 | /// This constructor is typically called internally when deserializing JSON responses 23 | /// from Horizon health API endpoints. 24 | /// 25 | /// Parameters: 26 | /// - [databaseConnected] Whether the Horizon database is connected 27 | /// - [coreUp] Whether the Stellar Core instance is running 28 | /// - [coreSynced] Whether the Stellar Core instance is synced with the network 29 | HealthResponse({ 30 | required this.databaseConnected, 31 | required this.coreUp, 32 | required this.coreSynced, 33 | }); 34 | 35 | /// Creates a HealthResponse from a JSON object. 36 | factory HealthResponse.fromJson(Map json) { 37 | return HealthResponse( 38 | databaseConnected: json['database_connected'] as bool, 39 | coreUp: json['core_up'] as bool, 40 | coreSynced: json['core_synced'] as bool, 41 | ); 42 | } 43 | 44 | /// Returns true if the server is healthy (all systems operational). 45 | /// The server is considered healthy when database is connected, core is up, and core is synced. 46 | bool get isHealthy => databaseConnected && coreUp && coreSynced; 47 | 48 | /// Converts this response to a JSON object. 49 | Map toJson() { 50 | return { 51 | 'database_connected': databaseConnected, 52 | 'core_up': coreUp, 53 | 'core_synced': coreSynced, 54 | }; 55 | } 56 | 57 | @override 58 | String toString() { 59 | return 'HealthResponse{databaseConnected: $databaseConnected, coreUp: $coreUp, coreSynced: $coreSynced}'; 60 | } 61 | } -------------------------------------------------------------------------------- /example/ios/Runner/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lib/src/responses/effects/misc_effects_responses.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'effect_responses.dart'; 6 | import '../response.dart'; 7 | 8 | /// Represents a sequence bumped effect response from Horizon. 9 | /// 10 | /// This effect occurs when an account manually increases its sequence number using 11 | /// the Bump Sequence operation. Bumping the sequence number is typically used to 12 | /// invalidate any pre-signed transactions with lower sequence numbers, or to prepare 13 | /// the account for future transactions with specific sequence requirements. 14 | /// 15 | /// The sequence number is a transaction-level nonce that ensures transaction uniqueness 16 | /// and ordering. Each transaction uses the account's current sequence number plus one. 17 | /// 18 | /// Triggered by: BumpSequenceOperation 19 | /// Returned by: Horizon API effects endpoint when querying for sequence bump effects 20 | /// 21 | /// Example: 22 | /// ```dart 23 | /// final effects = await sdk.effects.forAccount('account_id').execute(); 24 | /// for (var effect in effects.records) { 25 | /// if (effect is SequenceBumpedEffectResponse) { 26 | /// print('Sequence bumped to: ${effect.newSequence}'); 27 | /// } 28 | /// } 29 | /// ``` 30 | /// 31 | /// See also: 32 | /// - [BumpSequenceOperation] for bumping sequence numbers 33 | /// - [Stellar developer docs](https://developers.stellar.org) 34 | class SequenceBumpedEffectResponse extends EffectResponse { 35 | /// The new sequence number for the account after the bump 36 | int newSequence; 37 | 38 | /// Creates a [SequenceBumpedEffectResponse] with new sequence number and effect details. 39 | SequenceBumpedEffectResponse( 40 | this.newSequence, 41 | super.id, 42 | super.type_i, 43 | super.type, 44 | super.createdAt, 45 | super.pagingToken, 46 | super.account, 47 | super.links); 48 | 49 | factory SequenceBumpedEffectResponse.fromJson(Map json) => 50 | SequenceBumpedEffectResponse( 51 | convertInt(json['new_seq'])!, 52 | json['id'], 53 | json['type_i'], 54 | json['type'], 55 | json['created_at'], 56 | json['paging_token'], 57 | json['account'], 58 | EffectResponseLinks.fromJson(json['_links'])) 59 | ..accountMuxed = json['account_muxed'] 60 | ..accountMuxedId = json['account_muxed_id']; 61 | } 62 | -------------------------------------------------------------------------------- /lib/src/requests/health_request_builder.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2025 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'package:http/http.dart' as http; 6 | import 'dart:async'; 7 | import 'request_builder.dart'; 8 | import '../responses/response.dart'; 9 | import '../responses/health_response.dart'; 10 | 11 | /// Builds requests connected to the health endpoint of the Horizon server. 12 | /// Health endpoint provides information about the current operational status of the Horizon server. 13 | /// See: [Stellar developer docs](https://developers.stellar.org) 14 | class HealthRequestBuilder extends RequestBuilder { 15 | /// Creates a new HealthRequestBuilder instance. 16 | /// [httpClient] - The HTTP client to use for requests. 17 | /// [serverURI] - The base URI of the Horizon server. 18 | HealthRequestBuilder(http.Client httpClient, Uri serverURI) 19 | : super(httpClient, serverURI, ["health"]); 20 | 21 | /// Requests health status from the Horizon server. 22 | /// Returns a [Future] that resolves to a [HealthResponse] containing the server's health status. 23 | /// 24 | /// The response includes: 25 | /// - databaseConnected: Whether the Horizon database is connected 26 | /// - coreUp: Whether the Stellar Core instance is up and running 27 | /// - coreSynced: Whether the Stellar Core instance is synced with the network 28 | /// 29 | /// The server is considered healthy when all three values are true. 30 | /// 31 | /// Throws [UnknownResponse] if the server response could not be interpreted. 32 | /// Throws [http.ClientException] if there is a transport-level failure. 33 | /// 34 | /// Example: 35 | /// ```dart 36 | /// final sdk = StellarSDK.PUBLIC; 37 | /// final health = await sdk.health.execute(); 38 | /// if (health.isHealthy) { 39 | /// print('Server is healthy'); 40 | /// print('Database connected: ${health.databaseConnected}'); 41 | /// print('Core up: ${health.coreUp}'); 42 | /// print('Core synced: ${health.coreSynced}'); 43 | /// } 44 | /// ``` 45 | Future execute() async { 46 | TypeToken type = TypeToken(); 47 | ResponseHandler responseHandler = 48 | ResponseHandler(type); 49 | 50 | return await httpClient 51 | .get(this.buildUri(), headers: RequestBuilder.headers) 52 | .then((response) { 53 | return responseHandler.handleResponse(response); 54 | }); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /documentation/sdk_examples/fee_bump.md: -------------------------------------------------------------------------------- 1 | 2 | ### Fee bump transaction 3 | 4 | In this example we will let a payer account pay the fee for another transaction by using the fee bump transaction. 5 | 6 | ```dart 7 | // Create 3 random Keypairs, we will need them later for signing. 8 | KeyPair sourceKeyPair = KeyPair.random(); 9 | KeyPair destinationKeyPair = KeyPair.random(); 10 | KeyPair payerKeyPair = KeyPair.random(); 11 | 12 | // Account Ids. 13 | String payerId = payerKeyPair.accountId; 14 | String sourceId = sourceKeyPair.accountId; 15 | String destinationId = destinationKeyPair.accountId; 16 | 17 | // Create the source and the payer account. 18 | await FriendBot.fundTestAccount(sourceId); 19 | await FriendBot.fundTestAccount(payerId); 20 | 21 | // Load the current data of the source account so that we can create the inner transaction. 22 | AccountResponse sourceAccount = await sdk.accounts.account(sourceId); 23 | 24 | // Build the inner transaction which will create the the destination account by using the source account. 25 | Transaction innerTx = new TransactionBuilder(sourceAccount) 26 | .addOperation( 27 | new CreateAccountOperationBuilder(destinationId, "10").build()) 28 | .build(); 29 | 30 | // Sign the inner transaction with the source account key pair. 31 | innerTx.sign(sourceKeyPair, Network.TESTNET); 32 | 33 | // Build the fee bump transaction to let the payer account pay the fee for the inner transaction. 34 | // The base fee for the fee bump transaction must be higher than the fee of the inner transaction. 35 | FeeBumpTransaction feeBump = new FeeBumpTransactionBuilder(innerTx) 36 | .setBaseFee(200) 37 | .setFeeAccount(payerId) 38 | .build(); 39 | 40 | // Sign the fee bump transaction with the payer keypair 41 | feeBump.sign(payerKeyPair, Network.TESTNET); 42 | 43 | // Submit the fee bump transaction containing the inner transaction. 44 | SubmitTransactionResponse response = await sdk.submitFeeBumpTransaction(feeBump); 45 | 46 | // Let's check if the destination account has been created and received the funds. 47 | AccountResponse destination = await sdk.accounts.account(destinationId); 48 | for (Balance balance in destination.balances) { 49 | if (balance.assetType == Asset.TYPE_NATIVE) { 50 | if (double.parse(balance.balance) > 9) { 51 | print("Success :)"); 52 | } 53 | } 54 | } 55 | 56 | // You can load the transaction data with sdk.transactions 57 | TransactionResponse transaction = await sdk.transactions.transaction(response.hash); 58 | 59 | // Same for the inner transaction. 60 | transaction = await sdk.transactions.transaction(transaction.innerTransaction.hash); 61 | ``` 62 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Flutter Stellar SDK 2 | 3 | Thank you for your interest in contributing! 🚀 4 | This SDK is an open-source project maintained by [Soneso](https://github.com/Soneso). 5 | Contributions, feedback, and feature requests from the community are highly appreciated. 🙏 6 | 7 | --- 8 | 9 | ## 📣 How to Provide Feedback 10 | 11 | We’d love to hear your thoughts about the SDK: 12 | - ✅ What’s working well? 13 | - ⚡ What could be improved? 14 | - 🌟 Features you’d like to see in the future? 15 | 16 | 👉 Please share your feedback in [GitHub Discussions](https://github.com/Soneso/stellar_flutter_sdk/discussions). 17 | 18 | --- 19 | 20 | ## 🐞 Reporting Bugs 21 | 22 | If you find a bug: 23 | 1. Check [existing issues](https://github.com/Soneso/stellar_flutter_sdk/issues) to avoid duplicates. 24 | 2. Open a new [Bug Report](https://github.com/Soneso/stellar_flutter_sdk/issues/new?template=bug_report.yml). 25 | Please include: 26 | - Steps to reproduce 27 | - Expected vs. actual behavior 28 | - Error messages/logs 29 | - SDK version 30 | - Flutter/Dart version 31 | - Platform (Android, iOS, Web, etc.) 32 | - Device/emulator details 33 | 34 | The more details, the faster we can fix it! 35 | 36 | --- 37 | 38 | ## 🌟 Requesting Features 39 | 40 | Have an idea for an improvement or a new feature? 41 | 1. First, check [existing feature requests](https://github.com/Soneso/stellar_flutter_sdk/issues?q=label%3Aenhancement). 42 | 2. Open a new [Feature Request](https://github.com/Soneso/stellar_flutter_sdk/issues/new?template=feature_request.yml). 43 | Tell us: 44 | - What problem the feature solves 45 | - Why it would be useful 46 | - Any proposed solutions or alternatives 47 | 48 | --- 49 | 50 | ## 🤝 Contributing Code 51 | 52 | 1. Fork the repository. 53 | 2. Create a feature branch (`git checkout -b feature/my-new-feature`). 54 | 3. Commit your changes (`git commit -m "Add my new feature"`). 55 | 4. Push to your fork (`git push origin feature/my-new-feature`). 56 | 5. Open a Pull Request. 57 | 58 | Please ensure your code: 59 | - Follows Flutter/Dart best practices. 60 | - Includes tests for new functionality. 61 | - Updates documentation/examples if relevant. 62 | - Runs successfully with `flutter test`. 63 | 64 | --- 65 | 66 | ## 💬 Questions? 67 | 68 | If you’re not sure whether something should be a bug report, feature request, or discussion, 69 | just start with [GitHub Discussions](https://github.com/Soneso/stellar_flutter_sdk/discussions). 70 | We’ll help point you in the right direction. 71 | 72 | --- 73 | 74 | Thanks again for contributing to the Stellar ecosystem! 🌌 75 | -------------------------------------------------------------------------------- /documentation/sdk_examples/sep-0001-toml.md: -------------------------------------------------------------------------------- 1 | 2 | ### SEP-0001 - stellar.toml 3 | 4 | This examples shows how to obtain the parsed data from a ```stellar.toml``` file. For more details see: [SEP-0001](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0001.md). 5 | 6 | The data can be parsed from a string or loaded and parsed from a given domain. 7 | 8 | #### From string 9 | 10 | To parse the data from a string you can use the default constructor of the ```StellarToml``` class. 11 | ```dart 12 | String toml = ''' 13 | # Sample stellar.toml 14 | VERSION="2.0.0" 15 | # ... 16 | '''; 17 | 18 | StellarToml stellarToml = StellarToml(toml); 19 | GeneralInformation generalInformation = stellarToml.generalInformation; 20 | print(generalInformation.version); 21 | 22 | ``` 23 | After parsing, the ```StellarToml``` class provides information for (if available): ```generalInformation```, ```documentation```, ```pointsOfContact```, ```currencies``` and ```validators```. See the sdk api docs for more details. 24 | 25 | #### From domain 26 | 27 | To load and parse the data from a domain you can use the fromDomain constructor of the StellarToml class. It automatically composes the needed url. In the following example the data is loaded from: https://soneso.com/.well-known/stellar.toml - only the domain "soneso.com" has to be provided: 28 | ```dart 29 | StellarToml stellarToml = await StellarToml.fromDomain("soneso.com"); 30 | GeneralInformation generalInformation = stellarToml.generalInformation; 31 | //... 32 | ``` 33 | After parsing, the ```StellarToml``` class provides information for (if available): ```generalInformation```, ```documentation```, ```pointsOfContact```, ```currencies``` and ```validators```. See the sdk api docs for more details. 34 | 35 | #### Linked currency 36 | Alternately to specifying a specific currency in it's content, ```stellar.toml``` can link out to a separate TOML file for a given currency by specifying ```toml="https://DOMAIN/.well-known/CURRENCY.toml"``` as the currency's only field. 37 | 38 | ```# Sample stellar.toml 39 | VERSION="2.0.0" 40 | #... 41 | [[CURRENCIES]] 42 | toml="https://soneso.com/.well-known/TESTC.toml" 43 | #... 44 | ``` 45 | To load the data of this currency, you can use the static method: ```StellarToml.currencyFromUrl(String toml)``` - as shown in the example below: 46 | 47 | ```dart 48 | StellarToml stellarToml = await StellarToml.fromDomain("soneso.com"); 49 | List currencies = stellarToml.currencies; 50 | for (Currency currency in currencies) { 51 | if (currency.toml != null) { 52 | Currency linkedCurrency = await StellarToml.currencyFromUrl(currency.toml); 53 | print(linkedCurrency.code); 54 | } 55 | } 56 | ``` 57 | -------------------------------------------------------------------------------- /lib/src/eventsource/event.dart: -------------------------------------------------------------------------------- 1 | /// Represents a Server-Sent Event received from an EventSource stream. 2 | /// 3 | /// Server-Sent Events (SSE) provide a standard way to push real-time 4 | /// updates from a server to a client over HTTP. Each event can contain 5 | /// an ID, event type, and data payload. 6 | /// 7 | /// Properties: 8 | /// - [id]: Unique identifier for event replay (Last-Event-ID) 9 | /// - [event]: Event type name (defaults to "message") 10 | /// - [data]: Event payload data as a string 11 | /// 12 | /// Common event types in Stellar: 13 | /// - "open": Connection established 14 | /// - "message": Data update received 15 | /// - "error": Error occurred 16 | /// 17 | /// Example: 18 | /// ```dart 19 | /// // Listen for events from Horizon 20 | /// eventSource.listen((Event event) { 21 | /// if (event.event == "message") { 22 | /// // Parse the event data 23 | /// var json = jsonDecode(event.data!); 24 | /// print("Received: $json"); 25 | /// } 26 | /// }); 27 | /// ``` 28 | /// 29 | /// See also: 30 | /// - [EventSource] for creating SSE connections 31 | /// - [EventSourceDecoder] for parsing SSE streams 32 | class Event implements Comparable { 33 | /// Event identifier for replay functionality. 34 | /// 35 | /// An identifier that can be used to allow a client to replay 36 | /// missed events by returning the Last-Event-Id header. 37 | /// Set to null or empty string if not required. 38 | String? id; 39 | 40 | /// The event type name. 41 | /// 42 | /// Identifies the type of event being sent. Common values include 43 | /// "message" for data updates, "open" for connection establishment, 44 | /// and "error" for error conditions. Set to null or empty string 45 | /// if not required. 46 | String? event; 47 | 48 | /// The event payload data. 49 | /// 50 | /// Contains the actual data payload of the event, typically as 51 | /// JSON or plain text. Set to null or empty string if no data 52 | /// is included. 53 | String? data; 54 | 55 | /// Creates a new Event with optional id, event type, and data. 56 | Event({this.id, this.event, this.data}); 57 | 58 | /// Creates a new message event with optional id and data. 59 | /// 60 | /// Convenience constructor for the most common event type. 61 | /// 62 | /// Example: 63 | /// ```dart 64 | /// Event event = Event.message(id: "123", data: '{"type":"payment"}'); 65 | /// ``` 66 | Event.message({this.id, this.data}) : event = "message"; 67 | 68 | /// Compares events by their ID for ordering. 69 | /// 70 | /// Allows events to be sorted or compared based on their 71 | /// identifier values. 72 | @override 73 | int compareTo(Event other) => id!.compareTo(other.id!); 74 | } 75 | -------------------------------------------------------------------------------- /documentation/sdk_examples/manage_data.md: -------------------------------------------------------------------------------- 1 | 2 | ### Create a trustline 3 | 4 | In this example we will set a data entry (key value pair) into an account within the stellar network. 5 | To do so, we will create a new account and add the data entry by submitting a transaction that contains the prepared manage data operation. 6 | After that, we will reload the account from stellar, read and compare the data entry. 7 | In the last step we will delete the entry. 8 | 9 | ```dart 10 | // Create a random keypair for our new account. 11 | KeyPair keyPair = KeyPair.random(); 12 | 13 | // Account Id. 14 | String accountId = keyPair.accountId; 15 | 16 | // Create account. 17 | await FriendBot.fundTestAccount(accountId); 18 | 19 | // Load account data including it's current sequence number. 20 | AccountResponse account = await sdk.accounts.account(accountId); 21 | 22 | // Define a key value pair to save as a data entry. 23 | String key = "Sommer"; 24 | String value = "Die Möbel sind heiß!"; 25 | 26 | // Convert the value to bytes. 27 | List list = value.codeUnits; 28 | Uint8List valueBytes = Uint8List.fromList(list); 29 | 30 | // Prepare the manage data operation. 31 | ManageDataOperationBuilder 32 | manageDataOperationBuilder = 33 | ManageDataOperationBuilder(key, valueBytes); 34 | 35 | // Create the transaction. 36 | Transaction transaction = TransactionBuilder(account) 37 | .addOperation(manageDataOperationBuilder.build()) 38 | .build(); 39 | 40 | // Sign the transaction. 41 | transaction.sign(keyPair, Network.TESTNET); 42 | 43 | // Submit the transaction to stellar. 44 | await sdk.submitTransaction(transaction); 45 | 46 | // Reload the account. 47 | account = await sdk.accounts.account(accountId); 48 | 49 | // Get the value for our key as bytes. 50 | Uint8List resultBytes = account.data.getDecoded(key); 51 | 52 | // Convert it back to a string. 53 | String restltValue = String.fromCharCodes(resultBytes); 54 | 55 | // Compare. 56 | if(value == restltValue) { 57 | print("okay"); 58 | } else { 59 | print("failed"); 60 | } 61 | 62 | // In the next step we prepare the operation to delete the entry by passing null as a value. 63 | manageDataOperationBuilder = 64 | ManageDataOperationBuilder(key, null); 65 | 66 | // Prepare the transaction. 67 | transaction = TransactionBuilder(account) 68 | .addOperation(manageDataOperationBuilder.build()) 69 | .build(); 70 | 71 | // Sign the transaction. 72 | transaction.sign(keyPair, Network.TESTNET); 73 | 74 | // Submit. 75 | await sdk.submitTransaction(transaction); 76 | 77 | // Reload account. 78 | account = await sdk.accounts.account(accountId); 79 | 80 | // Check if the entry still exists. It should not be there any more. 81 | if(!account.data.keys.contains(key)){ 82 | print("success"); 83 | } 84 | ``` 85 | -------------------------------------------------------------------------------- /example/android/app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 8 | 12 | 20 | 24 | 28 | 33 | 37 | 38 | 39 | 40 | 41 | 42 | 44 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /example/lib/stellar_quest/series_2/02_multi_operational_trans.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | import '../../extensions/account_response_extensions.dart'; 4 | import '../../extensions/submit_transaction_response_extensions.dart'; 5 | 6 | Future multiOperationalTransaction({ 7 | required StellarSDK sdk, 8 | required Network network, 9 | }) async { 10 | final sourceKeyPair = KeyPair.fromSecretSeed( 11 | "SAH3BXVHQY4YMJIDQWUALJVNI6J2UAIZNPMC2Z4MV6CXFKAHZ6JGVD5G", 12 | // GDPQJAQXFBRJ3N6EXACC2XXCRSDZHFHTLK3DX4XDYAUWD3HRWTYWADRS 13 | ); 14 | 15 | final issuingKeyPair = KeyPair.fromSecretSeed( 16 | "SBK6NJQU5CK2IW7ALJVOE6E3FJ6TBOXDGWWVZR5B6XZCFAPFGNVGDMIJ", 17 | // GDPCNC4AVEAP7HBMIWMTD3D4EQS65EASDZTR3BYGVUBMKGDZGPAXDSNI 18 | ); 19 | _printBalances( 20 | sdk: sdk, 21 | sourceKeyPair: sourceKeyPair, 22 | issuingKeyPair: issuingKeyPair, 23 | ); 24 | 25 | // Add asset and set the issuer account 26 | final asset = Asset.createNonNativeAsset( 27 | "JOPM", 28 | issuingKeyPair.accountId, 29 | ); 30 | 31 | // Creat a trustline from the receiving account (source) to the issuing account 32 | final trustlineOperationBuilder = ChangeTrustOperationBuilder( 33 | asset, 34 | "200", 35 | ); 36 | 37 | // Execute a payment from the issuing account to the receiving account (source) 38 | final fundingOperationBuilder = PaymentOperationBuilder( 39 | sourceKeyPair.accountId, 40 | asset, 41 | "10", 42 | )..setSourceAccount(issuingKeyPair.accountId); 43 | 44 | var sourceAccount = await sdk.accounts.account( 45 | sourceKeyPair.accountId, 46 | ); 47 | 48 | final transactionBuilder = TransactionBuilder(sourceAccount) 49 | ..addOperation(trustlineOperationBuilder.build()) 50 | ..addOperation(fundingOperationBuilder.build()); 51 | 52 | final transaction = transactionBuilder.build() 53 | ..sign(sourceKeyPair, network) 54 | ..sign(issuingKeyPair, network); 55 | 56 | final result = await sdk.submitTransaction(transaction); 57 | 58 | result.printResult(); 59 | print(''); 60 | 61 | _printBalances( 62 | sdk: sdk, 63 | sourceKeyPair: sourceKeyPair, 64 | issuingKeyPair: issuingKeyPair, 65 | ); 66 | } 67 | 68 | Future _printBalances({ 69 | required StellarSDK sdk, 70 | required KeyPair sourceKeyPair, 71 | required KeyPair issuingKeyPair, 72 | }) async { 73 | var sourceAccount = await sdk.accounts.account( 74 | sourceKeyPair.accountId, 75 | ); 76 | print("Source account balance:"); 77 | sourceAccount.printBalances(); 78 | print(''); 79 | var issuingAccount = await sdk.accounts.account( 80 | issuingKeyPair.accountId, 81 | ); 82 | print("Issuing account balance:"); 83 | issuingAccount.printBalances(); 84 | print(''); 85 | } 86 | -------------------------------------------------------------------------------- /lib/src/account.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'muxed_account.dart'; 6 | 7 | /// Specifies interface for Account object used in TransactionBuilder. 8 | abstract class TransactionBuilderAccount { 9 | /// Returns ID associated with this Account. 10 | String get accountId; 11 | 12 | /// Returns current sequence number ot this Account. 13 | BigInt get sequenceNumber; 14 | 15 | /// Returns sequence number incremented by one, but does not increment internal counter. 16 | BigInt get incrementedSequenceNumber; 17 | 18 | /// Muxed account object created from this account object. 19 | MuxedAccount get muxedAccount; 20 | 21 | /// Increments sequence number in this object by one. 22 | void incrementSequenceNumber(); 23 | } 24 | 25 | /// Represents an account in Stellar network with it's sequence number. 26 | /// Account object is required to build a [Transaction]. 27 | class Account implements TransactionBuilderAccount { 28 | String _accountId; 29 | BigInt _mSequenceNumber; 30 | late MuxedAccount _muxedAccount; 31 | 32 | /// Creates a new Account with the given account ID and sequence number. 33 | /// 34 | /// Parameters: 35 | /// - [_accountId] The account's public key (G... address) 36 | /// - [_mSequenceNumber] The current sequence number 37 | /// - [muxedAccountMed25519Id] Optional muxed account ID for multiplexing 38 | Account(this._accountId, this._mSequenceNumber, 39 | {int? muxedAccountMed25519Id}) { 40 | this._muxedAccount = MuxedAccount(this._accountId, muxedAccountMed25519Id); 41 | } 42 | 43 | /// Creates an Account from an account ID string. 44 | /// 45 | /// Supports both standard (G...) and muxed (M...) account IDs. 46 | /// 47 | /// Parameters: 48 | /// - [accountId] The account ID (G... or M... address) 49 | /// - [sequenceNumber] The current sequence number 50 | /// 51 | /// Returns: A new [Account] instance 52 | static Account fromAccountId(String accountId, BigInt sequenceNumber) { 53 | MuxedAccount mux = MuxedAccount.fromAccountId(accountId)!; 54 | return new Account(mux.ed25519AccountId, sequenceNumber, 55 | muxedAccountMed25519Id: mux.id); 56 | } 57 | 58 | @override 59 | String get accountId => _accountId; 60 | 61 | @override 62 | BigInt get sequenceNumber => _mSequenceNumber; 63 | 64 | @override 65 | MuxedAccount get muxedAccount => _muxedAccount; 66 | 67 | @override 68 | BigInt get incrementedSequenceNumber => _mSequenceNumber + BigInt.one; 69 | 70 | /// Increments sequence number in this account object by one. 71 | void incrementSequenceNumber() { 72 | _mSequenceNumber = _mSequenceNumber + BigInt.one; 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /test/contract_bindings/hello_contract_client.dart: -------------------------------------------------------------------------------- 1 | // This file was generated by stellar_contract_bindings v0.5.0b0 and stellar_sdk v13.0.0. 2 | 3 | import 'dart:typed_data'; 4 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 5 | 6 | /// Client for interacting with the HelloContract contract 7 | class HelloContract { 8 | /// The underlying SorobanClient instance 9 | final SorobanClient _client; 10 | 11 | /// Creates a new HelloContract for the given contract ID 12 | static Future forContractId({ 13 | required KeyPair sourceAccountKeyPair, 14 | required String contractId, 15 | required Network network, 16 | required String rpcUrl, 17 | bool enableServerLogging = false, 18 | }) async { 19 | final options = ClientOptions( 20 | sourceAccountKeyPair: sourceAccountKeyPair, 21 | contractId: contractId, 22 | network: network, 23 | rpcUrl: rpcUrl, 24 | enableServerLogging: enableServerLogging, 25 | ); 26 | 27 | final client = await SorobanClient.forClientOptions(options: options); 28 | return HelloContract._(client); 29 | } 30 | 31 | /// Private constructor that wraps a SorobanClient 32 | HelloContract._(this._client); 33 | 34 | /// Gets the contract ID 35 | String getContractId() => _client.getContractId(); 36 | 37 | /// Gets the client options 38 | ClientOptions getOptions() => _client.getOptions(); 39 | 40 | /// Gets the contract specification 41 | ContractSpec getContractSpec() => _client.getContractSpec(); 42 | 43 | /// Invokes the hello method 44 | Future> hello({ 45 | required String to, 46 | KeyPair? signer, 47 | int baseFee = 100, 48 | int transactionTimeout = 300, 49 | int submitTimeout = 30, 50 | bool simulate = true, 51 | bool restore = true, 52 | bool force = false, 53 | }) async { 54 | final List args = [ 55 | XdrSCVal.forSymbol(to), 56 | ]; 57 | 58 | final methodOptions = MethodOptions(); 59 | // You can customize method options here if needed 60 | 61 | final result = await _client.invokeMethod( 62 | name: 'hello', 63 | args: args, 64 | force: force, 65 | methodOptions: methodOptions, 66 | ); 67 | return result.vec!.map((e) => e.sym!.toString()).toList(); 68 | } 69 | 70 | /// Builds an AssembledTransaction for the hello method. 71 | /// This is useful if you need to manipulate the transaction before signing and sending. 72 | Future buildHelloTx({ 73 | required String to, 74 | MethodOptions? methodOptions, 75 | }) async { 76 | final List args = [ 77 | XdrSCVal.forSymbol(to), 78 | ]; 79 | 80 | return await _client.buildInvokeMethodTx( 81 | name: 'hello', 82 | args: args, 83 | methodOptions: methodOptions, 84 | ); 85 | } 86 | } -------------------------------------------------------------------------------- /lib/src/responses/operations/inflation_operation_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'operation_responses.dart'; 6 | import '../transaction_response.dart'; 7 | 8 | /// Represents an inflation operation response from Horizon. 9 | /// 10 | /// The inflation operation was used to distribute fees collected by the network 11 | /// and increase the XLM supply. This operation is deprecated and disabled since 12 | /// Protocol 12 (October 2019) following a network vote. 13 | /// 14 | /// See also: 15 | /// - [Stellar developer docs](https://developers.stellar.org) 16 | class InflationOperationResponse extends OperationResponse { 17 | /// Creates an InflationOperationResponse from Horizon API operation data. 18 | /// 19 | /// This constructor is typically called internally when deserializing operation 20 | /// records from Horizon API responses. 21 | /// 22 | /// Parameters: 23 | /// - [links] Hypermedia links to related resources 24 | /// - [id] Unique operation identifier 25 | /// - [pagingToken] Pagination cursor 26 | /// - [transactionSuccessful] Whether the parent transaction succeeded 27 | /// - [sourceAccount] Operation source account ID 28 | /// - [sourceAccountMuxed] Muxed source account (if applicable) 29 | /// - [sourceAccountMuxedId] Muxed source account ID (if applicable) 30 | /// - [type] Operation type name 31 | /// - [type_i] Operation type as integer 32 | /// - [createdAt] Creation timestamp 33 | /// - [transactionHash] Parent transaction hash 34 | /// - [transaction] Full parent transaction 35 | /// - [sponsor] Account sponsoring the operation (if applicable) 36 | InflationOperationResponse( 37 | super.links, 38 | super.id, 39 | super.pagingToken, 40 | super.transactionSuccessful, 41 | super.sourceAccount, 42 | super.sourceAccountMuxed, 43 | super.sourceAccountMuxedId, 44 | super.type, 45 | super.type_i, 46 | super.createdAt, 47 | super.transactionHash, 48 | super.transaction, 49 | super.sponsor); 50 | 51 | /// Deserializes an inflation operation response from JSON. 52 | factory InflationOperationResponse.fromJson(Map json) => 53 | InflationOperationResponse( 54 | OperationResponseLinks.fromJson(json['_links']), 55 | json['id'], 56 | json['paging_token'], 57 | json['transaction_successful'], 58 | json['source_account'], 59 | json['source_account_muxed'], 60 | json['source_account_muxed_id'], 61 | json['type'], 62 | json['type_i'], 63 | json['created_at'], 64 | json['transaction_hash'], 65 | json['transaction'] == null 66 | ? null 67 | : TransactionResponse.fromJson(json['transaction']), 68 | json['sponsor']); 69 | } 70 | -------------------------------------------------------------------------------- /documentation/sdk_examples/sep-0002-federation.md: -------------------------------------------------------------------------------- 1 | 2 | ### SEP-0002 - Federation 3 | 4 | This examples shows how to resolve a stellar address, a stellar account id, a transaction id and a forward by using the federation protocol. For more details see: [SEP-0002 Federation](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0002.md). 5 | 6 | #### Resolving a stellar address 7 | 8 | To resolve a stellar address like for example ```bob*soneso.com``` we can use the static method ```Federation.resolveStellarAddress ``` as shown below: 9 | 10 | ```dart 11 | FederationResponse response = await Federation.resolveStellarAddress("bob*soneso.com"); 12 | 13 | print(response.stellarAddress); 14 | // bob*soneso.com 15 | 16 | print(response.accountId); 17 | // GBVPKXWMAB3FIUJB6T7LF66DABKKA2ZHRHDOQZ25GBAEFZVHTBPJNOJI 18 | 19 | print(response.memoType); 20 | // text 21 | 22 | print(response.memo); 23 | // hello memo text 24 | ``` 25 | 26 | #### Resolving a stellar account id 27 | 28 | To resolve a stellar account id like for example ```GBVPKXWMAB3FIUJB6T7LF66DABKKA2ZHRHDOQZ25GBAEFZVHTBPJNOJI``` we can use the static method ```Federation.resolveStellarAccountId ```. We need to provide the account id and the federation server url as parameters: 29 | 30 | ```dart 31 | FederationResponse response = await Federation.resolveStellarAccountId("GBVPKXWMAB3FIUJB6T7LF66DABKKA2ZHRHDOQZ25GBAEFZVHTBPJNOJI", "https://stellarid.io/federation/"); 32 | 33 | print(response.stellarAddress); 34 | // bob*soneso.com 35 | 36 | print(response.accountId); 37 | // GBVPKXWMAB3FIUJB6T7LF66DABKKA2ZHRHDOQZ25GBAEFZVHTBPJNOJI 38 | 39 | print(response.memoType); 40 | // text 41 | 42 | print(response.memo); 43 | // hello memo text 44 | ``` 45 | 46 | #### Resolving a stellar transaction id 47 | 48 | To resolve a stellar transaction id like for example ```c1b368c00e9852351361e07cc58c54277e7a6366580044ab152b8db9cd8ec52a``` we can use the static method ```Federation.resolveStellarTransactionId ```. We need to provide the transaction id and the federation server url as parameters: 49 | 50 | ```dart 51 | // Returns the federation record of the sender of the transaction if known by the server 52 | FederationResponse response = await Federation.resolveStellarTransactionId("c1b368c00e9852351361e07cc58c54277e7a6366580044ab152b8db9cd8ec52a", "https://stellarid.io/federation/"); 53 | ``` 54 | 55 | #### Resolving a forward 56 | 57 | Used for forwarding the payment on to a different network or different financial institution. Here we can use the static method ```Federation.resolveForward``` . We need to provide the needed query parameters as ```Map``` and the federation server url: 58 | 59 | ```dart 60 | FederationResponse response = await Federation.resolveForward({ 61 | "forward_type": "bank_account", 62 | "swift": "BOPBPHMM", 63 | "acct": "2382376" 64 | }, "https://stellarid.io/federation/"); 65 | 66 | // resulting request url: 67 | // https://stellarid.io/federation/?type=forward&forward_type=bank_account&swift=BOPBPHMM&acct=2382376 68 | ``` 69 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_data_entry.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_type.dart'; 6 | import 'xdr_data_io.dart'; 7 | import 'xdr_account.dart'; 8 | import "dart:typed_data"; 9 | 10 | class XdrDataEntry { 11 | XdrAccountID _accountID; 12 | XdrAccountID get accountID => this._accountID; 13 | set accountID(XdrAccountID value) => this._accountID = value; 14 | 15 | XdrString64 _dataName; 16 | XdrString64 get dataName => this._dataName; 17 | set dataName(XdrString64 value) => this._dataName = value; 18 | 19 | XdrDataValue _dataValue; 20 | XdrDataValue get dataValue => this._dataValue; 21 | set dataValue(XdrDataValue value) => this._dataValue = value; 22 | 23 | XdrDataEntryExt _ext; 24 | XdrDataEntryExt get ext => this._ext; 25 | set ext(XdrDataEntryExt value) => this._ext = value; 26 | 27 | XdrDataEntry(this._accountID, this._dataName, this._dataValue, this._ext); 28 | 29 | static void encode( 30 | XdrDataOutputStream stream, XdrDataEntry encodedDataEntry) { 31 | XdrAccountID.encode(stream, encodedDataEntry.accountID); 32 | XdrString64.encode(stream, encodedDataEntry.dataName); 33 | XdrDataValue.encode(stream, encodedDataEntry.dataValue); 34 | XdrDataEntryExt.encode(stream, encodedDataEntry.ext); 35 | } 36 | 37 | static XdrDataEntry decode(XdrDataInputStream stream) { 38 | return XdrDataEntry(XdrAccountID.decode(stream), XdrString64.decode(stream), 39 | XdrDataValue.decode(stream), XdrDataEntryExt.decode(stream)); 40 | } 41 | } 42 | 43 | class XdrDataEntryExt { 44 | 45 | int _v; 46 | int get discriminant => this._v; 47 | set discriminant(int value) => this._v = value; 48 | 49 | XdrDataEntryExt(this._v); 50 | 51 | static void encode( 52 | XdrDataOutputStream stream, XdrDataEntryExt encodedDataEntryExt) { 53 | stream.writeInt(encodedDataEntryExt.discriminant); 54 | switch (encodedDataEntryExt.discriminant) { 55 | case 0: 56 | break; 57 | } 58 | } 59 | 60 | static XdrDataEntryExt decode(XdrDataInputStream stream) { 61 | XdrDataEntryExt decodedDataEntryExt = XdrDataEntryExt(stream.readInt()); 62 | switch (decodedDataEntryExt.discriminant) { 63 | case 0: 64 | break; 65 | } 66 | return decodedDataEntryExt; 67 | } 68 | } 69 | 70 | class XdrDataValue { 71 | 72 | Uint8List _dataValue; 73 | Uint8List get dataValue => this._dataValue; 74 | set dataValue(Uint8List value) => this._dataValue = value; 75 | 76 | XdrDataValue(this._dataValue); 77 | 78 | static encode(XdrDataOutputStream stream, XdrDataValue encodedDataValue) { 79 | int dataValuesize = encodedDataValue.dataValue.length; 80 | stream.writeInt(dataValuesize); 81 | stream.write(encodedDataValue.dataValue); 82 | } 83 | 84 | static XdrDataValue decode(XdrDataInputStream stream) { 85 | int dataValuesize = stream.readInt(); 86 | return XdrDataValue(stream.readBytes(dataValuesize)); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_bucket.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_ledger.dart'; 6 | import 'xdr_data_io.dart'; 7 | 8 | //TODO: add BucketMetadata 9 | 10 | class XdrBucketEntryType { 11 | final _value; 12 | const XdrBucketEntryType._internal(this._value); 13 | toString() => 'BucketEntryType.$_value'; 14 | XdrBucketEntryType(this._value); 15 | get value => this._value; 16 | 17 | /// Bucket metadata, should come first. 18 | static const METAENTRY = const XdrBucketEntryType._internal(-1); 19 | 20 | /// Only updated. 21 | static const LIVEENTRY = const XdrBucketEntryType._internal(0); 22 | 23 | /// Deadentry. 24 | static const DEADENTRY = const XdrBucketEntryType._internal(1); 25 | 26 | /// Only created. 27 | static const INITENTRY = const XdrBucketEntryType._internal(2); 28 | 29 | static XdrBucketEntryType decode(XdrDataInputStream stream) { 30 | int value = stream.readInt(); 31 | switch (value) { 32 | case -1: 33 | return METAENTRY; 34 | case 0: 35 | return LIVEENTRY; 36 | case 1: 37 | return DEADENTRY; 38 | case 2: 39 | return INITENTRY; 40 | default: 41 | throw Exception("Unknown enum value: $value"); 42 | } 43 | } 44 | 45 | static void encode(XdrDataOutputStream stream, XdrBucketEntryType value) { 46 | stream.writeInt(value.value); 47 | } 48 | } 49 | 50 | class XdrBucketEntry { 51 | XdrBucketEntryType _type; 52 | XdrBucketEntryType get discriminant => this._type; 53 | set discriminant(XdrBucketEntryType value) => this._type = value; 54 | 55 | XdrLedgerEntry? _liveEntry; 56 | XdrLedgerEntry? get liveEntry => this._liveEntry; 57 | set liveEntry(XdrLedgerEntry? value) => this._liveEntry = value; 58 | 59 | XdrLedgerKey? _deadEntry; 60 | XdrLedgerKey? get deadEntry => this._deadEntry; 61 | set deadEntry(XdrLedgerKey? value) => this._deadEntry = value; 62 | 63 | XdrBucketEntry(this._type); 64 | 65 | static void encode( 66 | XdrDataOutputStream stream, XdrBucketEntry encodedBucketEntry) { 67 | stream.writeInt(encodedBucketEntry.discriminant.value); 68 | switch (encodedBucketEntry.discriminant) { 69 | case XdrBucketEntryType.LIVEENTRY: 70 | XdrLedgerEntry.encode(stream, encodedBucketEntry.liveEntry!); 71 | break; 72 | case XdrBucketEntryType.DEADENTRY: 73 | XdrLedgerKey.encode(stream, encodedBucketEntry.deadEntry!); 74 | break; 75 | } 76 | } 77 | 78 | static XdrBucketEntry decode(XdrDataInputStream stream) { 79 | XdrBucketEntry decodedBucketEntry = 80 | XdrBucketEntry(XdrBucketEntryType.decode(stream)); 81 | switch (decodedBucketEntry.discriminant) { 82 | case XdrBucketEntryType.LIVEENTRY: 83 | decodedBucketEntry.liveEntry = XdrLedgerEntry.decode(stream); 84 | break; 85 | case XdrBucketEntryType.DEADENTRY: 86 | decodedBucketEntry.deadEntry = XdrLedgerKey.decode(stream); 87 | break; 88 | } 89 | return decodedBucketEntry; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /documentation/sdk_examples/trustline.md: -------------------------------------------------------------------------------- 1 | 2 | ### Create a trustline 3 | 4 | In this example we will let one account, called trustor, trust another account that is the issuer of a custom token called "IOM". 5 | 6 | ```dart 7 | // First we create the trustor key pair from the seed of the trustor so that we can use it to sign the transaction. 8 | KeyPair trustorKeyPair = KeyPair.fromSecretSeed("SAPS66IJDXUSFDSDKIHR4LN6YPXIGCM5FBZ7GE66FDKFJRYJGFW7ZHYF"); 9 | 10 | // Account Id of the trustor account. 11 | String trustorAccountId = trustorKeyPair.accountId; 12 | 13 | // Load the trustor's account details including it's current sequence number. 14 | AccountResponse trustor = await sdk.accounts.account(trustorAccountId); 15 | 16 | // Account Id of the issuer of our custom token "IOM". 17 | String issuerAccountId = "GBGAKKFVRQJCXDLYANAMK4H2D4UHY4FARMGJXPSLGVVW3DQLYODFIKZ2"; 18 | 19 | // Define our custom token/asset "IOM" issued by the upper issuer account. 20 | Asset iomAsset = AssetTypeCreditAlphaNum4("IOM", issuerAccountId); 21 | 22 | // Prepare the change trust operation to trust the IOM asset/token defined above. 23 | // We limit the trusted/credit amount to 30.000. 24 | ChangeTrustOperationBuilder changeTrustOperation = 25 | ChangeTrustOperationBuilder(iomAsset, "300000"); 26 | 27 | // Build the transaction. 28 | Transaction transaction = new TransactionBuilder(trustor) 29 | .addOperation(changeTrustOperation.build()) 30 | .build(); 31 | 32 | // The trustor signs the transaction. 33 | transaction.sign(trustorKeyPair, Network.TESTNET); 34 | 35 | // Submit the transaction. 36 | SubmitTransactionResponse response = 37 | await sdk.submitTransaction(transaction); 38 | 39 | if (!response.success) { 40 | print("something went wrong."); 41 | } 42 | 43 | // Now we can send 1000 IOM from the issuer to the trustor. 44 | 45 | // First we create the issuer account key pair from it's seed so that we can use it to sign the transaction. 46 | KeyPair issuerKeyPair = KeyPair.fromSecretSeed("SA75FA55DXG7EN22ZYT6E42ZQBY3TUFF6MHDGG7R6ZEDMNGQ3EVSO3VZ"); 47 | 48 | // Load the issuer's account details including its current sequence number. 49 | AccountResponse issuer = await sdk.accounts.account(issuerAccountId); 50 | 51 | // Send 1000 IOM non native payment from the issuer to the trustor. 52 | transaction = new TransactionBuilder(issuer) 53 | .addOperation(PaymentOperationBuilder(trustorAccountId, iomAsset, "1000").build()) 54 | .build(); 55 | 56 | // The issuer signs the transaction. 57 | transaction.sign(issuerKeyPair, Network.TESTNET); 58 | 59 | // Submit the transaction to the stellar network. 60 | response = await sdk.submitTransaction(transaction); 61 | 62 | if (!response.success) { 63 | print("something went wrong."); 64 | } 65 | 66 | // (info) check the trustor account data to see if the trustor received the payment. 67 | trustor = await sdk.accounts.account(trustorAccountId); 68 | for (Balance balance in trustor.balances) { 69 | if (balance.assetType != Asset.TYPE_NATIVE && 70 | balance.assetCode == "IOM" && 71 | double.parse(balance.balance) > 90) { 72 | print("trustor received IOM payment"); 73 | break; 74 | } 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@1x.png", 19 | "scale" : "1x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "29x29", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-29x29@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@2x.png", 37 | "scale" : "2x" 38 | }, 39 | { 40 | "size" : "40x40", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-40x40@3x.png", 43 | "scale" : "3x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-App-60x60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@1x.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "20x20", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-20x20@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@1x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "29x29", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-29x29@2x.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@1x.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "40x40", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-40x40@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@1x.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "76x76", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-76x76@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "83.5x83.5", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-App-83.5x83.5@2x.png", 109 | "scale" : "2x" 110 | }, 111 | { 112 | "size" : "1024x1024", 113 | "idiom" : "ios-marketing", 114 | "filename" : "Icon-App-1024x1024@1x.png", 115 | "scale" : "1x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /lib/src/responses/operations/restore_footprint_operation_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'operation_responses.dart'; 6 | import '../transaction_response.dart'; 7 | 8 | /// Represents a restore footprint operation response from Horizon. 9 | /// 10 | /// This Soroban operation restores archived contract data entries, making them 11 | /// accessible again after they have expired and been archived. 12 | /// 13 | /// Returned by: Horizon API operations endpoint when querying restore footprint operations 14 | /// 15 | /// See also: 16 | /// - [RestoreFootprintOperation] for restoring archived contract data 17 | /// - [Stellar developer docs](https://developers.stellar.org) 18 | class RestoreFootprintOperationResponse extends OperationResponse { 19 | /// Creates a RestoreFootprintOperationResponse from Horizon API operation data. 20 | /// 21 | /// This constructor is typically called internally when deserializing operation 22 | /// records from Horizon API responses. 23 | /// 24 | /// Parameters: 25 | /// - [links] Hypermedia links to related resources 26 | /// - [id] Unique operation identifier 27 | /// - [pagingToken] Pagination cursor 28 | /// - [transactionSuccessful] Whether the parent transaction succeeded 29 | /// - [sourceAccount] Operation source account ID 30 | /// - [sourceAccountMuxed] Muxed source account (if applicable) 31 | /// - [sourceAccountMuxedId] Muxed source account ID (if applicable) 32 | /// - [type] Operation type name 33 | /// - [type_i] Operation type as integer 34 | /// - [createdAt] Creation timestamp 35 | /// - [transactionHash] Parent transaction hash 36 | /// - [transaction] Full parent transaction 37 | /// - [sponsor] Account sponsoring the operation (if applicable) 38 | RestoreFootprintOperationResponse( 39 | super.links, 40 | super.id, 41 | super.pagingToken, 42 | super.transactionSuccessful, 43 | super.sourceAccount, 44 | super.sourceAccountMuxed, 45 | super.sourceAccountMuxedId, 46 | super.type, 47 | super.type_i, 48 | super.createdAt, 49 | super.transactionHash, 50 | super.transaction, 51 | super.sponsor); 52 | 53 | /// Deserializes a restore footprint operation response from JSON. 54 | /// 55 | /// Converts a JSON map from the Horizon API into a RestoreFootprintOperationResponse object. 56 | factory RestoreFootprintOperationResponse.fromJson( 57 | Map json) => 58 | RestoreFootprintOperationResponse( 59 | OperationResponseLinks.fromJson(json['_links']), 60 | json['id'], 61 | json['paging_token'], 62 | json['transaction_successful'], 63 | json['source_account'], 64 | json['source_account_muxed'], 65 | json['source_account_muxed_id'], 66 | json['type'], 67 | json['type_i'], 68 | json['created_at'], 69 | json['transaction_hash'], 70 | json['transaction'] == null 71 | ? null 72 | : TransactionResponse.fromJson(json['transaction']), 73 | json['sponsor']); 74 | } 75 | -------------------------------------------------------------------------------- /example/pubspec.yaml: -------------------------------------------------------------------------------- 1 | name: example 2 | description: A new Flutter project. 3 | 4 | # The following line prevents the package from being accidentally published to 5 | # pub.dev using `pub publish`. This is preferred for private packages. 6 | publish_to: 'none' # Remove this line if you wish to publish to pub.dev 7 | 8 | # The following defines the version and build number for your application. 9 | # A version number is three numbers separated by dots, like 1.2.43 10 | # followed by an optional build number separated by a +. 11 | # Both the version and the builder number may be overridden in flutter 12 | # build by specifying --build-name and --build-number, respectively. 13 | # In Android, build-name is used as versionName while build-number used as versionCode. 14 | # Read more about Android versioning at https://developer.android.com/studio/publish/versioning 15 | # In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. 16 | # Read more about iOS versioning at 17 | # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html 18 | version: 1.0.0+1 19 | 20 | environment: 21 | sdk: ">=2.17.0 <4.0.0" 22 | 23 | dependencies: 24 | flutter: 25 | sdk: flutter 26 | # stellar_flutter_sdk: ^0.8.0 27 | # stellar_flutter_sdk: 28 | # git: 29 | # url: git://github.com/hasToDev/stellar_flutter_sdk.git 30 | # ref: a0f11e8a17ebbfa33bef94a9ac77db3711f2c7eb 31 | stellar_flutter_sdk: 32 | path: ../ 33 | sliver_tools: ^0.2.5 34 | 35 | # The following adds the Cupertino Icons font to your application. 36 | # Use with the CupertinoIcons class for iOS style icons. 37 | cupertino_icons: ^1.0.5 38 | 39 | # For information on the generic Dart part of this file, see the 40 | # following page: https://dart.dev/tools/pub/pubspec 41 | 42 | # The following section is specific to Flutter. 43 | flutter: 44 | 45 | # The following line ensures that the Material Icons font is 46 | # included with your application, so that you can use the icons in 47 | # the material Icons class. 48 | uses-material-design: true 49 | 50 | # To add assets to your application, add an assets section, like this: 51 | # assets: 52 | # - images/a_dot_burr.jpeg 53 | # - images/a_dot_ham.jpeg 54 | 55 | # An image asset can refer to one or more resolution-specific "variants", see 56 | # https://flutter.dev/assets-and-images/#resolution-aware. 57 | 58 | # For details regarding adding assets from package dependencies, see 59 | # https://flutter.dev/assets-and-images/#from-packages 60 | 61 | # To add custom fonts to your application, add a fonts section here, 62 | # in this "flutter" section. Each entry in this list should have a 63 | # "family" key with the font family name, and a "fonts" key with a 64 | # list giving the asset and other descriptors for the font. For 65 | # example: 66 | # fonts: 67 | # - family: Schyler 68 | # fonts: 69 | # - asset: fonts/Schyler-Regular.ttf 70 | # - asset: fonts/Schyler-Italic.ttf 71 | # style: italic 72 | # - family: Trajan Pro 73 | # fonts: 74 | # - asset: fonts/TrajanPro.ttf 75 | # - asset: fonts/TrajanPro_Bold.ttf 76 | # weight: 700 77 | # 78 | # For details regarding fonts from package dependencies, 79 | # see https://flutter.dev/custom-fonts/#from-packages 80 | -------------------------------------------------------------------------------- /documentation/sdk_examples/sep-0010-webauth.md: -------------------------------------------------------------------------------- 1 | 2 | ### SEP-0010 - Stellar Web Authentication 3 | 4 | 5 | 6 | Stellar Web Authentication is described in [SEP-0010](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0010.md). The SEP defines the standard way for clients such as wallets or exchanges to create authenticated web sessions on behalf of a user who holds a Stellar account. A wallet may want to authenticate with any web service which requires a Stellar account ownership verification, for example, to upload KYC information to an anchor in an authenticated way. 7 | 8 | The following examples show how to use the flutter stellar sdk to create authenticated web sessions on behalf of a user who holds a Stellar account. 9 | 10 | 11 | 12 | **Create a WebAuth instance** 13 | 14 | by providing the domain hosting the stellar.toml file: 15 | 16 | ```dart 17 | final webauth = await WebAuth.fromDomain("place.domain.com", Network.TESTNET); 18 | ``` 19 | 20 | **Request the jwtToken** 21 | 22 | for the web session by providing the account id of the client/user and the signers of the client account to sign the challenge from the web auth server: 23 | 24 | ```dart 25 | KeyPair clientKeyPair = KeyPair.fromSecretSeed(clientSecretSeed); 26 | String jwtToken = await webAuth.jwtToken(clientKeyPair.accountId,[clientKeyPair]); 27 | ``` 28 | 29 | That is all you need to do. The method ```jwtToken``` will request the challenge from the web auth server, validate it, sign it on behalf of the user and send it back to the web auth server. The web auth server will than respond with the jwt token. 30 | 31 | 32 | 33 | ### Client Attribution support 34 | The flutter sdk also provides client attribution support. To use it, pass the client domain and the client domain account key pair for signing: 35 | 36 | ```dart 37 | KeyPair clientKeyPair = KeyPair.fromSecretSeed(clientSecretSeed); 38 | KeyPair clientDomainAccountKeyPair = KeyPair.fromSecretSeed(clientDomainAccountSecretSeed); 39 | String jwtToken = await webAuth.jwtToken(clientKeyPair.accountId,[clientKeyPair],clientDomain:"place.client.com", clientDomainAccountKeyPair: clientDomainAccountKeyPair); 40 | ``` 41 | 42 | ### Client Domain Signing Delegate 43 | 44 | If you do not want to expose the client domain account keypair, you can alternatively provide a callback function (clientDomainSigningDelegate) that signs the challenge transaction with the client domain account. This is useful for remote signing services. 45 | 46 | ```dart 47 | // Example: Using a remote signing service 48 | String jwtToken = await webAuth.jwtToken( 49 | userAccountId, 50 | [userKeyPair], 51 | clientDomain: clientDomain, 52 | clientDomainSigningDelegate: (transactionXdr) async { 53 | // Send to remote signing service 54 | final response = await httpClient.post( 55 | Uri.parse('https://your-signer.example.com/sign-sep-10'), 56 | headers: { 57 | 'Content-Type': 'application/json', 58 | 'Authorization': 'Bearer $bearerToken', 59 | }, 60 | body: json.encode({ 61 | 'transaction': transactionXdr, 62 | 'network_passphrase': 'Test SDF Network ; September 2015', 63 | }), 64 | ); 65 | 66 | final jsonData = json.decode(response.body); 67 | return jsonData['transaction'] as String; 68 | }, 69 | ); 70 | ``` 71 | 72 | ### More examples 73 | You can find more examples in the test cases. 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hi@soneso.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://www.contributor-covenant.org/version/2/0/code_of_conduct.html][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html 47 | -------------------------------------------------------------------------------- /documentation/sdk_examples/muxed_account_payment.md: -------------------------------------------------------------------------------- 1 | 2 | ### Use muxed account for payment 3 | 4 | In this example we will see how to use a muxed account in a payment. 5 | 6 | Muxed accounts can furthermore be used in: 7 | - payment operation destination 8 | - payment strict receive operation destination 9 | - payment strict send operation destination 10 | - any operation source account 11 | - account merge operation destination 12 | - transaction source account 13 | - fee bump transaction fee source 14 | 15 | ```dart 16 | // Create two random key pairs, we will need them later for signing. 17 | KeyPair senderKeyPair = KeyPair.random(); 18 | KeyPair receiverKeyPair = KeyPair.random(); 19 | 20 | // AccountIds 21 | String accountCId = receiverKeyPair.accountId; 22 | String senderAccountId = senderKeyPair.accountId; 23 | 24 | // Create the sender account. 25 | await FriendBot.fundTestAccount(senderAccountId); 26 | 27 | // Load the current account data of the sender account. 28 | AccountResponse accountA = await sdk.accounts.account(senderAccountId); 29 | 30 | // Create the receiver account. 31 | Transaction transaction = new TransactionBuilder(accountA) 32 | .addOperation( 33 | new CreateAccountOperationBuilder(accountCId, "10").build()) 34 | .build(); 35 | 36 | // Sign. 37 | transaction.sign(senderKeyPair, Network.TESTNET); 38 | 39 | // Submit. 40 | SubmitTransactionResponse response = await sdk.submitTransaction(transaction); 41 | 42 | // Now let's create the mxued accounts to be used in the payment transaction. 43 | MuxedAccount muxedDestinationAccount = MuxedAccount(accountCId, 8298298319); 44 | MuxedAccount muxedSourceAccount = MuxedAccount(senderAccountId, 2442424242); 45 | 46 | // Build the payment operation. 47 | // We use the muxed account objects for destination and for source here. 48 | // This is not needed, you can also use only a muxed source account or muxed destination account. 49 | PaymentOperation paymentOperation = 50 | PaymentOperationBuilder.forMuxedDestinationAccount( 51 | muxedDestinationAccount, Asset.NATIVE, "100") 52 | .setMuxedSourceAccount(muxedSourceAccount) 53 | .build(); 54 | 55 | // Build the transaction. 56 | // If we want to use a Med25519 muxed account with id as a source of the transaction, we can just set the id in our account object. 57 | accountA.muxedAccountMed25519Id = 44498494844; 58 | transaction = new TransactionBuilder(accountA) 59 | .addOperation(paymentOperation) 60 | .build(); 61 | 62 | // Sign. 63 | transaction.sign(senderKeyPair, Network.TESTNET); 64 | 65 | // Submit. 66 | response = await sdk.submitTransaction(transaction); 67 | 68 | // Have a look to the transaction and the contents of the envelope in Stellar Laboratory 69 | // https://laboratory.stellar.org/#explorer?resource=transactions&endpoint=single&network=test 70 | print(response.hash); 71 | ``` 72 | 73 | Since version 1.2.9 also use muxed "M..." addresses are supported by default as source account ids and destination account ids. 74 | 75 | For example: 76 | ```dart 77 | String sourceAccountId = "MD6HSPJQPCQBMMSPP33SMERH32U5ZWIJN7DAD2V3UPWZBO347GN3EAAAAAAAAAPGE4NB4"; 78 | String destinationAccountId = "MBUZNQV4SSPFZPLIK55ZQ4SZWROKZLJQ62YF5Q3IKJAD5ICYCC3JSAAAAAAAABHOUBCZ4"; 79 | 80 | PaymentOperation paymentOperation = new PaymentOperationBuilder(destinationAccountId, Asset.NATIVE, "100") 81 | .setSourceAccount(sourceAccountId) 82 | .build(); 83 | ``` -------------------------------------------------------------------------------- /lib/src/responses/operations/extend_footprint_ttl_operation_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'operation_responses.dart'; 6 | import '../transaction_response.dart'; 7 | import '../response.dart'; 8 | 9 | /// Represents an extend footprint TTL operation response from Horizon. 10 | /// 11 | /// This Soroban operation extends the time-to-live (TTL) of contract data entries, 12 | /// preventing them from expiring and being archived. 13 | /// 14 | /// Returned by: Horizon API operations endpoint when querying extend footprint TTL operations 15 | /// 16 | /// See also: 17 | /// - [ExtendFootprintTTLOperation] for extending contract data TTL 18 | /// - [Stellar developer docs](https://developers.stellar.org) 19 | class ExtendFootprintTTLOperationResponse extends OperationResponse { 20 | /// The ledger number to which the footprint entries' TTL is extended 21 | int extendTo; 22 | 23 | /// Creates an ExtendFootprintTTLOperationResponse from Horizon API operation data. 24 | /// 25 | /// This constructor is typically called internally when deserializing operation 26 | /// records from Horizon API responses. 27 | /// 28 | /// Parameters: 29 | /// - [extendTo] The ledger number to which the footprint entries' TTL is extended 30 | /// - [links] Hypermedia links to related resources 31 | /// - [id] Unique operation identifier 32 | /// - [pagingToken] Pagination cursor 33 | /// - [transactionSuccessful] Whether the parent transaction succeeded 34 | /// - [sourceAccount] Operation source account ID 35 | /// - [sourceAccountMuxed] Muxed source account (if applicable) 36 | /// - [sourceAccountMuxedId] Muxed source account ID (if applicable) 37 | /// - [type] Operation type name 38 | /// - [type_i] Operation type as integer 39 | /// - [createdAt] Creation timestamp 40 | /// - [transactionHash] Parent transaction hash 41 | /// - [transaction] Full parent transaction 42 | /// - [sponsor] Account sponsoring the operation (if applicable) 43 | ExtendFootprintTTLOperationResponse( 44 | this.extendTo, 45 | super.links, 46 | super.id, 47 | super.pagingToken, 48 | super.transactionSuccessful, 49 | super.sourceAccount, 50 | super.sourceAccountMuxed, 51 | super.sourceAccountMuxedId, 52 | super.type, 53 | super.type_i, 54 | super.createdAt, 55 | super.transactionHash, 56 | super.transaction, 57 | super.sponsor); 58 | 59 | /// Deserializes an extend footprint TTL operation response from JSON. 60 | factory ExtendFootprintTTLOperationResponse.fromJson( 61 | Map json) => 62 | ExtendFootprintTTLOperationResponse( 63 | convertInt(json['extend_to'])!, 64 | OperationResponseLinks.fromJson(json['_links']), 65 | json['id'], 66 | json['paging_token'], 67 | json['transaction_successful'], 68 | json['source_account'], 69 | json['source_account_muxed'], 70 | json['source_account_muxed_id'], 71 | json['type'], 72 | json['type_i'], 73 | json['created_at'], 74 | json['transaction_hash'], 75 | json['transaction'] == null 76 | ? null 77 | : TransactionResponse.fromJson(json['transaction']), 78 | json['sponsor']); 79 | } 80 | -------------------------------------------------------------------------------- /compatibility/sep/SEP-0046_COMPATIBILITY_MATRIX.md: -------------------------------------------------------------------------------- 1 | # SEP-0046 (Contract Meta) Compatibility Matrix 2 | 3 | **Generated:** 2025-12-18 14:05:14 4 | 5 | **SDK Version:** 2.2.1 6 | **SEP Version:** 1.0.0 7 | **SEP Status:** Active 8 | **SEP URL:** https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0046.md 9 | 10 | ## SEP Summary 11 | 12 | A standard for the storage of metadata in contract Wasm files. 13 | 14 | ## Overall Coverage 15 | 16 | **Total Coverage:** 100.0% (9/9 fields) 17 | 18 | - ✅ **Implemented:** 9/9 19 | - ❌ **Not Implemented:** 0/9 20 | 21 | **Required Fields:** 100.0% (9/9) 22 | 23 | **Optional Fields:** 0% (0/0) 24 | 25 | ## Implementation Status 26 | 27 | ✅ **Implemented** 28 | 29 | ### Implementation Files 30 | 31 | - `lib/src/soroban/soroban_contract_parser.dart` 32 | 33 | ### Key Classes 34 | 35 | - **`SorobanContractParser`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 36 | - **`SorobanContractParserFailed`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 37 | - **`SorobanContractInfo`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 38 | 39 | ## Coverage by Section 40 | 41 | | Section | Coverage | Required Coverage | Implemented | Total | 42 | |---------|----------|-------------------|-------------|-------| 43 | | Encoding Format | 100.0% | 100.0% | 3 | 3 | 44 | | Implementation Support | 100.0% | 100.0% | 3 | 3 | 45 | | Metadata Storage | 100.0% | 100.0% | 3 | 3 | 46 | 47 | ## Detailed Field Comparison 48 | 49 | ### Encoding Format 50 | 51 | | Field | Required | Status | SDK Property | Description | 52 | |-------|----------|--------|--------------|-------------| 53 | | `binary_stream_encoding` | ✓ | ✅ | `_parseMeta` | Encode entries as a stream of binary values | 54 | | `key_value_pairs` | ✓ | ✅ | `metaEntries` | Store metadata as key-value string pairs | 55 | | `scmetaentry_xdr` | ✓ | ✅ | `_parseMeta` | Use SCMetaEntry XDR type for structuring metadata | 56 | 57 | ### Implementation Support 58 | 59 | | Field | Required | Status | SDK Property | Description | 60 | |-------|----------|--------|--------------|-------------| 61 | | `decode_scmetaentry` | ✓ | ✅ | `_parseMeta` | Decode SCMetaEntry XDR structures | 62 | | `extract_meta_entries` | ✓ | ✅ | `_parseMeta` | Extract meta entries as key-value pairs from contract | 63 | | `parse_contract_meta` | ✓ | ✅ | `parseContractByteCode` | Parse contract metadata from contract bytecode | 64 | 65 | ### Metadata Storage 66 | 67 | | Field | Required | Status | SDK Property | Description | 68 | |-------|----------|--------|--------------|-------------| 69 | | `contractmetav0_section` | ✓ | ✅ | `_parseMeta` | Support for storing metadata in "contractmetav0" Wasm custom sections | 70 | | `multiple_entries_single_section` | ✓ | ✅ | `_parseMeta` | Support for multiple metadata entries in a single custom section | 71 | | `multiple_sections` | ✓ | ✅ | `_parseMeta` | Support for multiple "contractmetav0" sections interpreted sequentially | 72 | 73 | ## Implementation Gaps 74 | 75 | 🎉 **No gaps found!** All fields are implemented. 76 | 77 | ## Recommendations 78 | 79 | ✅ The SDK has full compatibility with SEP-0046! 80 | 81 | ## Legend 82 | 83 | - ✅ **Implemented**: Field is implemented in SDK 84 | - ❌ **Not Implemented**: Field is missing from SDK 85 | - ⚙️ **Server**: Server-side only feature (not applicable to client SDKs) 86 | - ✓ **Required**: Field is required by SEP specification 87 | - (blank) **Optional**: Field is optional 88 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_memo.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_data_io.dart'; 6 | import 'xdr_type.dart'; 7 | 8 | class XdrMemoType { 9 | final _value; 10 | const XdrMemoType._internal(this._value); 11 | toString() => 'MemoType.$_value'; 12 | XdrMemoType(this._value); 13 | get value => this._value; 14 | 15 | static const MEMO_NONE = const XdrMemoType._internal(0); 16 | static const MEMO_TEXT = const XdrMemoType._internal(1); 17 | static const MEMO_ID = const XdrMemoType._internal(2); 18 | static const MEMO_HASH = const XdrMemoType._internal(3); 19 | static const MEMO_RETURN = const XdrMemoType._internal(4); 20 | 21 | static XdrMemoType decode(XdrDataInputStream stream) { 22 | int value = stream.readInt(); 23 | switch (value) { 24 | case 0: 25 | return MEMO_NONE; 26 | case 1: 27 | return MEMO_TEXT; 28 | case 2: 29 | return MEMO_ID; 30 | case 3: 31 | return MEMO_HASH; 32 | case 4: 33 | return MEMO_RETURN; 34 | default: 35 | throw Exception("Unknown enum value: $value"); 36 | } 37 | } 38 | 39 | static void encode(XdrDataOutputStream stream, XdrMemoType value) { 40 | stream.writeInt(value.value); 41 | } 42 | } 43 | 44 | class XdrMemo { 45 | XdrMemo(this._type); 46 | XdrMemoType _type; 47 | XdrMemoType get discriminant => this._type; 48 | set discriminant(XdrMemoType value) => this._type = value; 49 | 50 | String? _text; 51 | String? get text => this._text; 52 | set text(String? value) => this._text = value; 53 | 54 | XdrUint64? _id; 55 | XdrUint64? get id => this._id; 56 | set id(XdrUint64? value) => this._id = value; 57 | 58 | XdrHash? _hash; 59 | XdrHash? get hash => this._hash; 60 | set hash(XdrHash? value) => this._hash = value; 61 | 62 | XdrHash? _retHash; 63 | XdrHash? get retHash => this._retHash; 64 | set retHash(XdrHash? value) => this._retHash = value; 65 | 66 | static void encode(XdrDataOutputStream stream, XdrMemo encodedMemo) { 67 | stream.writeInt(encodedMemo.discriminant.value); 68 | switch (encodedMemo.discriminant) { 69 | case XdrMemoType.MEMO_NONE: 70 | break; 71 | case XdrMemoType.MEMO_TEXT: 72 | stream.writeString(encodedMemo.text!); 73 | break; 74 | case XdrMemoType.MEMO_ID: 75 | XdrUint64.encode(stream, encodedMemo.id!); 76 | break; 77 | case XdrMemoType.MEMO_HASH: 78 | XdrHash.encode(stream, encodedMemo.hash!); 79 | break; 80 | case XdrMemoType.MEMO_RETURN: 81 | XdrHash.encode(stream, encodedMemo.retHash!); 82 | break; 83 | } 84 | } 85 | 86 | static XdrMemo decode(XdrDataInputStream stream) { 87 | XdrMemo decodedMemo = XdrMemo(XdrMemoType.decode(stream)); 88 | switch (decodedMemo.discriminant) { 89 | case XdrMemoType.MEMO_NONE: 90 | break; 91 | case XdrMemoType.MEMO_TEXT: 92 | decodedMemo.text = stream.readString(); 93 | break; 94 | case XdrMemoType.MEMO_ID: 95 | decodedMemo.id = XdrUint64.decode(stream); 96 | break; 97 | case XdrMemoType.MEMO_HASH: 98 | decodedMemo.hash = XdrHash.decode(stream); 99 | break; 100 | case XdrMemoType.MEMO_RETURN: 101 | decodedMemo.retHash = XdrHash.decode(stream); 102 | break; 103 | } 104 | return decodedMemo; 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /compatibility/sep/SEP-0047_COMPATIBILITY_MATRIX.md: -------------------------------------------------------------------------------- 1 | # SEP-0047 (Contract Interface Discovery) Compatibility Matrix 2 | 3 | **Generated:** 2025-12-18 14:05:15 4 | 5 | **SDK Version:** 2.2.1 6 | **SEP Version:** 0.1.0 7 | **SEP Status:** Draft 8 | **SEP URL:** https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0047.md 9 | 10 | ## SEP Summary 11 | 12 | A standard for a contract to indicate which SEPs it claims to implement. 13 | 14 | ## Overall Coverage 15 | 16 | **Total Coverage:** 100.0% (9/9 fields) 17 | 18 | - ✅ **Implemented:** 9/9 19 | - ❌ **Not Implemented:** 0/9 20 | 21 | **Required Fields:** 100.0% (9/9) 22 | 23 | **Optional Fields:** 0% (0/0) 24 | 25 | ## Implementation Status 26 | 27 | ✅ **Implemented** 28 | 29 | ### Implementation Files 30 | 31 | - `lib/src/soroban/soroban_contract_parser.dart` 32 | 33 | ### Key Classes 34 | 35 | - **`SorobanContractParser`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 36 | - **`SorobanContractParserFailed`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 37 | - **`SorobanContractInfo`**: Parser for extracting metadata from Soroban contract WebAssembly bytecode. 38 | 39 | ## Coverage by Section 40 | 41 | | Section | Coverage | Required Coverage | Implemented | Total | 42 | |---------|----------|-------------------|-------------|-------| 43 | | Implementation Support | 100.0% | 100.0% | 3 | 3 | 44 | | Meta Entry Format | 100.0% | 100.0% | 3 | 3 | 45 | | SEP Declaration | 100.0% | 100.0% | 3 | 3 | 46 | 47 | ## Detailed Field Comparison 48 | 49 | ### Implementation Support 50 | 51 | | Field | Required | Status | SDK Property | Description | 52 | |-------|----------|--------|--------------|-------------| 53 | | `expose_supported_seps` | ✓ | ✅ | `supportedSeps` | Expose supportedSeps property on contract info object | 54 | | `parse_supported_seps` | ✓ | ✅ | `_parseSupportedSeps` | Parse and extract list of supported SEPs from contract metadata | 55 | | `validate_sep_format` | ✓ | ✅ | `_parseSupportedSeps` | Validate SEP number format and filter invalid entries | 56 | 57 | ### Meta Entry Format 58 | 59 | | Field | Required | Status | SDK Property | Description | 60 | |-------|----------|--------|--------------|-------------| 61 | | `empty_value_handling` | ✓ | ✅ | `_parseSupportedSeps` | Handle empty or missing "sep" meta entries gracefully | 62 | | `sep_number_format` | ✓ | ✅ | `_parseSupportedSeps` | Parse SEP numbers in various formats (e.g., "41", "0041", "SEP-41") | 63 | | `whitespace_handling` | ✓ | ✅ | `_parseSupportedSeps` | Trim whitespace from SEP numbers in comma-separated list | 64 | 65 | ### SEP Declaration 66 | 67 | | Field | Required | Status | SDK Property | Description | 68 | |-------|----------|--------|--------------|-------------| 69 | | `comma_separated_list` | ✓ | ✅ | `_parseSupportedSeps` | Parse comma-separated list of SEP numbers from meta value | 70 | | `multiple_sep_entries` | ✓ | ✅ | `_parseSupportedSeps` | Support for multiple "sep" meta entries with combined values | 71 | | `sep_meta_key` | ✓ | ✅ | `_parseSupportedSeps` | Support for "sep" meta entry key to indicate implemented SEPs | 72 | 73 | ## Implementation Gaps 74 | 75 | 🎉 **No gaps found!** All fields are implemented. 76 | 77 | ## Recommendations 78 | 79 | ✅ The SDK has full compatibility with SEP-0047! 80 | 81 | ## Legend 82 | 83 | - ✅ **Implemented**: Field is implemented in SDK 84 | - ❌ **Not Implemented**: Field is missing from SDK 85 | - ⚙️ **Server**: Server-side only feature (not applicable to client SDKs) 86 | - ✓ **Required**: Field is required by SEP specification 87 | - (blank) **Optional**: Field is optional 88 | -------------------------------------------------------------------------------- /lib/src/network.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'dart:convert'; 6 | import 'dart:typed_data'; 7 | import 'util.dart'; 8 | 9 | /// Represents a Stellar network (public, testnet, or custom). 10 | /// 11 | /// The Network class specifies which Stellar network to use for transactions. 12 | /// Each network has a unique network passphrase that is hashed into every 13 | /// transaction hash, preventing transactions from one network being replayed 14 | /// on another network (replay attack protection). 15 | /// 16 | /// Available networks: 17 | /// - [PUBLIC]: The production Stellar network (mainnet) 18 | /// - [TESTNET]: The test network for development and testing 19 | /// - [FUTURENET]: The network for testing upcoming protocol features 20 | /// 21 | /// Network passphrases are critical for security: 22 | /// - Transactions signed for one network cannot be submitted to another 23 | /// - The passphrase is hashed into the transaction signature 24 | /// - Always verify you're using the correct network before signing 25 | /// 26 | /// Example usage: 27 | /// ```dart 28 | /// // Sign for testnet (development) 29 | /// transaction.sign(keyPair, Network.TESTNET); 30 | /// 31 | /// // Sign for mainnet (production) 32 | /// transaction.sign(keyPair, Network.PUBLIC); 33 | /// 34 | /// // Create custom network (for standalone/private networks) 35 | /// Network customNetwork = Network("Custom Network ; January 2024"); 36 | /// transaction.sign(keyPair, customNetwork); 37 | /// ``` 38 | /// 39 | /// Security warnings: 40 | /// - NEVER use TESTNET credentials on PUBLIC network 41 | /// - NEVER use PUBLIC network for testing 42 | /// - Always double-check network before signing with real funds 43 | /// - Test thoroughly on TESTNET before deploying to PUBLIC 44 | /// 45 | /// See also: 46 | /// - [Transaction.sign] for signing with a specific network 47 | /// - [Transaction.hash] to compute network-specific transaction hash 48 | /// - [Stellar developer docs](https://developers.stellar.org) 49 | class Network { 50 | /// The production Stellar network (mainnet). 51 | /// 52 | /// Use this for real transactions with actual funds. Transactions on this 53 | /// network have real economic value and cannot be reversed. 54 | static final Network PUBLIC = 55 | new Network("Public Global Stellar Network ; September 2015"); 56 | 57 | /// The test network for development and testing. 58 | /// 59 | /// Use this for development and testing. Test XLM can be obtained from 60 | /// friendbot and has no real value. Always test your application thoroughly 61 | /// on TESTNET before deploying to PUBLIC. 62 | static final Network TESTNET = 63 | new Network("Test SDF Network ; September 2015"); 64 | 65 | /// The future network for testing upcoming protocol features. 66 | /// 67 | /// This network is used to test protocol changes before they are released 68 | /// to TESTNET and PUBLIC. It may be reset periodically. 69 | static final Network FUTURENET = 70 | new Network("Test SDF Future Network ; October 2022"); 71 | 72 | String _networkPassphrase; 73 | 74 | /// Creates a new Network object to represent a network with a given [networkPassphrase]. 75 | Network(this._networkPassphrase); 76 | 77 | /// Returns the network passphrase of this network. 78 | String get networkPassphrase => _networkPassphrase; 79 | 80 | /// Returns the network id (SHA-256 hashed networkPassphrase). 81 | Uint8List? get networkId => 82 | Util.hash(Uint8List.fromList(utf8.encode(this.networkPassphrase))); 83 | } 84 | -------------------------------------------------------------------------------- /example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /lib/src/responses/operations/bump_sequence_operation_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'operation_responses.dart'; 6 | import '../transaction_response.dart'; 7 | 8 | /// Represents a bump sequence operation response from Horizon. 9 | /// 10 | /// A bump sequence operation advances the sequence number of the source account 11 | /// to a specified value, invalidating any transactions with lower sequence numbers. 12 | /// 13 | /// Returned by: Horizon API operations endpoint when querying bump sequence operations 14 | /// 15 | /// Fields: 16 | /// - [bumpTo]: The new sequence number for the source account 17 | /// 18 | /// Example: 19 | /// ```dart 20 | /// final operations = await sdk.operations 21 | /// .forAccount('account_id') 22 | /// .execute(); 23 | /// 24 | /// for (var op in operations.records) { 25 | /// if (op is BumpSequenceOperationResponse) { 26 | /// print('Sequence bumped to: ${op.bumpTo}'); 27 | /// } 28 | /// } 29 | /// ``` 30 | /// 31 | /// See also: 32 | /// - [BumpSequenceOperation] for creating bump sequence operations 33 | /// - [Stellar developer docs](https://developers.stellar.org) 34 | class BumpSequenceOperationResponse extends OperationResponse { 35 | /// The new sequence number for the source account 36 | String bumpTo; 37 | 38 | /// Creates a BumpSequenceOperationResponse from Horizon API operation data. 39 | /// 40 | /// This constructor is typically called internally when deserializing operation 41 | /// records from Horizon API responses. 42 | /// 43 | /// Parameters: 44 | /// - [bumpTo]: The new sequence number for the source account 45 | /// - [links]: Hypermedia links to related resources 46 | /// - [id]: Unique operation identifier 47 | /// - [pagingToken]: Pagination cursor 48 | /// - [transactionSuccessful]: Whether the parent transaction succeeded 49 | /// - [sourceAccount]: Operation source account ID 50 | /// - [sourceAccountMuxed]: Muxed source account (if applicable) 51 | /// - [sourceAccountMuxedId]: Muxed source account ID (if applicable) 52 | /// - [type]: Operation type name 53 | /// - [type_i]: Operation type as integer 54 | /// - [createdAt]: Creation timestamp 55 | /// - [transactionHash]: Parent transaction hash 56 | /// - [transaction]: Full parent transaction 57 | /// - [sponsor]: Account sponsoring the operation (if applicable) 58 | BumpSequenceOperationResponse( 59 | this.bumpTo, 60 | super.links, 61 | super.id, 62 | super.pagingToken, 63 | super.transactionSuccessful, 64 | super.sourceAccount, 65 | super.sourceAccountMuxed, 66 | super.sourceAccountMuxedId, 67 | super.type, 68 | super.type_i, 69 | super.createdAt, 70 | super.transactionHash, 71 | super.transaction, 72 | super.sponsor); 73 | 74 | /// Deserializes a bump sequence operation response from JSON. 75 | factory BumpSequenceOperationResponse.fromJson(Map json) => 76 | BumpSequenceOperationResponse( 77 | json['bump_to'], 78 | OperationResponseLinks.fromJson(json['_links']), 79 | json['id'], 80 | json['paging_token'], 81 | json['transaction_successful'], 82 | json['source_account'], 83 | json['source_account_muxed'], 84 | json['source_account_muxed_id'], 85 | json['type'], 86 | json['type_i'], 87 | json['created_at'], 88 | json['transaction_hash'], 89 | json['transaction'] == null 90 | ? null 91 | : TransactionResponse.fromJson(json['transaction']), 92 | json['sponsor']); 93 | } 94 | -------------------------------------------------------------------------------- /test/contract_bindings/atomic_swap_contract_client.dart: -------------------------------------------------------------------------------- 1 | // This file was generated by stellar_contract_bindings v0.5.0b0 and stellar_sdk v13.0.0. 2 | 3 | import 'dart:typed_data'; 4 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 5 | 6 | /// Client for interacting with the AtomicSwapContract contract 7 | class AtomicSwapContract { 8 | /// The underlying SorobanClient instance 9 | final SorobanClient _client; 10 | 11 | /// Creates a new AtomicSwapContract for the given contract ID 12 | static Future forContractId({ 13 | required KeyPair sourceAccountKeyPair, 14 | required String contractId, 15 | required Network network, 16 | required String rpcUrl, 17 | bool enableServerLogging = false, 18 | }) async { 19 | final options = ClientOptions( 20 | sourceAccountKeyPair: sourceAccountKeyPair, 21 | contractId: contractId, 22 | network: network, 23 | rpcUrl: rpcUrl, 24 | enableServerLogging: enableServerLogging, 25 | ); 26 | 27 | final client = await SorobanClient.forClientOptions(options: options); 28 | return AtomicSwapContract._(client); 29 | } 30 | 31 | /// Private constructor that wraps a SorobanClient 32 | AtomicSwapContract._(this._client); 33 | 34 | /// Gets the contract ID 35 | String getContractId() => _client.getContractId(); 36 | 37 | /// Gets the client options 38 | ClientOptions getOptions() => _client.getOptions(); 39 | 40 | /// Gets the contract specification 41 | ContractSpec getContractSpec() => _client.getContractSpec(); 42 | 43 | /// Invokes the swap method 44 | Future swap({ 45 | required Address a, 46 | required Address b, 47 | required Address tokenA, 48 | required Address tokenB, 49 | required BigInt amountA, 50 | required BigInt minBForA, 51 | required BigInt amountB, 52 | required BigInt minAForB, 53 | KeyPair? signer, 54 | int baseFee = 100, 55 | int transactionTimeout = 300, 56 | int submitTimeout = 30, 57 | bool simulate = true, 58 | bool restore = true, 59 | bool force = false, 60 | }) async { 61 | final List args = [ 62 | a.toXdrSCVal(), 63 | b.toXdrSCVal(), 64 | tokenA.toXdrSCVal(), 65 | tokenB.toXdrSCVal(), 66 | XdrSCVal.forI128BigInt(amountA), 67 | XdrSCVal.forI128BigInt(minBForA), 68 | XdrSCVal.forI128BigInt(amountB), 69 | XdrSCVal.forI128BigInt(minAForB), 70 | ]; 71 | 72 | final methodOptions = MethodOptions(); 73 | // You can customize method options here if needed 74 | 75 | final result = await _client.invokeMethod( 76 | name: 'swap', 77 | args: args, 78 | force: force, 79 | methodOptions: methodOptions, 80 | ); 81 | } 82 | 83 | /// Builds an AssembledTransaction for the swap method. 84 | /// This is useful if you need to manipulate the transaction before signing and sending. 85 | Future buildSwapTx({ 86 | required Address a, 87 | required Address b, 88 | required Address tokenA, 89 | required Address tokenB, 90 | required BigInt amountA, 91 | required BigInt minBForA, 92 | required BigInt amountB, 93 | required BigInt minAForB, 94 | MethodOptions? methodOptions, 95 | }) async { 96 | final List args = [ 97 | a.toXdrSCVal(), 98 | b.toXdrSCVal(), 99 | tokenA.toXdrSCVal(), 100 | tokenB.toXdrSCVal(), 101 | XdrSCVal.forI128BigInt(amountA), 102 | XdrSCVal.forI128BigInt(minBForA), 103 | XdrSCVal.forI128BigInt(amountB), 104 | XdrSCVal.forI128BigInt(minAForB), 105 | ]; 106 | 107 | return await _client.buildInvokeMethodTx( 108 | name: 'swap', 109 | args: args, 110 | methodOptions: methodOptions, 111 | ); 112 | } 113 | } -------------------------------------------------------------------------------- /lib/src/responses/operations/manage_data_operation_response.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2024 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'operation_responses.dart'; 6 | import '../transaction_response.dart'; 7 | 8 | /// Represents a manage data operation response from Horizon. 9 | /// 10 | /// A manage data operation sets, modifies, or deletes a data entry (key-value pair) 11 | /// associated with an account. Each account can store up to 1000 data entries. 12 | /// 13 | /// Returned by: Horizon API operations endpoint when querying manage data operations 14 | /// 15 | /// Fields: 16 | /// - [name] The key name of the data entry 17 | /// - [value] The base64-encoded value (empty string to delete the entry) 18 | /// 19 | /// Example: 20 | /// ```dart 21 | /// final operations = await sdk.operations 22 | /// .forAccount('account_id') 23 | /// .execute(); 24 | /// 25 | /// for (var op in operations.records) { 26 | /// if (op is ManageDataOperationResponse) { 27 | /// print('Data entry: ${op.name}'); 28 | /// print('Value: ${op.value}'); 29 | /// } 30 | /// } 31 | /// ``` 32 | /// 33 | /// See also: 34 | /// - [ManageDataOperation] for creating manage data operations 35 | /// - [Stellar developer docs](https://developers.stellar.org) 36 | class ManageDataOperationResponse extends OperationResponse { 37 | /// The key name of the data entry 38 | String name; 39 | 40 | /// The base64-encoded value (empty string to delete the entry) 41 | String value; 42 | 43 | /// Creates a ManageDataOperationResponse from Horizon API operation data. 44 | /// 45 | /// This constructor is typically called internally when deserializing operation 46 | /// records from Horizon API responses. 47 | /// 48 | /// Parameters: 49 | /// - [name] The key name of the data entry 50 | /// - [value] The base64-encoded value 51 | /// - [links] Hypermedia links to related resources 52 | /// - [id] Unique operation identifier 53 | /// - [pagingToken] Pagination cursor 54 | /// - [transactionSuccessful] Whether the parent transaction succeeded 55 | /// - [sourceAccount] Operation source account ID 56 | /// - [sourceAccountMuxed] Muxed source account (if applicable) 57 | /// - [sourceAccountMuxedId] Muxed source account ID (if applicable) 58 | /// - [type] Operation type name 59 | /// - [type_i] Operation type as integer 60 | /// - [createdAt] Creation timestamp 61 | /// - [transactionHash] Parent transaction hash 62 | /// - [transaction] Full parent transaction 63 | /// - [sponsor] Account sponsoring the operation (if applicable) 64 | ManageDataOperationResponse( 65 | this.name, 66 | this.value, 67 | super.links, 68 | super.id, 69 | super.pagingToken, 70 | super.transactionSuccessful, 71 | super.sourceAccount, 72 | super.sourceAccountMuxed, 73 | super.sourceAccountMuxedId, 74 | super.type, 75 | super.type_i, 76 | super.createdAt, 77 | super.transactionHash, 78 | super.transaction, 79 | super.sponsor); 80 | 81 | /// Deserializes a manage data operation response from JSON. 82 | factory ManageDataOperationResponse.fromJson(Map json) => 83 | ManageDataOperationResponse( 84 | json['name'], 85 | json['value'], 86 | OperationResponseLinks.fromJson(json['_links']), 87 | json['id'], 88 | json['paging_token'], 89 | json['transaction_successful'], 90 | json['source_account'], 91 | json['source_account_muxed'], 92 | json['source_account_muxed_id'], 93 | json['type'], 94 | json['type_i'], 95 | json['created_at'], 96 | json['transaction_hash'], 97 | json['transaction'] == null 98 | ? null 99 | : TransactionResponse.fromJson(json['transaction']), 100 | json['sponsor']); 101 | } 102 | -------------------------------------------------------------------------------- /example/health_check_example.dart: -------------------------------------------------------------------------------- 1 | import 'package:stellar_flutter_sdk/stellar_flutter_sdk.dart'; 2 | 3 | Future main() async { 4 | // Example: Check the health of various Stellar networks 5 | 6 | print('Checking health of Stellar networks...\n'); 7 | 8 | // Check PUBLIC network health 9 | await checkNetworkHealth('PUBLIC', StellarSDK.PUBLIC); 10 | 11 | // Check TESTNET health 12 | await checkNetworkHealth('TESTNET', StellarSDK.TESTNET); 13 | 14 | // Check FUTURENET health 15 | await checkNetworkHealth('FUTURENET', StellarSDK.FUTURENET); 16 | 17 | // Check custom Horizon server health 18 | final customSdk = StellarSDK('https://custom-horizon.example.com'); 19 | await checkNetworkHealth('CUSTOM', customSdk); 20 | } 21 | 22 | Future checkNetworkHealth(String networkName, StellarSDK sdk) async { 23 | print('--- $networkName Network ---'); 24 | 25 | try { 26 | // Execute health check 27 | final health = await sdk.health.execute(); 28 | 29 | // Display health status 30 | print('Is Healthy: ${health.isHealthy}'); 31 | print('Database Connected: ${health.databaseConnected}'); 32 | print('Core Up: ${health.coreUp}'); 33 | print('Core Synced: ${health.coreSynced}'); 34 | 35 | // Check if the server is healthy 36 | if (health.isHealthy) { 37 | print('✅ Server is fully operational'); 38 | } else { 39 | print('⚠️ Server may be experiencing issues'); 40 | 41 | if (!health.databaseConnected) { 42 | print(' - Database connection issue'); 43 | } 44 | if (!health.coreUp) { 45 | print(' - Stellar Core is down'); 46 | } 47 | if (!health.coreSynced) { 48 | print(' - Stellar Core is not synced'); 49 | } 50 | } 51 | 52 | // Display rate limit information if available 53 | if (health.rateLimitLimit != null) { 54 | print('Rate Limit: ${health.rateLimitRemaining}/${health.rateLimitLimit}'); 55 | } 56 | } catch (e) { 57 | print('❌ Error checking health: $e'); 58 | } 59 | 60 | print(''); 61 | } 62 | 63 | // Advanced example: Monitor server health periodically 64 | class HealthMonitor { 65 | final StellarSDK sdk; 66 | final Duration checkInterval; 67 | final Function(HealthResponse)? onHealthy; 68 | final Function(HealthResponse)? onUnhealthy; 69 | final Function(dynamic)? onError; 70 | 71 | HealthMonitor({ 72 | required this.sdk, 73 | this.checkInterval = const Duration(minutes: 1), 74 | this.onHealthy, 75 | this.onUnhealthy, 76 | this.onError, 77 | }); 78 | 79 | Stream startMonitoring() async* { 80 | while (true) { 81 | try { 82 | final health = await sdk.health.execute(); 83 | 84 | if (health.isHealthy) { 85 | onHealthy?.call(health); 86 | } else { 87 | onUnhealthy?.call(health); 88 | } 89 | 90 | yield health; 91 | } catch (e) { 92 | onError?.call(e); 93 | } 94 | 95 | await Future.delayed(checkInterval); 96 | } 97 | } 98 | } 99 | 100 | // Usage example for health monitoring 101 | void healthMonitoringExample() { 102 | final monitor = HealthMonitor( 103 | sdk: StellarSDK.PUBLIC, 104 | checkInterval: Duration(seconds: 30), 105 | onHealthy: (health) { 106 | print('Server is healthy - DB: ${health.databaseConnected}, Core: ${health.coreUp}, Synced: ${health.coreSynced}'); 107 | }, 108 | onUnhealthy: (health) { 109 | print('Server unhealthy! DB: ${health.databaseConnected}, Core: ${health.coreUp}, Synced: ${health.coreSynced}'); 110 | }, 111 | onError: (error) { 112 | print('Failed to check health: $error'); 113 | }, 114 | ); 115 | 116 | // Start monitoring 117 | monitor.startMonitoring().listen( 118 | (health) { 119 | // Process health updates 120 | print('Health update: ${health.isHealthy ? "healthy" : "unhealthy"}'); 121 | }, 122 | onError: (error) { 123 | print('Monitoring error: $error'); 124 | }, 125 | ); 126 | } -------------------------------------------------------------------------------- /lib/src/asset_type_credit_alphanum4.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'assets.dart'; 6 | import 'asset_type_credit_alphanum.dart'; 7 | import 'xdr/xdr_account.dart'; 8 | import 'xdr/xdr_asset.dart'; 9 | import 'key_pair.dart'; 10 | import 'util.dart'; 11 | 12 | /// Represents credit assets with 1-4 character asset codes. 13 | /// 14 | /// This is the most common type of credit asset on Stellar, used for assets 15 | /// with short codes like "USD", "EUR", "BTC", "USDC", etc. 16 | /// 17 | /// Asset code requirements: 18 | /// - Length: 1-4 characters (inclusive) 19 | /// - Characters: ASCII 32-127 excluding spaces 20 | /// - Case-sensitive: "USD" and "usd" are different assets 21 | /// - No leading/trailing spaces 22 | /// 23 | /// Common examples: 24 | /// - Fiat currencies: "USD", "EUR", "JPY", "GBP" 25 | /// - Cryptocurrencies: "BTC", "ETH" 26 | /// - Stablecoins: "USDC" (4 chars, fits in AlphaNum4) 27 | /// - Custom tokens: "GOLD", "OIL", "COIN" 28 | /// 29 | /// Creating assets: 30 | /// ```dart 31 | /// // US Dollar issued by an anchor 32 | /// Asset usd = AssetTypeCreditAlphaNum4( 33 | /// "USD", 34 | /// "GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX" 35 | /// ); 36 | /// 37 | /// // Bitcoin token 38 | /// Asset btc = AssetTypeCreditAlphaNum4( 39 | /// "BTC", 40 | /// "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" 41 | /// ); 42 | /// 43 | /// // Single character code 44 | /// Asset x = AssetTypeCreditAlphaNum4("X", issuerId); 45 | /// ``` 46 | /// 47 | /// Using in operations: 48 | /// ```dart 49 | /// // Create trustline 50 | /// ChangeTrustOperation trustOp = ChangeTrustOperationBuilder( 51 | /// usd, 52 | /// "10000" // Maximum amount to trust 53 | /// ).build(); 54 | /// 55 | /// // Make payment 56 | /// PaymentOperation paymentOp = PaymentOperationBuilder( 57 | /// destinationId, 58 | /// usd, 59 | /// "100.50" 60 | /// ).build(); 61 | /// ``` 62 | /// 63 | /// Important notes: 64 | /// - Codes longer than 4 characters must use [AssetTypeCreditAlphaNum12] 65 | /// - Empty codes or codes > 4 characters throw [AssetCodeLengthInvalidException] 66 | /// - Always verify the issuer address before trusting an asset 67 | /// - Asset code "XLM" is valid but discouraged (could confuse with native) 68 | /// 69 | /// See also: 70 | /// - [AssetTypeCreditAlphaNum12] for codes 5-12 characters 71 | /// - [AssetTypeCreditAlphaNum] for base credit asset functionality 72 | /// - [Asset] for general asset operations 73 | /// - [ChangeTrustOperation] for establishing trustlines 74 | class AssetTypeCreditAlphaNum4 extends AssetTypeCreditAlphaNum { 75 | /// Creates a credit asset with a 1-4 character code. 76 | /// 77 | /// Parameters: 78 | /// - [code] Asset code (1-4 characters, case-sensitive) 79 | /// - [issuerId] Issuer's Stellar account ID (G... address) 80 | /// 81 | /// Throws: 82 | /// - [AssetCodeLengthInvalidException] If code length is not 1-4 characters 83 | /// 84 | /// Example: 85 | /// ```dart 86 | /// Asset usd = AssetTypeCreditAlphaNum4( 87 | /// "USD", 88 | /// "GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX" 89 | /// ); 90 | /// ``` 91 | AssetTypeCreditAlphaNum4(String code, String issuerId) 92 | : super(code, issuerId) { 93 | if (code.length < 1 || code.length > 4) { 94 | throw new AssetCodeLengthInvalidException(); 95 | } 96 | } 97 | 98 | @override 99 | String get type => Asset.TYPE_CREDIT_ALPHANUM4; 100 | 101 | /// Converts this asset to its XDR Asset representation. 102 | /// 103 | /// Returns: XDR Asset for this 4-character credit alphanum asset. 104 | @override 105 | XdrAsset toXdr() { 106 | XdrAsset xdrAsset = XdrAsset(XdrAssetType.ASSET_TYPE_CREDIT_ALPHANUM4); 107 | 108 | XdrAccountID accountID = 109 | XdrAccountID(KeyPair.fromAccountId(issuerId).xdrPublicKey); 110 | 111 | XdrAssetAlphaNum4 credit = 112 | XdrAssetAlphaNum4(Util.paddedByteArrayString(mCode, 4), accountID); 113 | xdrAsset.alphaNum4 = credit; 114 | return xdrAsset; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /compatibility/sep/SEP-0002_COMPATIBILITY_MATRIX.md: -------------------------------------------------------------------------------- 1 | # SEP-0002 (Federation protocol) Compatibility Matrix 2 | 3 | **Generated:** 2025-12-18 14:04:39 4 | 5 | **SDK Version:** 2.2.1 6 | **SEP Version:** 1.1.0 7 | **SEP Status:** Final 8 | **SEP URL:** https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0002.md 9 | 10 | ## SEP Summary 11 | 12 | The Stellar federation protocol maps Stellar addresses to more information 13 | about a given user. It’s a way for Stellar client software to resolve 14 | email-like addresses such as `name*yourdomain.com` into account IDs like: 15 | `GCCVPYFOHY7ZB7557JKENAX62LUAPLMGIWNZJAFV2MITK6T32V37KEJU`. Stellar addresses 16 | provide an easy way for users to share payment details by using a syntax that 17 | interoperates across different domains and providers. 18 | 19 | ## Overall Coverage 20 | 21 | **Total Coverage:** 100.0% (10/10 fields) 22 | 23 | - ✅ **Implemented:** 10/10 24 | - ❌ **Not Implemented:** 0/10 25 | 26 | **Required Fields:** 100.0% (6/6) 27 | 28 | **Optional Fields:** 100.0% (4/4) 29 | 30 | ## Implementation Status 31 | 32 | ✅ **Implemented** 33 | 34 | ### Implementation Files 35 | 36 | - `lib/src/sep/0002/federation.dart` 37 | 38 | ### Key Classes 39 | 40 | - **`Federation`**: Implements SEP-0002 Federation protocol for human-readable Stellar addresses. 41 | - **`FederationResponse`**: Implements SEP-0002 Federation protocol for human-readable Stellar addresses. 42 | - **`_FederationRequestBuilder`**: Implements SEP-0002 Federation protocol for human-readable Stellar addresses. 43 | 44 | ## Coverage by Section 45 | 46 | | Section | Coverage | Required Coverage | Implemented | Total | 47 | |---------|----------|-------------------|-------------|-------| 48 | | Request Parameters | 100.0% | 100.0% | 2 | 2 | 49 | | Request Types | 100.0% | 100.0% | 4 | 4 | 50 | | Response Fields | 100.0% | 100.0% | 4 | 4 | 51 | 52 | ## Detailed Field Comparison 53 | 54 | ### Request Parameters 55 | 56 | | Field | Required | Status | SDK Property | Description | 57 | |-------|----------|--------|--------------|-------------| 58 | | `q` | ✓ | ✅ | `q` | String to look up (stellar address, account ID, or transaction ID) | 59 | | `type` | ✓ | ✅ | `type` | Type of lookup (name, id, txid, or forward) | 60 | 61 | ### Request Types 62 | 63 | | Field | Required | Status | SDK Property | Description | 64 | |-------|----------|--------|--------------|-------------| 65 | | `forward` | | ✅ | `resolveForward` | Used for forwarding the payment on to a different network or different financial institution. The other parameters of the query will vary depending on what kind of institution is the ultimate destinat... | 66 | | `id` | ✓ | ✅ | `resolveStellarAccountId` | returns the federation record of the Stellar address associated with the given account ID. In some cases this is ambiguous. For instance if an anchor sends transactions on behalf of its users the acco... | 67 | | `name` | ✓ | ✅ | `resolveStellarAddress` | returns the federation record for the given Stellar address. | 68 | | `txid` | | ✅ | `resolveStellarTransactionId` | returns the federation record of the sender of the transaction if known by the server. | 69 | 70 | ### Response Fields 71 | 72 | | Field | Required | Status | SDK Property | Description | 73 | |-------|----------|--------|--------------|-------------| 74 | | `account_id` | ✓ | ✅ | `accountId` | Stellar public key / account ID | 75 | | `memo` | | ✅ | `memo` | value of memo to attach to transaction, for hash this should be base64-encoded. This field should always be of type string (even when memo_type is equal id) to support parsing value in languages that ... | 76 | | `memo_type` | | ✅ | `memoType` | type of memo to attach to transaction, one of text, id or hash | 77 | | `stellar_address` | ✓ | ✅ | `stellarAddress` | stellar address | 78 | 79 | ## Implementation Gaps 80 | 81 | 🎉 **No gaps found!** All fields are implemented. 82 | 83 | ## Recommendations 84 | 85 | ✅ The SDK has full compatibility with SEP-0002! 86 | 87 | ## Legend 88 | 89 | - ✅ **Implemented**: Field is implemented in SDK 90 | - ❌ **Not Implemented**: Field is missing from SDK 91 | - ⚙️ **Server**: Server-side only feature (not applicable to client SDKs) 92 | - ✓ **Required**: Field is required by SEP specification 93 | - (blank) **Optional**: Field is optional 94 | -------------------------------------------------------------------------------- /lib/src/asset_type_credit_alphanum12.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'assets.dart'; 6 | import 'asset_type_credit_alphanum.dart'; 7 | import 'xdr/xdr_account.dart'; 8 | import 'xdr/xdr_asset.dart'; 9 | import 'key_pair.dart'; 10 | import 'util.dart'; 11 | 12 | /// Represents credit assets with 5-12 character asset codes. 13 | /// 14 | /// This asset type is used for assets with longer codes that don't fit in 15 | /// AlphaNum4 (1-4 characters). Common for branded tokens and specific 16 | /// asset identifiers. 17 | /// 18 | /// Asset code requirements: 19 | /// - Length: 5-12 characters (inclusive) 20 | /// - Characters: ASCII 32-127 excluding spaces 21 | /// - Case-sensitive: "LONGCODE" and "longcode" are different 22 | /// - No leading/trailing spaces 23 | /// 24 | /// Common examples: 25 | /// - Domain-based codes: "example.com", "anchor.io" 26 | /// - Descriptive names: "GOLDTOKEN", "SHARECLASS" 27 | /// - Versioned assets: "USDC2024", "TOKEN-V2" 28 | /// - Brand identifiers: "ACMECOINS" 29 | /// 30 | /// Creating assets: 31 | /// ```dart 32 | /// // Long asset code 33 | /// Asset longAsset = AssetTypeCreditAlphaNum12( 34 | /// "LONGASSET", 35 | /// "GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX" 36 | /// ); 37 | /// 38 | /// // Domain-based code 39 | /// Asset domainAsset = AssetTypeCreditAlphaNum12( 40 | /// "example.com", 41 | /// "GD5J6HLF5666X4AZLTFTXLY46J5SW7EXRKBLEYPJP33S33MXZGV6CWFN" 42 | /// ); 43 | /// 44 | /// // Maximum length (12 characters) 45 | /// Asset maxLength = AssetTypeCreditAlphaNum12( 46 | /// "TWELVECHARS", 47 | /// issuerId 48 | /// ); 49 | /// ``` 50 | /// 51 | /// Using in operations: 52 | /// ```dart 53 | /// // Create trustline 54 | /// ChangeTrustOperation trustOp = ChangeTrustOperationBuilder( 55 | /// longAsset, 56 | /// "1000000" 57 | /// ).build(); 58 | /// 59 | /// // Make payment 60 | /// PaymentOperation paymentOp = PaymentOperationBuilder( 61 | /// destinationId, 62 | /// longAsset, 63 | /// "50.25" 64 | /// ).build(); 65 | /// ``` 66 | /// 67 | /// Important notes: 68 | /// - Codes 1-4 characters must use [AssetTypeCreditAlphaNum4] instead 69 | /// - Codes < 5 or > 12 characters throw [AssetCodeLengthInvalidException] 70 | /// - Always verify the issuer address before trusting 71 | /// - Asset ordering: AlphaNum4 < AlphaNum12 (matters for liquidity pools) 72 | /// 73 | /// See also: 74 | /// - [AssetTypeCreditAlphaNum4] for codes 1-4 characters 75 | /// - [AssetTypeCreditAlphaNum] for base credit asset functionality 76 | /// - [Asset] for general asset operations 77 | /// - [ChangeTrustOperation] for establishing trustlines 78 | class AssetTypeCreditAlphaNum12 extends AssetTypeCreditAlphaNum { 79 | /// Creates a credit asset with a 5-12 character code. 80 | /// 81 | /// Parameters: 82 | /// - [code] Asset code (5-12 characters, case-sensitive) 83 | /// - [issuerId] Issuer's Stellar account ID (G... address) 84 | /// 85 | /// Throws: 86 | /// - [AssetCodeLengthInvalidException] If code length is not 5-12 characters 87 | /// 88 | /// Example: 89 | /// ```dart 90 | /// Asset longCode = AssetTypeCreditAlphaNum12( 91 | /// "LONGASSET", 92 | /// "GDUKMGUGDZQK6YHYA5Z6AY2G4XDSZPSZ3SW5UN3ARVMO6QSRDWP5YLEX" 93 | /// ); 94 | /// ``` 95 | AssetTypeCreditAlphaNum12(String code, String issuerId) 96 | : super(code, issuerId) { 97 | if (code.length < 5 || code.length > 12) { 98 | throw new AssetCodeLengthInvalidException(); 99 | } 100 | } 101 | 102 | @override 103 | String get type => Asset.TYPE_CREDIT_ALPHANUM12; 104 | 105 | /// Converts this asset to its XDR Asset representation. 106 | /// 107 | /// Returns: XDR Asset for this 12-character credit alphanum asset. 108 | @override 109 | XdrAsset toXdr() { 110 | XdrAsset xdrAsset = XdrAsset(XdrAssetType.ASSET_TYPE_CREDIT_ALPHANUM12); 111 | 112 | XdrAssetAlphaNum12 credit = XdrAssetAlphaNum12( 113 | Util.paddedByteArrayString(mCode, 12), 114 | XdrAccountID(KeyPair.fromAccountId(issuerId).xdrPublicKey)); 115 | xdrAsset.alphaNum12 = credit; 116 | return xdrAsset; 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_auth.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_type.dart'; 6 | import 'xdr_data_io.dart'; 7 | import 'xdr_other.dart'; 8 | import 'xdr_signing.dart'; 9 | 10 | class XdrAuth { 11 | int _unused; 12 | int get unused => this._unused; 13 | set unused(int value) => this._unused = value; 14 | 15 | XdrAuth(this._unused); 16 | 17 | static void encode(XdrDataOutputStream stream, XdrAuth encodedAuth) { 18 | stream.writeInt(encodedAuth.unused); 19 | } 20 | 21 | static XdrAuth decode(XdrDataInputStream stream) { 22 | return XdrAuth(stream.readInt()); 23 | } 24 | } 25 | 26 | class XdrAuthCert { 27 | XdrCurve25519Public _pubkey; 28 | XdrCurve25519Public get pubkey => this._pubkey; 29 | set pubkey(XdrCurve25519Public value) => this._pubkey = value; 30 | 31 | XdrUint64 _expiration; 32 | XdrUint64 get expiration => this._expiration; 33 | set expiration(XdrUint64 value) => this._expiration = value; 34 | 35 | XdrSignature _sig; 36 | XdrSignature get sig => this._sig; 37 | set sig(XdrSignature value) => this._sig = value; 38 | 39 | XdrAuthCert(this._pubkey, this._expiration, this._sig); 40 | 41 | static void encode(XdrDataOutputStream stream, XdrAuthCert encodedAuthCert) { 42 | XdrCurve25519Public.encode(stream, encodedAuthCert.pubkey); 43 | XdrUint64.encode(stream, encodedAuthCert.expiration); 44 | XdrSignature.encode(stream, encodedAuthCert.sig); 45 | } 46 | 47 | static XdrAuthCert decode(XdrDataInputStream stream) { 48 | return XdrAuthCert(XdrCurve25519Public.decode(stream), 49 | XdrUint64.decode(stream), XdrSignature.decode(stream)); 50 | } 51 | } 52 | 53 | class XdrAuthenticatedMessage { 54 | XdrUint32 _v; 55 | XdrUint32 get discriminant => this._v; 56 | set discriminant(XdrUint32 value) => this._v = value; 57 | 58 | XdrAuthenticatedMessageV0? _v0; 59 | XdrAuthenticatedMessageV0? get v0 => this._v0; 60 | set v0(XdrAuthenticatedMessageV0? value) => this._v0 = value; 61 | 62 | XdrAuthenticatedMessage(this._v); 63 | 64 | static void encode(XdrDataOutputStream stream, 65 | XdrAuthenticatedMessage encodedAuthenticatedMessage) { 66 | stream.writeInt(encodedAuthenticatedMessage.discriminant.uint32); 67 | switch (encodedAuthenticatedMessage.discriminant.uint32) { 68 | case 0: 69 | XdrAuthenticatedMessageV0.encode( 70 | stream, encodedAuthenticatedMessage._v0!); 71 | break; 72 | } 73 | } 74 | 75 | static XdrAuthenticatedMessage decode(XdrDataInputStream stream) { 76 | XdrAuthenticatedMessage decodedAuthenticatedMessage = 77 | XdrAuthenticatedMessage(XdrUint32.decode(stream)); 78 | switch (decodedAuthenticatedMessage.discriminant.uint32) { 79 | case 0: 80 | decodedAuthenticatedMessage._v0 = 81 | XdrAuthenticatedMessageV0.decode(stream); 82 | break; 83 | } 84 | return decodedAuthenticatedMessage; 85 | } 86 | } 87 | 88 | class XdrAuthenticatedMessageV0 { 89 | XdrUint64 _sequence; 90 | XdrUint64 get sequence => this._sequence; 91 | set sequence(XdrUint64 value) => this._sequence = value; 92 | 93 | XdrStellarMessage _message; 94 | XdrStellarMessage get message => this._message; 95 | set message(XdrStellarMessage value) => this._message = value; 96 | 97 | XdrHmacSha256Mac _mac; 98 | XdrHmacSha256Mac get mac => this._mac; 99 | set mac(XdrHmacSha256Mac value) => this._mac = value; 100 | 101 | XdrAuthenticatedMessageV0(this._sequence, this._message, this._mac); 102 | 103 | static void encode(XdrDataOutputStream stream, 104 | XdrAuthenticatedMessageV0 encodedAuthenticatedMessageV0) { 105 | XdrUint64.encode(stream, encodedAuthenticatedMessageV0.sequence); 106 | XdrStellarMessage.encode(stream, encodedAuthenticatedMessageV0.message); 107 | XdrHmacSha256Mac.encode(stream, encodedAuthenticatedMessageV0.mac); 108 | } 109 | 110 | static XdrAuthenticatedMessageV0 decode(XdrDataInputStream stream) { 111 | return XdrAuthenticatedMessageV0(XdrUint64.decode(stream), 112 | XdrStellarMessage.decode(stream), XdrHmacSha256Mac.decode(stream)); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /lib/src/xdr/xdr_network.dart: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Stellar Flutter SDK Authors. All rights reserved. 2 | // Use of this source code is governed by a license that can be 3 | // found in the LICENSE file. 4 | 5 | import 'xdr_type.dart'; 6 | import 'xdr_data_io.dart'; 7 | import "dart:typed_data"; 8 | 9 | class XdrNodeID { 10 | XdrNodeID(this._nodeID); 11 | 12 | XdrPublicKey _nodeID; 13 | XdrPublicKey get nodeID => this._nodeID; 14 | set nodeID(XdrPublicKey value) => this._nodeID = value; 15 | 16 | static void encode(XdrDataOutputStream stream, XdrNodeID encodedNodeID) { 17 | XdrPublicKey.encode(stream, encodedNodeID._nodeID); 18 | } 19 | 20 | static XdrNodeID decode(XdrDataInputStream stream) { 21 | return XdrNodeID(XdrPublicKey.decode(stream)); 22 | } 23 | } 24 | 25 | class XdrPeerAddress { 26 | XdrPeerAddress(this._ip, this._port, this._numFailures); 27 | XdrPeerAddressIp _ip; 28 | XdrPeerAddressIp get ip => this._ip; 29 | set ip(XdrPeerAddressIp value) => this._ip = value; 30 | 31 | XdrUint32 _port; 32 | XdrUint32 get port => this._port; 33 | set port(XdrUint32 value) => this._port = value; 34 | 35 | XdrUint32 _numFailures; 36 | XdrUint32 get numFailures => this._numFailures; 37 | set numFailures(XdrUint32 value) => this._numFailures = value; 38 | 39 | static void encode( 40 | XdrDataOutputStream stream, XdrPeerAddress encodedPeerAddress) { 41 | XdrPeerAddressIp.encode(stream, encodedPeerAddress.ip); 42 | XdrUint32.encode(stream, encodedPeerAddress.port); 43 | XdrUint32.encode(stream, encodedPeerAddress.numFailures); 44 | } 45 | 46 | static XdrPeerAddress decode(XdrDataInputStream stream) { 47 | XdrPeerAddressIp ip = XdrPeerAddressIp.decode(stream); 48 | XdrUint32 port = XdrUint32.decode(stream); 49 | XdrUint32 numFailures = XdrUint32.decode(stream); 50 | return XdrPeerAddress(ip, port, numFailures); 51 | } 52 | } 53 | 54 | class XdrPeerAddressIp { 55 | XdrPeerAddressIp(this._type); 56 | XdrIPAddrType _type; 57 | XdrIPAddrType get discriminant => this._type; 58 | set discriminant(XdrIPAddrType value) => this._type = value; 59 | 60 | Uint8List? _ipv4; 61 | Uint8List? get ipv4 => this._ipv4; 62 | set ipv4(Uint8List? value) => this._ipv4 = value; 63 | 64 | Uint8List? _ipv6; 65 | Uint8List? get ipv6 => this._ipv6; 66 | set ipv6(Uint8List? value) => this._ipv6 = value; 67 | 68 | static void encode( 69 | XdrDataOutputStream stream, XdrPeerAddressIp encodedPeerAddressIp) { 70 | stream.writeInt(encodedPeerAddressIp.discriminant.value); 71 | switch (encodedPeerAddressIp.discriminant) { 72 | case XdrIPAddrType.IPv4: 73 | stream.write(encodedPeerAddressIp.ipv4!); 74 | break; 75 | case XdrIPAddrType.IPv6: 76 | stream.write(encodedPeerAddressIp.ipv6!); 77 | break; 78 | } 79 | } 80 | 81 | static XdrPeerAddressIp decode(XdrDataInputStream stream) { 82 | XdrPeerAddressIp decodedPeerAddressIp = 83 | XdrPeerAddressIp(XdrIPAddrType.decode(stream)); 84 | switch (decodedPeerAddressIp.discriminant) { 85 | case XdrIPAddrType.IPv4: 86 | int ipv4size = 4; 87 | decodedPeerAddressIp.ipv4 = stream.readBytes(ipv4size); 88 | break; 89 | case XdrIPAddrType.IPv6: 90 | int ipv6size = 16; 91 | decodedPeerAddressIp.ipv6 = stream.readBytes(ipv6size); 92 | break; 93 | } 94 | return decodedPeerAddressIp; 95 | } 96 | } 97 | 98 | class XdrIPAddrType { 99 | final _value; 100 | const XdrIPAddrType._internal(this._value); 101 | toString() => 'IPAddrType.$_value'; 102 | XdrIPAddrType(this._value); 103 | get value => this._value; 104 | 105 | static const IPv4 = const XdrIPAddrType._internal(0); 106 | static const IPv6 = const XdrIPAddrType._internal(1); 107 | 108 | static XdrIPAddrType decode(XdrDataInputStream stream) { 109 | int value = stream.readInt(); 110 | switch (value) { 111 | case 0: 112 | return IPv4; 113 | case 1: 114 | return IPv6; 115 | default: 116 | throw Exception("Unknown enum value: $value"); 117 | } 118 | } 119 | 120 | static void encode(XdrDataOutputStream stream, XdrIPAddrType value) { 121 | stream.writeInt(value.value); 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /mentions/mentions.md: -------------------------------------------------------------------------------- 1 | ### Mentions 2 | 3 | Thank you, Jeff Lee for providing a great base for this sdk by porting tweetnacl and fixum and by providing the dart sdk in 2018. Your projects helped a lot to start building the stellar flutter sdk as we have it today. 4 | 5 | Thanks to Steven Roose, anicdh and loama for providing code that helped to implement Key Derivation Methods for Stellar Keys (SEP-0005) in this sdk. 6 | 7 | Licences for used code: 8 | 9 | MIT License 10 | 11 | Copyright (c) 2018 Jeff Lee 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | 31 | The MIT License (MIT) 32 | 33 | Copyright (c) 2016 Dartcoin 34 | 35 | Permission is hereby granted, free of charge, to any person obtaining a copy 36 | of this software and associated documentation files (the "Software"), to deal 37 | in the Software without restriction, including without limitation the rights 38 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 39 | copies of the Software, and to permit persons to whom the Software is 40 | furnished to do so, subject to the following conditions: 41 | 42 | The above copyright notice and this permission notice shall be included in all 43 | copies or substantial portions of the Software. 44 | 45 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 46 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 47 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 48 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 49 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 50 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 51 | SOFTWARE. 52 | 53 | Copyright 2018, anicdh. All rights reserved. 54 | Redistribution and use in source and binary forms, with or without 55 | modification, are permitted provided that the following conditions are 56 | met: 57 | 58 | * Redistributions of source code must retain the above copyright 59 | notice, this list of conditions and the following disclaimer. 60 | * Redistributions in binary form must reproduce the above 61 | copyright notice, this list of conditions and the following 62 | disclaimer in the documentation and/or other materials provided 63 | with the distribution. 64 | * Neither the name of Google Inc. nor the names of its 65 | contributors may be used to endorse or promote products derived 66 | from this software without specific prior written permission. 67 | 68 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 69 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 70 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 71 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 72 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 73 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 74 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 75 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 76 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 77 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 78 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 79 | 80 | -------------------------------------------------------------------------------- /documentation/sdk_examples/change_trust.md: -------------------------------------------------------------------------------- 1 | 2 | ### Change trust 3 | 4 | In this example we will create, update, and delete a trustline. For more on trustlines, please refer to the [assets documentation](https://www.stellar.org/developers/learn/concepts/assets.html). 5 | 6 | We will let one account, called trustor, trust another account that is the issuer of a custom token called "ASTRO". Then, we will modify and finally delete the trustline. 7 | 8 | ```dart 9 | // Create two random key pairs, we will need them later for signing. 10 | KeyPair issuerKeypair = KeyPair.random(); 11 | KeyPair trustorKeypair = KeyPair.random(); 12 | 13 | // Account Ids. 14 | String issuerAccountId = issuerKeypair.accountId; 15 | String trustorAccountId = trustorKeypair.accountId; 16 | 17 | // Create trustor account. 18 | await FriendBot.fundTestAccount(trustorAccountId); 19 | 20 | // Load the trustor account so that we can later create the trustline. 21 | AccountResponse trustorAccount = await sdk.accounts.account(trustorAccountId); 22 | 23 | // Create the issuer account. 24 | CreateAccountOperation cao = CreateAccountOperationBuilder(issuerAccountId, "10").build(); 25 | Transaction transaction = TransactionBuilder(trustorAccount) 26 | .addOperation(cao) 27 | .build(); 28 | transaction.sign(trustorKeypair, Network.TESTNET); 29 | SubmitTransactionResponse response = await sdk.submitTransaction(transaction); 30 | 31 | // Creat our custom asset. 32 | String assetCode = "ASTRO"; 33 | Asset astroDollar = AssetTypeCreditAlphaNum12(assetCode, issuerAccountId); 34 | 35 | // Create the trustline. Limit: 10000 ASTRO. 36 | String limit = "10000"; 37 | // Build the operation. 38 | ChangeTrustOperation cto = ChangeTrustOperationBuilder(astroDollar, limit).build(); 39 | // Build the transaction. 40 | transaction = TransactionBuilder(trustorAccount) 41 | .addOperation(cto) 42 | .build(); 43 | // Sign. 44 | transaction.sign(trustorKeypair, Network.TESTNET); 45 | // Submit. 46 | response = await sdk.submitTransaction(transaction); 47 | 48 | // Load the trustor account again to see if the trustline has been created. 49 | trustorAccount = await sdk.accounts.account(trustorAccountId); 50 | 51 | // Check if the trustline exists. 52 | for (Balance balance in trustorAccount.balances) { 53 | if (balance.assetCode == assetCode) { 54 | print("Trustline for " + assetCode + " found. Limit: ${double.parse(balance.limit)}"); 55 | // Trustline for ASTRO found. Limit: 10000.0 56 | break; 57 | } 58 | } 59 | 60 | // Now, let's modify the trustline, change the trust limit to 40000. 61 | limit = "40000"; 62 | 63 | // Build the change trust operation. 64 | cto = ChangeTrustOperationBuilder(astroDollar, limit).build(); 65 | // Build the transaction. 66 | transaction = TransactionBuilder(trustorAccount).addOperation(cto).build(); 67 | // Sign. 68 | transaction.sign(trustorKeypair, Network.TESTNET); 69 | // Submit. 70 | response = await sdk.submitTransaction(transaction); 71 | 72 | // Load the trustor account to see if the trustline has been modified. 73 | trustorAccount = await sdk.accounts.account(trustorAccountId); 74 | 75 | // Check. 76 | for (Balance balance in trustorAccount.balances) { 77 | if (balance.assetCode == assetCode) { 78 | print("Trustline for " + assetCode + " found. Limit: ${double.parse(balance.limit)}"); 79 | // Trustline for ASTRO found. Limit: 40000.0 80 | break; 81 | } 82 | } 83 | 84 | // And now let's delete the trustline. 85 | // To delete it, we must set the trust limit to zero. 86 | limit = "0"; 87 | // Build the operation. 88 | cto = ChangeTrustOperationBuilder(astroDollar, limit).build(); 89 | // Build the transaction. 90 | transaction = TransactionBuilder(trustorAccount).addOperation(cto).build(); 91 | // Sign. 92 | transaction.sign(trustorKeypair, Network.TESTNET); 93 | // Submit. 94 | response = await sdk.submitTransaction(transaction); 95 | 96 | // Load the trustor account again to see if the trustline has been deleted. 97 | trustorAccount = await sdk.accounts.account(trustorAccountId); 98 | 99 | // Check. 100 | bool found = false; 101 | 102 | for (Balance balance in trustorAccount.balances) { 103 | if (balance.assetCode == assetCode) { 104 | found = true; 105 | break; 106 | } 107 | } 108 | 109 | if(!found) { 110 | print("success, trustline deleted"); 111 | } 112 | ``` 113 | --------------------------------------------------------------------------------