{"id":22072610,"url":"https://github.com/broxus/nekoton_bridge","last_synced_at":"2026-03-03T10:05:30.478Z","repository":{"id":66355174,"uuid":"601093894","full_name":"broxus/nekoton_bridge","owner":"broxus","description":null,"archived":false,"fork":false,"pushed_at":"2026-02-03T18:32:32.000Z","size":4763,"stargazers_count":3,"open_issues_count":2,"forks_count":4,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-02-04T07:50:59.322Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/broxus.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2023-02-13T11:01:32.000Z","updated_at":"2026-02-03T18:38:47.000Z","dependencies_parsed_at":"2025-06-06T15:34:02.858Z","dependency_job_id":"06237310-25b9-46ae-b55e-01b32c52d46f","html_url":"https://github.com/broxus/nekoton_bridge","commit_stats":null,"previous_names":[],"tags_count":385,"template":false,"template_full_name":null,"purl":"pkg:github/broxus/nekoton_bridge","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broxus%2Fnekoton_bridge","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broxus%2Fnekoton_bridge/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broxus%2Fnekoton_bridge/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broxus%2Fnekoton_bridge/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/broxus","download_url":"https://codeload.github.com/broxus/nekoton_bridge/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/broxus%2Fnekoton_bridge/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29084091,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-04T03:31:03.593Z","status":"ssl_error","status_checked_at":"2026-02-04T03:29:50.742Z","response_time":62,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-30T21:13:55.587Z","updated_at":"2026-02-04T12:09:02.462Z","avatar_url":"https://github.com/broxus.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Nekoton bridge for flutter\n\n[![License: AGPLv3][license_badge]][license_link]\n[![Build \u0026 Test](https://github.com/broxus/nekoton_bridge/actions/workflows/build.yml/badge.svg)](https://github.com/broxus/nekoton_bridge/actions/workflows/build.yml)\n\nThis package based on [flutter_rust_bridge](https://cjycode.com/flutter_rust_bridge) generator.\n\n## Gettind Started as user 🚀\n\n### Installation ⚙️\n\nAdd [flutter_nekoton_bridge][pubdev_link] to your `pubspec.yaml`:\n\n```yaml\ndependencies:\n  flutter_nekoton_bridge:\n```\n\n### Logger 🪵\n\nThe first thing you need to do is to setup logger. You can use any logger you want, but we recommend to use [logging](https://pub.dev/packages/logging)-based package. For example, you can check [fancy_logger](https://github.com/broxus/ever_wallet_flutter_new/tree/main/packages/fancy_logger) from Sparx wallet.\n\nTo setup logger you need to call `setupLogger` function from `flutter_nekoton_bridge` package. It's a good idea to provide mapping from `LogLevel` to your logger levels. For example, you can use `LogLevel` from `logger` package:\n\n```dart\n  /// The main log level map\n  static final Map\u003cLevel, fnb.LogLevel?\u003e _logMap = {\n    Level.ALL: fnb.LogLevel.Trace,\n    Level.FINEST: fnb.LogLevel.Trace,\n    Level.FINER: fnb.LogLevel.Trace,\n    Level.FINE: fnb.LogLevel.Debug,\n    Level.CONFIG: fnb.LogLevel.Debug,\n    Level.INFO: fnb.LogLevel.Info,\n    Level.WARNING: fnb.LogLevel.Warn,\n    Level.SEVERE: fnb.LogLevel.Error,\n    Level.SHOUT: fnb.LogLevel.Error,\n    Level.OFF: null,\n  };\n\n  Level _toLogLevel(fnb.LogLevel level) {\n    return _logMap.keys.firstWhere((key) =\u003e _logMap[key] == level);\n  }\n```\n\nThen you can use it in ```_logHandler``` callback:\n\n```dart\n  void _logHandler(fnb.LogEntry logEntry) {\n    final logLevel = _toLogLevel(logEntry.level);\n\n    _log.log(logLevel, '${logEntry.tag}: ${logEntry.msg}');\n  }\n```\n\nAnd finally, you can setup logger in your app using this code:\n\n```dart\n   fnb.setupLogger(\n      level: logLevel,\n      mobileLogger: mobileLogger,\n      logHandler: _logHandler,\n   );\n```\n\nWhere ```level``` is your default log level, ```mobileLogger``` is just a flag that you want to use mobile logger (if you want to use your own logger, you can set it to false) and ```logHandler` is a callback that will be called for each log entry.\n\nPlease note: you should setup logger before any other calls to bridge.\n\n### Bridge initialization 🎬\n\nTo initialize bridge you need to call ```initRustToDartCaller``` function from the package. It will register all callbacks and initialize bridge. You should call it before any other calls to bridge (just call it right after logger setup).\n\n```dart\n  fnb.initRustToDartCaller();\n```\n\nIt's a good idea to check how we do it in Sparx wallet in [NekotonRepository](https://github.com/broxus/ever_wallet_flutter_new/blob/main/packages/nekoton_repository/lib/src/nekoton_repository.dart).\n\n### Bridge usage 📈\n\n#### Fixed point numbers 🔝\n\nWe don't used [Fixed](https://pub.dev/packages/fixed) package in this package because in the most cases we don't have scale digits in our amounts ¯\\_(ツ)_/¯.\n\nBut! We highly recommend to use it package for fixed point numbers in your app because you have to have scale digits in your amounts for correct calculations and representation. So, tt's a good idea to use it in your app!\n\nFixed allows you to store and manipulate fixed point numbers. Fixed point numbers are numbers that have a fixed number of digits after the decimal point. You shouldn't use floating point numbers for financial calculations because they are not precise enough. Using strings 🩼 for storing fixed point is also not a good idea because it's not efficient and can produce bugs due to decimal separator difference (, or .) and can't be used in calculations. Fixed point numbers are precise and can be used for financial calculations.\n\nFor [example](https://fixed.onepub.dev/constructors):\n\n```dart\nFixed.fromInt(1234, scale: 3); // == 1.234\n\nFixed.fromBigInt(BigInt.from(1234), scale: 3); // == 1.234\n\nfinal t1 = Fixed.fromDecimal(Decimal.fromInt(1), scale: 2); // == 1.00\n\nfinal t3 = Fixed.parse('1.234', scale: 2); // == 1.23, scale: 2\n```\n\nPlease note: this is the least desireable method as it can introduce rounding errors:\n\n```dart\nfinal t2 = Fixed.fromNum(1.234, scale: 3); // == 1.234\n```\n\n#### Money 💰\n\nAlso we recommend to use [money2](https://pub.dev/packages/money2) package for money calculations. It's a good idea to use it for all money calculations in your app.\n\nPlease note that due to found [bug](https://github.com/onepub-dev/money.dart/issues/75) we highly recommend to use [money2_improver](https://pub.dev/packages/money2_improver) for parsing amounts from strings. Also this package contains some useful extensions for money2.\n\n## Getting Started as hacker 👨🏻‍💻\n\nYou should start installing the main things:\n* [Flutter](https://docs.flutter.dev/get-started/install)\n* [Rust](https://www.rust-lang.org/learn/get-started)\n\nThen your adventure continues by installing dependencies:\n\n```\ncargo install flutter_rust_bridge_codegen\ncargo install cargo-xcode\nrustup target add \\\n    aarch64-linux-android \\\n    armv7-linux-androideabi \\\n    x86_64-linux-android \\\n    i686-linux-android\ncargo install cargo-ndk --version 2.6.0\nrustup target add aarch64-apple-ios x86_64-apple-ios\nrustup target add aarch64-apple-ios-sim\ndart pub global activate melos\n```\n\nAt this point, all preparations should be completed and we can start compiling the library.\n\n## Melos magic 🪄\n\nUsing [melos](https://melos.invertase.dev/) makes it very easy to work with the project, so enjoy.\n\nYou can run any job interactively run running `melos run` and selecting needed case or directly (e.g. `melos run test`).\n\n### Bootstrap 🏁\n\nMelos takes care about dependencies of all packages, including managing of local-generated library version. So, just run:\n\n```\nmelos bs\n```\n\n## Codegen 🦾\n\nThis thing will run all code generators for all packages:\n\n```\n$ melos run codegen\n```\n\n### Build 🪛\n\nThe library consists of dart files and platform-specific binaries. pub.dev has a hard 100 MB upload limit, so we can't distribute platform-specific (they can be really huge!) this way. So, we should use something like Github releases for distribute it. Commands below will build everything for two platforms:\n\n```\nmelos run build:ios\nmelos run build:android\n\n# or just\nmelos build\n```\n\nYou can find `platform-build/NekotonBridge.xcframework.zip` and `platform-build/android.tar.gz` in case of success. Rust build cache will be in `target/` directory.\n\n### Clean up 🧹\n\nJust run commands below to clean all, including build directories and flutter projects.\n\n```\nmelos clean\n```\n\n## Example 🤡\n\nYou can find dumbest example in `packages/flutter_nekoton_bridge/example`. During build scripts will copy platform-specific binaries from `platform-build/` folder, or download prebuild binaries from github (if you don't build binaries locally).\n\nYou can open the project in Android studio or Visual studio code, or even build and run it using `flutter run`.\n\n### iOS build \n\nDuring build scripts copies platform-specific binaries to `packages/flutter_nekoton_bridge/ios/Frameworks/netokon_bridge*.zip` and unpack it to `packages/flutter_nekoton_bridge/ios/Frameworks/NekotonBridge.xcframework/`. It's a good idea to check this things if something went wrong.\n\n### Android build 🤖\n\nDuring build scripts copies platform-specific binaries to `packages/flutter_nekoton_bridge/android/netokon_bridge.tar.gz` and unpack it to `packages/flutter_nekoton_bridge/android/src/main/jniLibs/`. It's also a good idea to check this things if something went wrong.\n\n## Tests ✔️\n\nYou can run dart, flutter and integration tests: `melos run test:dart`, `melos run test:flutter` or `melos run test:integration`. You can also run all tests at one by running `melos run test`.\n\nYou need to run emulator/simulator to complete `melos run test:integration`\n\n### Disabling flaky tests 💩\n\nYu can disable test or even test group by adding\n\n```dart\nskip: skipBecauseFlaky()\n```\n\nIt detects current OS and skips test depending on FLUTTER_TEST_SKIP_FLAKY_* environment variable that can be set in CI. Currently it supports:\n\n* Android: FLUTTER_TEST_SKIP_FLAKY_ANDROID\n* iOS: FLUTTER_TEST_SKIP_FLAKY_IOS\n\n## Code 📊\n\nYou can run code analysis: `melos run analyze`. It will analyze all dart code, including subpackages.\n\n## Code format 🗃️\n\n`melos run check-format` will check, `melos run format` will fix dart code formatting.\n\n## Rust code format and analysis 🦀\n\n`melos run check-rust` will ckeck and analyze rust code.\n\n## Prepare to commit 🤝🏻\n\n`melos run check-all` will ckeck, analyze and run all tests. In future this thing will be in git pre-comit hook.\n\nYou need to run emulator/simulator to complete this command\n\n## Conventional Commits ❤️\n\n[This magic](https://melos.invertase.dev/guides/automated-releases#versioning) will update version and build our library automatically using commit messages and tags. [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0) is a lightweight convention on top of commit messages.\n\n## Version 🏷️\n\nPackage version control is done by melos. It runs by gh action 'create-release' ```melos version -a --yes```.\n\n\n# HOW to write rust code for nekoton_bridge 🦀\nThe first thing you need understand is because of `frb` ability to generate Dart code correctly only\nfrom single rust file, we must merge all necessary source code into single file.\n\nThanks to `bin/merger.dart` we can write code in separated modules as a usual code written in rust.\nBut here's some nuances you should understand:\n1) All code that should be generated to Dart side must be located inside file with name pattern\n   `*api.rs`, for example, `logger_api.rs` or `models_api.rs`. Code in this files will be merged\n   into `merged.rs` file that is target for `flutter_rust_bridge`.\n2) You don't need to import local crates as `pub`. `frb` can look through local imports itself.\n3) Use `pub` for external structures as described in official doc of `frb`, but in `bin/merger.dart`\n   whole hierarchy of crate will be converted to public if there is at least one pub import in any file.\n4) DO NOT PUT any structures inside `*api.rs` files because it will be copied to `merged.rs` file\nand you will see duplicate. Better to put it inside other files of module and import it inside `*api.rs` file.\n5) USE local imports starting with `crate`: `crate::nekoton_wrapper::...`\n6) If method can throw Error, then it should return `anyhow::Result\u003cT, anyhow::Error\u003e` where T is return type\n   and error can be got by calling `handle_error` function.\n7) If you have problems with implementing `dyn AnyTrait` of nekoton, then you need to make a hack with\n   self-wrapped trait with implemented `UnwindSafe + RefUnwindSafe`, see `UnsignedMessageBoxTrait`\n\n\n[license_badge]: https://img.shields.io/badge/license-AGPLv3-blue.svg\n[license_link]: https://opensource.org/license/agpl-v3/\n[pubdev_link]: https://pub.dev/packages/flutter_nekoton_bridge\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroxus%2Fnekoton_bridge","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbroxus%2Fnekoton_bridge","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbroxus%2Fnekoton_bridge/lists"}