Giter Site home page Giter Site logo

functionland / react-native-fula Goto Github PK

View Code? Open in Web Editor NEW
2.0 1.0 4.0 2.74 MB

React (JS/Native) wrapper for go-fula/mobile which creates a bridge between Fula and WNFS for React Native to enable developers create mobile native apps

License: MIT License

Shell 0.03% Java 15.00% JavaScript 0.43% TypeScript 66.44% Swift 14.63% C 0.02% Objective-C 0.46% Ruby 1.12% Objective-C++ 1.88%
fula java mobile-app mobile-development react-native reactjs wrapper-library filesystem javascript webnative

react-native-fula's Introduction

react-native-fula

This package is a bridge to use the Fula protocols in the react-native. It uses WNFS to create the Merkle dag from files and folders and transfer the DAG using Graphsync to the nodes.

Installation

npm install react-native-fula

Usage

import { fula } from 'react-native-fula'; // Until the library becomes stable, we suggest importing from github directly
// Creates a new client without creating a filesystem. It is better to call this instead of directly calling init
const peerId //returns peerId as string
=  newClient(
  identity: string, //privateKey of did identity
  storePath: string, // leave empty to use the default temp one
  bloxAddr: string, //leave empty for testing without a backend node
  exchange: 'noop'|'', //add noop for testing without a backend
  autoFlush: boolean, //Default to false. Always set to false unless you know what you are doing. explicitly write data to disk after each operation if set to true
  useRelay: boolean, //default to true. If true it forces the connection through relay
  refresh: boolean? //forces the fula object to be recreated. default is false
)
//Initialize the fula client, which creates the libp2p connection if newClient is not called before, and creates filesystem. Note that input is not an object e.g. init('','','','noop', false)
[
    peerId, //returns peerId of the created libp2p instance in form of a string of bytes
    cid, //return the root cid of the WNFS merkle DAG in form of a string
    private_ref //return the keys needed to decode hte encrypted WNFS tree in form of a string of object
]
=
await fula.init(
    identity: string, //bytes of the privateKey of did identity in string format
    storePath: string, // leave empty to use the default temp one
    bloxAddr: string, //leave empty for testing without a backend node
    exchange: 'noop'|'', //add noop for testing without a backend
    autoFlush: boolean, //Default to false. Always set to false unless you know what you are doing. explicitly write data to disk after each operation if set to true
    useRelay: boolean, //default to true. If true it forces the connection through relay
    refresh: boolean? //forces the fula object to be recreated. default is false
);
//Creates a Folder
const cid //returns the cid of the new root. Note that on every write action the root cid changes.
=
await fula.mkdir(
    path: string // This is the Fula path to create a folder and always starts with "root/" and should not start or end with a slash e.g "root/pictures"
);
//Write a local file on the device to the Fula tree (upload). It keeps the original file modification date.
const cid //returns the cid of the new root. Note that on every write action the root cid changes.
=
await fula.writeFile(
    fulaTargetFilename: string, //path to the file on the tree. It should include the filename and extension and start from the "root/". e.g. "root/pictures/cat.jpg"
    localFilename: string //path to the local file. e.g the file that needs to be uploaded
);
//// TODO: This needs to be improved by using stream to not overload the memory for large files
//reads a file on fula tree to a local file on the device (download). It is stream so does not affect memory for large files.
const localFilePath //returns the path to the local file and includes the filename
=
await fula.readFile(
    fulaTargetFilename: string, //path to the file on the tree. It should include the filename and extension and start from the "root/". e.g. "root/pictures/cat.jpg"
    localFilename: string //path to the local file. It should include the filename and extension. e.g. "/temp/cat.jpg"
);
//shows all files and folders under the specified path on Fula
const fileList //returns all the files and folders in a string separated by \n
=
await fula.ls(
    path: string, //path to the folder on the tree. It always starts from the "root". e.g. "root" or "root/pictures"
);
//// TODO: This needs to be improved by returning an array of files and folders and in chunks to not overload hte memory for large folders
//removes all files and folders at the specified path on Fula
const cid //returns the cid of the new root. Note that on every write action the root cid changes.
=
await fula.rm(
    path: string, //path to the file or folder on the tree. It always starts from the "root". e.g. "root/pictures" or "root/pictures/cat.jpg"
);
//copies the specified file or folder at sourcePath to the filename at targetPath. the path itself(apart from filename) must exist
const cid //returns the cid of the new root. Note that on every write action the root cid changes.
=
await fula.cp(
    sourcePath: string, //path to the file or folder on the tree. It always starts from the "root". e.g. "root/pictures" or "root/pictures/cat.jpg"
    targetPath: string, //path to the file or folder on the tree. It always starts from the "root". e.g. "root/pictures2" or "root/pictures2/cat.jpg"
);
//moves the specified file or folder at sourcePath to the filename at targetPath. the path itself(apart from filename) must exist
const cid //returns the cid of the new root. Note that on every write action the root cid changes.
=
await fula.mv(
    sourcePath: string, //path to the file or folder on the tree. It always starts from the "root". e.g. "root/pictures" or "root/pictures/cat.jpg"
    targetPath: string, //path to the file or folder on the tree. It always starts from the "root". e.g. "root/pictures2" or "root/pictures2/cat.jpg"
);
//checks if fula is ready (initialized through newClient or init)
const result //returns true if succesful and false if fails
=
await fula.isReady(
    filesystemCheck: boolean //Default is true. If true it checks if both WNFS and Fula are ready. If false it only checks fula
);
//checks if client can reach server
const result //returns true if it can, and false if it cannot
=
await fula.checkConnection(
    timeout: number? //default to 20. Maximum time in seconds that checkConnection waits before throwing an error
);
//checks if there are any un-synced actions on the client
const result //returns true if there are, and false if everything is synced with server
=
await fula.checkFailedActions(
    retry: boolean //if true, it tries to sync device with server, if not, it only checks
    timeout: number? //default to 20. Maximum time in seconds that checkConnection waits before throwing an error
);
//lists any cids that are failed to be pushed to backend and only exist on client device
const result //returns an array of cids or false if no cid is found
=
await fula.listFailedActions(
    cids: string[] //if [], it returns all failed cids, and if provided, it only return the failed cids that are in the array of cids provided as input
);
//Gives access to the blox for a specific peerId. This call must be made from the authorizer only.
const result //returns true if succesful and false if fails
=
await fula.setAuth(
    peerId: string, //peer ID of the app that needs access to the blox
    allow: boolean, // true to allow and false to remove access
);
//shuts down the fula libp2p and datastore
await fula.shutdown();
//removes all Fula related data and information (Except the encrypted filesystem) at the specified storage local path
const result //returns true if succesful and false if fails
=
await fula.logout(
    identity: string, //bytes of the privateKey of did identity in string format
    storePath: string, // leave empty to use the default temp one
);

Polkadot type creation

You can follow the documentation here: https://polkadot.js.org/docs/api/examples/promise/typegen

Alternatively you do the below on a Linux or WSL inside the react-native-fula folder:

curl -H "Content-Type: application/json" -d "{\"id\":\"1\", \"jsonrpc\":\"2.0\", \"method\": \"state_getMetadata\", \"params\":[]}" https://node3.functionyard.fula.network > edgeware.json

yarn build:polkadot

Testing

Open a cmd or terminal as admin (sudo)

corepack enable

Then cd to the react-native-fula folder (no need for admin, sudo) and run:

yarn install

to run the example app, run:

yarn example android

Roadmap

Please note the following might not be done in order:

  • Initial version with all functions included
  • Add WNFS tree encryption key generation from an input (deterministically)
  • Improve ead function to use a stream. ( 💯 v1 Release here )
  • Connect to backend
  • Connect to Blockchain codes using APIs

Other related libraries

Name Description
WNFS for Android Android build for WNFS rust version
WNFS for iOS iOS build for WNFS rust version
WNFS Build Android .aar for WNFS
Fula Build android .aar file for Fula
Fx Fotos Fx Fotos dApp using react-native-fula

Contributing

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

License

MIT

react-native-fula's People

Contributors

ehsan6sha avatar farhoud avatar ghorbani-m avatar hhio618 avatar matiqorb avatar mehdibalouchi avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

react-native-fula's Issues

fula.connect always returns true

connect method always returns true even if the endpoints (boxAddr) are wrong:

For example at a local environment all these addresses returns true:
Correct address; '/ip4/192.168.0.200/tcp/4002/p2p/PeerId.....'
Wrong: address: '/ip4/192.168.0.201/tcp/4002/p2p/PerrtId....'

fulaInit Error

When I call the fula.Init() more than once in some circumstances I get this error:

[Error: Cannot acquire directory lock on "/data/user/0/land.fx.fotos/files/wnfs". Another process is using this Badger database.: resource temporarily unavailable]

Fula files related methods error

In some situations when playing with Fula files methods(read,write,ls...), I get the errors:

[Error: An Error Occured in Fs.Fs.ls: Cannot find file or directory]
[Error: An Error Occured in Fs.Fs.writeFileStreamFromPath: Cannot find file or directory]

And the solution is to clear the App data to resolve this issue

Improve error handling

In some circumstances causes apps to crash.

Reproduce error:

Try to send a file before connecting to the box

error: cannot find symbol

@functionland/react-native-fula/android/src/main/java/land/fx/fula/FulaModule.java:229: error: cannot find symbol
  public void newClient(String identityString, String storePath, String bloxAddr, string exchange, Promise promise) {
                                                                                  ^
  symbol:   class string
  location: class FulaModule
1 error

Ping the box

Sometimes we just need to check the box connectivity or test the box connection, for now we have to send a file to detect weather the box is available or not.

Connect

Return Connection like js

Module FulaModule requires main queue setup

We need consider this warning when upgrade the react-native package.

Module FulaModule requires main queue setup since it overrides initbut doesn't implementrequiresMainQueueSetup. In a future release React Native will default to initializing all native modules on a background thread unless explicitly opted-out of.

cancel operation

Sometimes We need to cancel an operation middle of execution.
For example, We call the send method to upload a file while Box is not available and then decide to cancel the upload operation.

setAuth method return error

Here I shared the PeeId that I used to call setAuth:

LOG  setAuth {"allow": true, "peerId": "12D3KooWE3mJ7pAK2Q8RZ4CaJAL1mE3jaX6ec3QeNEKdhDFxwj6b"}
LOG  setAuth:  [Error: failed to parse peer ID: selected encoding not supported]

Run fula under a android forgrand service

on android wrap the FULA client inside service
is the better way to run FULA clients this way:

  • the service can run on its own process
  • auto start on boot
  • the service can create and control notification

If you need I can make PR. I have done it on a project like this with a more complicated interface.

clear recent cids

1- clear recent cids must only clear those that are listed to make sure no unnotieced cid is being cleared.

Unable to get a file and store to a specific path

Get an error to receive a file with file path parameter:

file.receive("[cid]", false,"[FilePath]")

Error:

[Error: open /data/user/0/land.fx.fotos/files/fula/received////storage/emulated/0/Android/media/com.whatsapp/WhatsApp/Media/WhatsApp Images/IMG-20220525-WA0038.jpg: no such file or directory]

newClient method error

When I call the newClient method I get this error:

Possible Unhandled Promise Rejection (id: 0):
Error: Cannot convert argument of type class [B
Error: Cannot convert argument of type class [B

The payload is:

 const newClient = await fula.newClient(
        keyPair.secretKey.toString(), //bytes of the privateKey of did identity in string format
        `${deviceUtils.DocumentDirectoryPath}/testconnection`, // leave empty to use the default temp one
        form.address, //This is a multi addr 
        '', 
      )

yarn example ios error

error unsupported Swift architecture
^
:0: error: could not build Objective-C module 'CryptoSwift'

The file receive method overwrite issue

The file.receive method gets the file from the Box and stores it on the phone's storage.
If the file still exists on the phone the file will be overwritten and it causes unwanted manipulation of the user files, and in some circumstances, the user lost the original file.

Reproduce issue

  1. Send a file to the box
  2. Edit the file and save it with the same name
  3. Receive file from the box

Issue: The edited file will be overwritten.

Proposal

The solution could be a temp folder to store the files and then if the app wants will move them to another place.
Also, we can add a method to clear the temp folder.

Memory leak in SharedPreferenceHelper

1- Do not place Android context classes in static fields (static reference to SharedPreferenceHelper which has field context pointing to Context); this is a memory leak

2- Do not place Android context classes in static fields; this is a memory leak

build failed

err:

ERROR npm ERR! code 1
npm ERR! path /home/farhoud/workspace/functionland/react-native-fula
npm ERR! command failed
npm ERR! command sh -c bob build
npm ERR! ℹ Building target commonjs
npm ERR! ℹ Cleaning up previous build at lib/commonjs
npm ERR! ℹ Compiling 6 files in src with babel
npm ERR! ✔ Wrote files to lib/commonjs
npm ERR! ℹ Building target module
npm ERR! ℹ Cleaning up previous build at lib/module
npm ERR! ℹ Compiling 6 files in src with babel
npm ERR! ✔ Wrote files to lib/module
npm ERR! ℹ Building target typescript
npm ERR! ℹ Cleaning up previous build at lib/typescript
npm ERR! ℹ Generating type definitions with tsc
npm ERR! src/protocols/file.ts:50:35 - error TS2345: Argument of type 'FileMeta' is not assignable to parameter of type 'string'.
npm ERR! 
npm ERR! 50   return base64ToObject<FileMeta>(meta);
npm ERR!                                      ~~~~
npm ERR! 
npm ERR! 
npm ERR! Found 1 error in src/protocols/file.ts:50
npm ERR! 
npm ERR! ✖ Failed to build definition files.
npm ERR! bob build

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.