Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

react-native-fula

React Native bridge for the Fula protocols, providing blockchain operations, blox device management, plugin management, and AI interactions via go-fula/mobile.

Architecture

┌─────────────────────────────────────────────────┐
│ React Native App │
├─────────────────────────────────────────────────┤
│ TypeScript API (fula, blockchain, fxblox, fxAi)│
├───────────────────┬─────────────────────────────┤
│ Android (Java) │ iOS (Swift) │
│ FulaModule.java │ FulaModule.swift │
├───────────────────┼─────────────────────────────┤
│ go-fula/mobile │ go-fula/mobile │
│ (JNI via .aar) │ (Fula framework) │
└───────────────────┴─────────────────────────────┘

The library uses React Native's NativeModules bridge. All heavy operations run on background threads (single-threaded executor on Android, DispatchQueue.global on iOS) to avoid blocking the JS thread. Responses are returned as JSON strings from the native layer and parsed into typed objects in TypeScript.

Installation

npm install @functionland/react-native-fula

iOS

cd ios && pod install

Requires iOS 15.0+.

Android

The Android AAR is fetched automatically from JitPack. Make sure your project-level build.gradle (or the library's own repositories block) includes:

maven { url 'https://jitpack.io' }

Requires minSdkVersion 26+, Java 17.

Usage

The library exports four namespaced modules:

import{fula,blockchain,fxblox,fxAi}from'@functionland/react-native-fula';

fula -- Client Lifecycle

Manages the Fula client: initialization, connectivity, and shutdown.

// Register lifecycle listeners for proper cleanup on app background/terminationawaitfula.registerLifecycleListener();// Create a new client and connect to the blox nodeconstpeerId=awaitfula.newClient(identity,// string -- base64 private key of DID identitystorePath,// string -- local store path (empty string for default)bloxAddr,// string -- blox multiaddr (empty string for testing without backend)exchange,// string -- 'noop' for testing, '' for productionautoFlush,// boolean (default: false) -- flush writes to disk after each operationuseRelay,// boolean (default: true) -- force connection through relayrefresh// boolean (default: false) -- force recreate the fula object);// init() is a backward-compatible alias for newClient.// Returns { peerId, rootCid } where rootCid is always "".const{ peerId, rootCid }=awaitfula.init(identity,storePath,bloxAddr,exchange,autoFlush,rootCid,useRelay,refresh);
// Check if fula is initialized (optionally check filesystem too)constready=awaitfula.isReady(filesystemCheck);// default: true// Check if client can reach the bloxconstconnected=awaitfula.checkConnection(timeout);// timeout in seconds, default 20// Ping blox peer (tries direct -> relay -> DHT fallback)constresult=awaitfula.ping(timeout);// default 60s// result: { success: boolean, successes: number, avg_rtt_ms: number, errors: string[] }// Shut down libp2p and datastore (client must be discarded after this)awaitfula.shutdown();// Shut down and clear all local dataconstsuccess=awaitfula.logout(identity,storePath);

blockchain -- On-Chain Operations

All blockchain operations are relayed through the connected blox node. The client must be initialized first via fula.newClient() or fula.init().

Account Management

// Check if account exists on-chainconst{ account, exists }=awaitblockchain.checkAccountExists(account);// Fund an accountconst{ from, to, amount }=awaitblockchain.accountFund(account);// Get current account infoconst{ account }=awaitblockchain.getAccount();// Query asset balanceconst{ amount }=awaitblockchain.assetsBalance(account,assetId,classId);// Transfer tokens to Fula networkconst{ msg, description }=awaitblockchain.transferToFula(amount,wallet,chain);

Pool Management

// List all poolsconst{ pools }=awaitblockchain.listPools();// pools: [{ poolID, creator, poolName, parent, participants, region }]// Join / leave a poolconstjoined=awaitblockchain.joinPool(poolID);constleft=awaitblockchain.leavePool(poolID);// Join / leave with a specific blockchainconstjoined=awaitblockchain.joinPoolWithChain(poolID,chainName);constleft=awaitblockchain.leavePoolWithChain(poolID,chainName);// Cancel a pending join requestconstcancelled=awaitblockchain.cancelPoolJoin(poolID);// List pending join requests for a poolconst{ poolRequests }=awaitblockchain.listPoolJoinRequests(poolID);// poolRequests: [{ poolID, account, voted, positiveVotes, peerID }]

Storage and Replication

// Upload manifest for multiple CIDsconst{ storer, cid, pool_id }=awaitblockchain.batchUploadManifest(cids,poolId,replicationFactor);// Replicate content in poolconstreplicatedCids=awaitblockchain.replicateInPool(cids,account,poolId);// List available replication requestsconstavailable=awaitblockchain.listAvailableReplicationRequests(poolID);

Blox Info

// Get free space on blox deviceconst{ size, avail, used, used_percentage }=awaitblockchain.bloxFreeSpace();

fxblox -- Device and Plugin Management

Hardware commands, diagnostics, and plugin management for blox devices. Commands are sent over libp2p to the connected blox.

Hardware Commands

const{ status, msg }=awaitfxblox.wifiRemoveall();// Remove all saved WiFi connectionsconst{ status, msg }=awaitfxblox.reboot();// Reboot deviceconst{ status, msg }=awaitfxblox.partition();// Partition device storageconst{ status, msg }=awaitfxblox.eraseBlData();// Erase all blox local data

Diagnostics

// Fetch Docker container logsconst{ status, msg }=awaitfxblox.fetchContainerLogs(containerName,tailCount);// Analyze logs for best/target peersconst{ best, target, err }=awaitfxblox.findBestAndTargetInLogs(containerName,tailCount);// Storage informationconst{ folder_path, size }=awaitfxblox.getFolderSize(folderPath);const{ size, storage_max, count, folder_path, version }=awaitfxblox.getDatastoreSize();// Docker image infoconst{ images }=awaitfxblox.getDockerImageBuildDates();// images: [{ container_name, image_name, image_created, image_digest }]// IPFS cluster infoconst{ cluster_peer_id, cluster_peer_name }=awaitfxblox.getClusterInfo();

Plugin Management

// List all available pluginsconst{ plugins }=awaitfxblox.listPlugins();// plugins: [{ name, description, version, usage, rewards, socials, requiredInputs, approved, installed }]// List currently active pluginsconst{ msg, status }=awaitfxblox.listActivePlugins();// Install / uninstall / update a pluginconstinstalled=awaitfxblox.installPlugin(pluginName,params);constuninstalled=awaitfxblox.uninstallPlugin(pluginName);constupdated=awaitfxblox.updatePlugin(pluginName);// Check plugin statusconst{ status }=awaitfxblox.showPluginStatus(pluginName,lines);const{ status, msg }=awaitfxblox.getInstallStatus(pluginName);const{ status, msg }=awaitfxblox.getInstallOutput(pluginName,params);

fxAi -- AI Chat

Interact with AI models running on the blox device. Responses are streamed over libp2p.

// Start a chat session -- returns a stream IDconststreamID=awaitfxAi.chatWithAI(aiModel,userMessage);// Option 1: Collect all chunks into a single responseconstfullResponse=awaitfxAi.fetchChunksUsingIterator(streamID);// Option 2: Stream chunks with callbacksconstcancel=fxAi.streamChunks(streamID,{onChunk: (chunk)=>console.log(chunk),onComplete: ()=>console.log('done'),onError: (err)=>console.error(err),});// Call cancel() to stop listening// Option 3: Get chunks manually one at a timeconstchunk=awaitfxAi.getChatChunk(streamID);

Deprecated / Dead Code

The following methods still exist in the TypeScript layer (src/protocols/blockchain.ts and src/interfaces/fulaNativeModule.ts) but have no native implementation on either Android or iOS. They were removed from native modules when direct chain/polkadot APIs were dropped. Calling them will result in a runtime error:

  • blockchain.createAccount(seed) -- use blox-side account creation instead
  • blockchain.createPool(seed, poolName) -- use blox-side pool creation instead
  • blockchain.votePoolJoinRequest(seed, poolID, account, accept)
  • blockchain.newStoreRequest(seed, poolID, uploader, cid)
  • blockchain.removeReplicationRequest(seed, poolID, cid)
  • blockchain.removeStorer(seed, storer, poolID, cid)
  • blockchain.removeStoredReplication(seed, uploader, poolID, cid)

TODO: Clean up the TypeScript layer to remove these dead methods and their associated types (SeededResponse, PoolCreateResponse, PoolVoteResponse).

Native Dependency Versions

PlatformDependencyVersionSource
Androidcom.github.functionland:fula-build-aarv1.58.2JitPack
iOSFula (go-fula/mobile)~> 1.58.2CocoaPods

Development

Prerequisites

  • Node >= 16
  • Yarn 1.22+
  • For Android: JDK 17, Android SDK with NDK 27.1.12297006
  • For iOS: Xcode with iOS 15.0+ SDK

Setup

# Enable corepack (run as admin/sudo)
corepack enable# Install dependencies
yarn install
# Install iOS pods (macOS only)
yarn example pods

Running the Example App

# Android
yarn example android
# iOS
yarn example ios

Scripts

CommandDescription
yarn installInstall dependencies
yarn example androidRun example app on Android
yarn example iosRun example app on iOS
yarn testRun Jest tests
yarn typecheckTypeScript type checking
yarn lintESLint + Prettier
yarn build:androidBuild Android debug APK
yarn build:iosBuild iOS for simulator

Project Structure

src/
index.tsx # Entry point -- re-exports all modules
interfaces/
fulaNativeModule.ts # NativeModules bridge interface
protocols/
fula.ts # Client lifecycle (init, connect, shutdown)
blockchain.ts # On-chain operations (accounts, pools, storage)
fxblox.ts # Device and plugin management
fx-ai.ts # AI chat streaming
types/
blockchain.ts # Blockchain response types
fxblox.ts # Fxblox response types
android/
src/main/java/land/fx/fula/
FulaModule.java # Android native module
FulaPackage.java # React Native package registration
ThreadUtils.java # Single-threaded executor for background work
ios/
Fula.swift # iOS native module (Swift)
Fula.mm # Objective-C++ bridge declarations
Extensions.swift # String/Data/UInt8 utility extensions
example/ # Example React Native app

Related Libraries

NameDescription
go-fulaCore Fula protocol implementation in Go
fula-build-aarAndroid .aar build of go-fula/mobile
Fx FotosPhoto dApp built with react-native-fula

Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

About

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula for React Native to enable connection between blox and mobile apps

Topics

Resources

Code of conduct

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages