From 38acabe4524006d76ae0552fe48270eb93477633 Mon Sep 17 00:00:00 2001 From: gh-actions Date: Tue, 26 Mar 2024 14:54:02 +0000 Subject: [PATCH] Deploy website - based on 33cab857b31c2896cb5c778b7918c8e5ba49d7cd --- 404.html | 4 ++-- RFCs/document-syncing.html | 4 ++-- RFCs/fula-sec.html | 4 ++-- RFCs/fula-sec/did.html | 4 ++-- RFCs/fula-sec/encryption.html | 4 ++-- RFCs/personal-data-reserve.html | 4 ++-- RFCs/private-network.html | 4 ++-- RFCs/replication.html | 4 ++-- RFCs/rfc-process.html | 4 ++-- api-intro.html | 4 ++-- api/client-instance.html | 4 ++-- api/file-api.html | 4 ++-- api/graph-api.html | 4 ++-- assets/js/{97dabe39.e53fff2c.js => 97dabe39.5371dc50.js} | 2 +- .../{runtime~main.af948529.js => runtime~main.906d6544.js} | 2 +- blockchain/Recipes/Account.html | 4 ++-- blockchain/Recipes/Asset.html | 4 ++-- blockchain/Recipes/Bag.html | 4 ++-- blockchain/Recipes/Bundle.html | 4 ++-- blockchain/Recipes/Challenges.html | 4 ++-- blockchain/Recipes/Claims.html | 4 ++-- blockchain/Recipes/Manifest.html | 4 ++-- blockchain/Recipes/Market.html | 4 ++-- blockchain/Recipes/Pool.html | 4 ++-- blockchain/Services/BuildNode.html | 4 ++-- blockchain/Services/Explorer.html | 4 ++-- blockchain/Services/FulaContractAPI.html | 4 ++-- blockchain/Services/Node.html | 4 ++-- blockchain/Services/NodeAPI.html | 4 ++-- blockchain/Services/ProofEngine.html | 4 ++-- blockchain/Services/RunNode.html | 4 ++-- blockchain/Services/Status.html | 4 ++-- blockchain/blockchain-intro.html | 4 ++-- blockchain/recipes.html | 4 ++-- blockchain/services.html | 4 ++-- blog/archive.html | 4 ++-- components/WorkInProgress.html | 4 ++-- design/encryption.html | 4 ++-- design/test.html | 4 ++-- functionyard.html | 4 ++-- functionyard/add-storage.html | 4 ++-- functionyard/dapps.html | 4 ++-- functionyard/fxblox-app.html | 4 ++-- functionyard/fxblox-hardware-rpi.html | 6 +++--- functionyard/fxblox-hardware.html | 4 ++-- functionyard/fxfotos.html | 4 ++-- functionyard/join.html | 4 ++-- functionyard/metamask.html | 4 ++-- getting-started.html | 4 ++-- getting-started/box-setup.html | 4 ++-- getting-started/fula-client.html | 4 ++-- getting-started/rpi-setup.html | 4 ++-- getting-started/using-samples.html | 4 ++-- index.html | 4 ++-- mvp.html | 4 ++-- mvp/admin-reporting.html | 4 ++-- mvp/box-admin.html | 4 ++-- mvp/forgot-password.html | 4 ++-- mvp/fotos.html | 4 ++-- mvp/fotos/availability.html | 4 ++-- mvp/fotos/backup.html | 4 ++-- mvp/fotos/setup.html | 4 ++-- mvp/fotos/sharing.html | 4 ++-- mvp/my-account.html | 4 ++-- mvp/pools.html | 4 ++-- mvp/pools/storage-provide.html | 4 ++-- mvp/privacy-dashboard.html | 4 ++-- mvp/questions.html | 4 ++-- mvp/technical-questions.html | 4 ++-- mvp/unboxing.html | 4 ++-- reference-api.html | 4 ++-- release/testnet-alpha.html | 4 ++-- whitepaper.html | 4 ++-- work_in_progress.html | 4 ++-- 74 files changed, 147 insertions(+), 147 deletions(-) rename assets/js/{97dabe39.e53fff2c.js => 97dabe39.5371dc50.js} (62%) rename assets/js/{runtime~main.af948529.js => runtime~main.906d6544.js} (99%) diff --git a/404.html b/404.html index bf32863e..f7552e03 100644 --- a/404.html +++ b/404.html @@ -5,13 +5,13 @@ Page Not Found | Functionland - +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

- + \ No newline at end of file diff --git a/RFCs/document-syncing.html b/RFCs/document-syncing.html index 0443a169..ea1f8ddb 100644 --- a/RFCs/document-syncing.html +++ b/RFCs/document-syncing.html @@ -5,13 +5,13 @@ Document Syncing | Functionland - +
Skip to main content

Document Syncing

Summary​

This RFC proposes usage of IPFS-Cluster in conjunction with a Correspondant and Newsroom component to sync files and folders across several devices.

Use Case​

A Box owner would like to sync the meeting notes on their desktop with other meeting participants in real time.

They run a command and provide instructions for other participants to download the document.

Each participant is able to download and edit the meeting notes and see updates from others in real time.

Out of Scope​

  • high-frequency updates to documents which might be encountered with multi-tenancy or recording streaming video

  • data persisted by orbit db or any other dbs

Pre-conditions​

  • each participant's device in the meeting is accessible from the others

    EITHER

    * they have a public static IP

    OR

    * NAT hole punching works AND there are relays available to help establish connectivity

Design Considerations​

IPFS-Cluster​

A properly configured ipfs-cluster provides most of the properties required to implement this use case including.

  • a private network of trusted peers

  • conflict resolution

  • notifying peers of changes

  • efficient transmission of data

  • providing peer pinning status

Conflict Resolution​

IPFS Cluster provides two choices for conflict resolution.

CRDT will be used because:

  • it utilizes 'GossipSub' which will probably be useful for future use cases related to replication.

  • it does not require > 50% of peers to be online in order to operate

  • 'follower' peers might be used in the future to provide 'read-only' access

  • 'trusted peers' might be used in the future to provide access control

  • peers will probably come and go frequently (ie/ someone needs to drop from the meeting)

  • since we have full control over the document store, we can ensure the DAG is shallow (based on limitations of number of files in a directory)

  • less stable / tested conflict resolution can be tolerated for this use case

Design​

Box System Architecture​

The following diagram illustrates how various components on the Box will work together to implement data syncing.

There are two new components introduced:

  • correspondant

  • newsroom

Box System Architecture

Box System Architecture

System Properties​

  • peers should not enter a recursive loop with each other by notifying authors of updates that originated from them

  • each program should be reentrant in the sense that they can be aborted at any point during execution then restarted

    • the shared state will be updated to reflect the latest changes to the file system

Correspondant​

The role of the correspondant is to ensure IPFS-Cluster is pinning the latest files created and updated on the author's file system.

When the root CID of the file system changes it should also unpin the old one so that the garbage collector can remove deleted files.

A watch (with debounce) of the filesystem is used instead of an interval timer for the event loop since it will enable changes to be corresponded immediately without consuming resources unnecessarily.

Correspondant Flow State​

Correspondant Flow Chart Implementation

Correspondant Flow Chart Implementation

Newsroom Flow State​

Newsroom FLow Chart Implementation

Newsroom FLow Chart Implementation

Docker-Compose​

In order to access ipfs-cluster-ctl and ipfs from the command line, the correspondant and newsroom will be bundled in the same image as ipfs-cluster-ctl and IPFS.

A separate service will be defined for:

  • newsroom

  • correspondant

  • IPFS

  • ipfs-cluster-ctl

  • ipfs-cluster-service

The docker setup for the IPFS components can be followed from the IPFS-Cluster documentation.

The IPFS components should be listed as a dependency of the correspondant and newsroom.

Future​

Performance Optimizations​

  • a scheduler might be used to prioritize fula-api latency over syncing

  • since the correspondant knows what file/folder changed, it might rebuild the DAG bottom up instead of top down

  • further research needs to be put into how ipfs get works to see if entire contents of the DAG are copied to /fx or only the parts that change

    • if the former is true, since we know the old DAG, we could walk them both ourselves skipping the CIDs that are the same

    • this may be necessary for handling removal of files anyway

Connectivity Research​

The main goal is to remove the connectivity pre-condition from this use case so it will work from any device over the vast majority of network topologies.

The following issues are related to this:

Possibilities​

Data types​

Although this use case is focused on syncing plaintext (eg/ UTF-8 encoded) files it could also cover other documents that IPFS and IPFS-Cluster handles well out of the box such as photos and video.

Person-person Collaboration​

With the addition of an authentication and ACL layer:

  • two different Box owners could share a document with each other and perform real-time edits on it. They might add a third person as reviewer with read-only access

  • a group of people might create a shared album where certain members have the ability to upload photos and others are only allowed to view them (or vice versa)

- + \ No newline at end of file diff --git a/RFCs/fula-sec.html b/RFCs/fula-sec.html index 4fb02956..85267ef8 100644 --- a/RFCs/fula-sec.html +++ b/RFCs/fula-sec.html @@ -5,13 +5,13 @@ FULA Security Layer | Functionland - +
Skip to main content

FULA Security Layer

Overview​

Authentication and encrypted data storage are the main structural elements for decentralized networks and Web3 applications. By default, IPFS does not encrypt the data persisted to it. This means that if someone has a CID, they can access the data without the author's permission. The fula-sec layer aims to solve this, so that data owners can have full control over how their data is accessed.

The fula-sec layer is broken down into the following fundamental building blocks:

What Security Protocols Implemented​

We aim not only to encrypt the data, but also to verify its valid data and use a key exchange mechanism. The key exchange mechanism remains the DID (Decentrilized Identity) mechanism. In the table below, you can see which algorithm was used for what purpose.

KeywordObjectiveDescription
Ed25519Used to obtain user IdentityEdwards-curve Digital Signature Algorithm(EdDSA)
AESUsed by the client side to encrypt each content. The keys are shared only by authorized audience. The keys are not given to audience in a straightforward manner, of course.Advanced Encryption Standard Algorithm (AES)
JWSJWS includes the Signing option. It has two method sign the payload and verify a signed data. A JSON Web Signature (abbreviated JWS) is an IETF-proposed standard (RFC 7515) for signing arbitrary data.
JWEAn encrypted JWE object for one or multiple DIDs.JSON Web Encryption (JWE) is an IETF standard providing a standardised syntax for the exchange of encrypted data, based on JSON and Base64.
RSARSA involves a public key and a private key. The public key can be known by everyone and is used for encrypting messages. The intention is that messages encrypted with the public key can only be decrypted by using the private key.Rivest–Shamir–Adleman.

Unresolved questions​

  • Content Access Revoke
  • Storing DID document in L3 blockchain

Future possibilities​

  • A box owner can associate multiple peer addresses with a DID.
- + \ No newline at end of file diff --git a/RFCs/fula-sec/did.html b/RFCs/fula-sec/did.html index eae091d5..a7db63b0 100644 --- a/RFCs/fula-sec/did.html +++ b/RFCs/fula-sec/did.html @@ -5,14 +5,14 @@ Decentralized Identity (DID) | Functionland - +
Skip to main content

Decentralized Identity (DID)

Why DID in FULA?​

DID enables agents to assert their identity so that they can establish trust, privacy and security with other agents in the network without a centralized authority.

What is Required?​

Setting up decentralized identity with providers(blockchain/distributed ledger) usually consists of the following elements:

  1. Identity owner: The user who creates their decentralized identity using the identity wallet.
  2. Issuer/Verifier: An entity that issues and verifies identification information. They sign the transaction with their private key.
  3. Blockchain/Distributed Ledger: A decentralized and distributed ledger that provides the mechanism and functions for DID and operation.
  4. DID (Decentralized Identifier): A unique identifier that contains details such as public key, verification information, documents.

Can we achieve creating DID without any providers?​

Yes, but with some flaws. As long as we do not store all operations with DID on a ledger verified by an acceptable number of other nodes, security of the data will be lost. Moreover, data storage in blockchain/distributed ledger mechanism is immutable and permanent, and hence, modification and deletion are not possible. The decentralized identity systems use this mechanism so that no external entity can tamper or modify the data.

How does it work?​

  1. Create DID identity - With Create DID, we will have a DID identity and two secret keys options for backup.

create-did

Create DID identity flow


  1. Recover DID identity - We need a mnemonic or private key to restore identity.

recover-did

Recover DID identity flow

See here for DID reference implementation.

- + \ No newline at end of file diff --git a/RFCs/fula-sec/encryption.html b/RFCs/fula-sec/encryption.html index 979a1ba6..9613fcac 100644 --- a/RFCs/fula-sec/encryption.html +++ b/RFCs/fula-sec/encryption.html @@ -5,13 +5,13 @@ Two-way Encryption Mechanism | Functionland - +
Skip to main content

Two-way Encryption Mechanism

Summary​

There are two scenarios that require encryption

  1. Tagged DID encryption
  2. Asymmetric Encryption - Encrypt the subscriber/audience's public key.

Tagged Encryption​

Encrypt data by adding a DID.

Tagged encryption works according to the following steps:

  1. Each agent must have a generated DID address.

  2. Alice uses a unique symmetric key (sKn) for encrypting each piece of content and each file while streaming to the Box.

  3. After the file has been successfully stored to the IPFS node, it returns the CID for each encrypted file to Alice.

  4. Alice now gives Bob access to the file by issuing him a JWE Doc with BOB`s DID address, symmetric key (sK1) and CID

  5. Bob decrypts the document using his own DID address and then obtains the symmetric key (sK1) to get the file that belongs to Alice. As a result, BOB gets the CID and sends a request to the Box.

  6. Bob decrypts the data with sK1 while streaming it from the Box.

tagged-encryption

Tagged Encryption Sequence Diagram

See here for tagged encryption sample code.

Asymmetric Encryption​

With assymetric encryption, no one needs to share DID identity with others, they just need to know a PubKey.

Asymmetric Encryption works according to the following steps:

  1. First, each application must have a generated DID address and PublicKey.

  2. Alice uses a unique symmetric key (sKn) for encrypting each piece of content and each file while streaming to the Box.

  3. After the file has been successfully stored to the IPFS node, it returns the CID for each encrypted file to Alice.

  4. Alice now gives Bob access to the file by issuing him a JWE Doc with BOB`s PubKey, symmetric key (sK1) and CID.

  5. Bob decrypts the document using his own PrivateKey and then obtains the symmetric key (sK1) to get the file that belongs to Alice. As a result, BOB gets the CID and sends a request to the Box.

  6. Bob decrypts data with sK1 while streaming it from the Box.

Assymetric Encryption Sequence Diagram

Tagged Encryption Sequence Diagram

See here for assymetric encryption sample code.

References​

- + \ No newline at end of file diff --git a/RFCs/personal-data-reserve.html b/RFCs/personal-data-reserve.html index fc2cef17..3c6584e6 100644 --- a/RFCs/personal-data-reserve.html +++ b/RFCs/personal-data-reserve.html @@ -5,13 +5,13 @@ Personal Data Reserve | Functionland - +
Skip to main content

Personal Data Reserve

Summary​

This RFC covers how a Box customer's data can be replicated across a group of Boxes physically separated from each other to help prevent unwanted loss.

Use Case​

A person owns 3-5 Boxes (eg/ one in their home, one at their office and one at a friend's house).

Their basement floods bricking the one located in their home.

They are still able to access all of the data that was uploaded to their bricked home Box from one of their other Boxes or a brand new Box provisioned with factory settings.

The following scenarios are handled:

  • adding a new Box to the reserve

  • removing a Box from the reserve

  • data becomes corrupted on a Box

Terminology​

NameDefinition
reservea group of keepers collaboratively working together to back up a snapshot
snapshota collection of data that represents the entire file system being backed up at a given moment in time
chunka portion of a data set
keepera Box process responsible for backing up a file system to the reserve
retrievera Box process given the task of rebuilding a usable file system from a snapshot
authorthe Box where the backed up data set was created
peera member of the reserve
replication factorhow many keepers a chunk of data is stored on; a greater replication factor means greater resilience
data seta file, directory, or data from a database
warning time windowhow much time should be given to send an alert before an imminent limitation is encountered and a system failure occurs

Pre-conditions​

  • the owner has already authenticated themselves with each Box

  • the fula-api is persisting data to a disk accessible by the keeper

  • each Box is already provisioned with the necessary configuration info required to operate a reserve

Assumptions​

  • each keeper in a reserve can be trusted to not operate maliciously by performing unwanted delete operations

  • the data being backed up is:

    • multimedia files such as photos and video
    • orbit db metadata
    • plain text files for shared configuration data

Out of Scope​

  • high-frequency updates to data sets which might be encountered with multi-tenancy or recording streaming video

  • syncing of data between Boxes so that it is usable on each Box (eg/ CRUD operations on them in real time)

  • conflicts arising from concurrent updates initiated by a user on several different Boxes

  • heuristics used to minimize bandwidth and improve availability

Limitations​

The following limitations may be encountered while operating a reserve:

  • file size
  • number of files in a directory
  • snapshot size
  • number of keepers in a reserve

Configuration​

Configuration data for each peer can be split into local and shared.

Local Configuration​

  • local Box address

  • local public/private key

Shared Configuration​

  • remote Box addresses of other peers in the reserve

  • shared secret

  • minimum acceptable replication factor

  • 'normal' event dispatching frequency

  • warning time window

    • has a global default as well as an override for each limitation

Conflict Resolution​

Although it can be assumed the snapshot is already free from conflicts caused by concurrent updates initiated from a user, conflicts may still arise from disk corruption or other unforseen keeper errors.

The disputing keepers will take the appropriate steps to resolve the conflict. If an appropriate resolution can not be achieved, an event is raised.

Events​

The following events are dispatched for an administrative UI.

  • limitation imminent

  • limitation encountered

  • keeper health

    • memory
    • disk I/O
    • CPU usage
    • disk corruption
  • unresolved conflict

  • unacceptable replication factor

  • keeper added / removed

  • network disruption

Event Types​

  • normal
  • warning
  • failure

Warnings​

Events dispatched before a failure occurs based on a forecasting heuristic to determine how quickly a limit will be reached.

Event Frequency​

Normal events are dispatched periodically (based on a config param) for historical reporting and warnings|failures are dispatched immediately.

Implementation​

Components​

The components that are needed for this use case are:

  • data set keeper

  • data set retriever

  • event dispatcher

  • file integrity monitor

Event Dispatcher​

A mechanism for dispatching events and queueing them to prevent loss if a peer goes down.

File Integrity Monitoring​

For detecting / handling disk corruption.

A full sweep of the file system is periodically done comparing the contents of chunks on disk with a source of truth.

Network Architecture​

A peer-peer architecture is used over master/slave so that if a single Box goes down the rest of the reserve will still be able to operate normally.

  • any shared config data is stored on each Box

  • any shared state required for the retrieval of a data set is stored on each Box

  • no central servers are used for networking

Drawbacks​

Putting the responsibility of data reliability on Box owners means there is potential for a Box owner to make a mistake and permanently lose their data.

Rationale and alternatives​

An alternative could be to use paid services (cloud storage providers) with their own SLAs to take on the responsibility of data reliability.

If participating in a decentralized storage network (DSN), the Box owner could also purchase a mining component to offset their cost.

There are currently a few drawbacks with this:

  • becoming a storage miner requires a significant upfront investment to cover hardware and staking costs

  • a private reserve will always be more efficient since keepers will not have to worry about the overhead of trusting each other

These options are not mutually exclusive. Offering both options (free and paid) could provide the greatest freedom/flexibility for Box owners.

Dependencies​

  • IPFS Cluster

  • private connections

  • authentication

  • retriever

  • keeper

@TODO - provide links to relevant docs

Unresolved questions​

What is an ideal replication factor?

How can resilience be measured? Markov models?

How can contents of an entire filesystem be efficiently compared with a source of truth?

How can system resources and their limits be calculated?

How can NAT hole punching work in a pnet without any relays?

Should data compression be taken into account?

Future Possibilities​

History​

Storing a history snapshots so an owner can go back in time and recover a data set from a previous state. This could help with data loss due to user errors.

Regions​

A person or group of people may have a large number of Boxes and want to set up geographically grouped regions such that if there is a severe network outage, each region will still be able to recover the entire contents of a snapshot.

- + \ No newline at end of file diff --git a/RFCs/private-network.html b/RFCs/private-network.html index 87e656b0..c63bd086 100644 --- a/RFCs/private-network.html +++ b/RFCs/private-network.html @@ -5,7 +5,7 @@ Private Network | Functionland - + @@ -18,7 +18,7 @@ In the Config we should add to support to load config.json in this format:

{
"nodes": [
"/ip4/104.131.131.82/tcp/4001/ipfs/QmaCpDMGvV2BGHeYERUEnRQAwe3N8SzbUtfsmvsqQLuvuJ",
"/dnsaddr/bootstrap.libp2p.io/ipfs/QmNnooDu7bfjPFoTZYxMNLWUQJyrVwtbZg5gBMjTezGAJN",
"/dnsaddr/bootstrap.libp2p.io/ipfs/QmQCU2EcMqAqQPR2i9bChDtGNJchTbq5TbXJJ16u19uLTa"
]
}

Which will be used for creating js-libp2p-bootstrap config.

FULA-client​

In fula-client We have to change pkey to fulaSecret so:

createClient(config?: Partial<Libp2pOptions & constructorOptions>, pKey = undefined): Promise<Fula>

to

createClient(config?: Partial<Libp2pOptions & constructorOptions>, fulaSecret = undefined): Promise<Fula>

and change connect interface to get a list of peerId`s from:

connect: (peerId: string) => Connection

to

 connect: (peerId: [string]) => Connection

We need to change Connection in the way that:

Case Study​

For dogfooding of new changes we can use a copy of react-gallery and change the BoxConfig to get list of comma seperated peerIds and App should change to pass the list of peerId's to fula-client.

Note: if example repo would be outside mono-repo we can just use branch for describing every functionality.

Alternative approaches​

VPN​

Using VPN for creating the private network.

Disadvantage:

- + \ No newline at end of file diff --git a/RFCs/replication.html b/RFCs/replication.html index d3feb02a..35b42cbc 100644 --- a/RFCs/replication.html +++ b/RFCs/replication.html @@ -5,14 +5,14 @@ Replication | Functionland - +
Skip to main content

Replication

Summary

When user set up his box he should join/create a public/private pool. in every pool user will pin their data for High availability and replication. and get fula token for keeping the pinset alive.

Motivation

  • user can mine fula and use app's and other futuers.
  • user can have HA on his/her data.

Guide-level explanation

  • there is node call validator that run's on the box and try to keep the pinset alive.
  • the validator use fula-file-protocol to stream pinned data to functionland/box container which keeping the pools data.
  • the validator can get the proof that the data stored and get to consensus of cluster pinset state.
  • joining to the pool most be base on geolocation.

Reference-level explanation

Drawbacks

Rationale and alternatives

Prior art

Unresolved questions

Future possibilities

- + \ No newline at end of file diff --git a/RFCs/rfc-process.html b/RFCs/rfc-process.html index 98a57238..88f182d8 100644 --- a/RFCs/rfc-process.html +++ b/RFCs/rfc-process.html @@ -5,13 +5,13 @@ Requests for comments (RFCs) | Functionland - +
Skip to main content

Request for comments

What is the RFC process?​

Many changes, including bug fixes and documentation improvements, can be implemented and reviewed via the normal GitHub pull request workflow.

However, some changes though are "substantial", and we ask that these be put through a bit of design process and produce a consensus among community members.

The "RFC" (Request For Comments) process is intended to provide a consistent, controlled path for new features to enter the project, so that all stakeholders and contributors can be confident about the direction the project is evolving in.

When to follow this process​

You should consider using this process if you intend to make "substantial" changes in any Functionland project or the documentation. Here are some examples of things that would benefit from an RFC:

  • A new feature that requires rethinking of something that has already been developed and shipped.
  • A change in the documentation structure in order to enhance readers experience.
  • The introduction of a new idea, concept or convention that is currently not present in Functionland.

The RFC process will help you attract more attention to your proposal, as well as make sure that everybody gets a chance to participate in shaping and polishing your new idea.

About the process​

In short, to get a major feature added to any of Functionland's projects, you would first get the RFC merged into the RFC repo of that project as a markdown file. At that point the RFC is β€˜active’ and may be implemented with the goal of eventual inclusion.

  • Fork the project repository
  • Copy rfcs/template.md to rfcs/0000-my-feature/README.md (where my-feature is descriptive, don't ask for an RFC number yet)
  • Put any accompanying resources (pictures, etc.) in rfcs/0000-my-feature/. You can refer to these in the text.
  • Fill in the RFC. Details matter! Remember: RFCs that lack convincing motivation, fail to demonstrate understanding of the impact of the design, or are disingenuous about the drawbacks or alternatives tend to be poorly received.
  • Submit a pull request. As a pull request, the RFC will receive design feedback from the broader community. The author should be prepared to revise it in response to their feedback.
  • Build consensus and integrate feedback. RFCs that have broad support are much more likely to make progress than those that don't receive any comments.
  • The community will discuss the RFC pull request in the comment thread of the pull request itself as much as possible. Offline discussion will be summarized on the pull request comment thread.
  • RFCs rarely go through this process unchanged, especially as members of the broader community identify alternatives and drawbacks. You can make edits, big and small, to the RFC to clarify or change the design, but make changes as new commits to the pull request, and leave a comment on the pull request explaining your changes. Specifically, do not squash or rebase commits after they are visible on the pull request.
  • At some point, a member will propose a "motion for final comment period" (FCP), along with a disposition for the RFC (merge, close, or postpone).
    • For RFCs with lengthy discussion, the motion to FCP is usually preceded by a summary comment that attempts to map the current state of the discussion including major tradeoffs and/or points of disagreement.
  • The FCP lasts ten (10) calendar days, guaranteeing it remains open for at least five (5) business days. This allows stakeholders the opportunity to submit any final objections before a decision is reached.
  • In most cases the FCP period is quiet, and the RFC is either merged or closed. However, sometimes substantial new arguments or ideas are raised, the FCP is canceled, and the RFC returns to development mode.
- + \ No newline at end of file diff --git a/api-intro.html b/api-intro.html index e04eca86..4e5b7f92 100644 --- a/api-intro.html +++ b/api-intro.html @@ -5,13 +5,13 @@ Fula API | Functionland - +
Skip to main content

Fula API

We designed Fula API to help you (a third-party, open-source developer) build other rich and compelling user experiences.

Want to get your hands dirty right away? Head over to getting started.

If you're the kind of person who likes to read the entire manual before starting the engine, then visit the Fula Reference API.

- + \ No newline at end of file diff --git a/api/client-instance.html b/api/client-instance.html index e006f8c0..293fab0c 100644 --- a/api/client-instance.html +++ b/api/client-instance.html @@ -5,13 +5,13 @@ Client Instance | Functionland - +
Skip to main content

Client Instance

Fula client package provides a method createClient that returns client instance. You can use this object to call File and Data APIs.

The client instance is basically a wrapper around a libp2p node. It abstracts away the protocol layer and makes it easier to communicate over libp2p with Fula's File and Graph protocols.

In addition to File and Data APIs, the client instance provides access to the underlying libp2p node. It also maintains the connection between client and the Box and provides a reconnecting mechanism.

You can find below basic methods for working with the client instance.

Create a new client instance​

You can use the createClient method to create a new client instance.

async createClient(config?, pKey=undefined)

Arguments are:

  • config?: The configuration object that gets passed directly to the underlying libp2p node. See here for more information
  • pkey: The private key used for securing the connection. Fula client is currently using NOISE as the connection encryptor, if you want to change that in config, make sure you provide appropriate arguments.

The method resolves to a Fula instance.

Example:

import {createClient} from '@functionland/fula'
const client = await createClient()

Connect to Box​

In order to use the different APIs provided by the Fula client, you must connect a client instance to a Box app using the connect method.

async connect(serverId)

Arguments are:

  • serverId: The base58 PeerID string provided by Box app or any other libp2p node supporting File and Graph protocols.

Example:

const serverId = '12D3KooWBFCDpMyEmyAAAAY6PiQw2vaM35ChTZ8ZmVUe8GFRMUrt' // copied from box app
await client.connect(serverId)

Close a connection​

You can disconnect an already connected client instance using the close method. This will close the connection and stops the libp2p node.

async close()

Example:

await client.close()

Access to Libp2p node​

As mentioned earlier, the Fula client is a wrapper around a libp2p node abstracting away the protocol layer and providing APIs to communicate over File and Graph protocols. If you want to do more specific configurations, access the libp2p cache, or access other interfaces, you can use the getNode method.

getNode()

This method returns a Libp2p node.

Example:

const libp2pNode = client.getNode()
console.log(libp2pNode.multiaddrs)
// [ <Multiaddr 047f00000106f9ba - /ip4/127.0.0.1/tcp/63930> ]
WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

- + \ No newline at end of file diff --git a/api/file-api.html b/api/file-api.html index 48ee7690..5ee50fe6 100644 --- a/api/file-api.html +++ b/api/file-api.html @@ -5,7 +5,7 @@ File API | Functionland - + @@ -13,7 +13,7 @@
Skip to main content

File API (Object Store)

File API provides an interface-like object store for you to upload files and streams (eg. photos, videos or any type of document) and efficiently retrieve them for use in your web/mobile DApp.

File protocol is based on object stores. When you upload something, a CID is created and returned to you and the file gets stored in an IPFS compatible datastore.

Upload​

SendFile​

sendFile(File) => Promise<FileId>

sendFile will take a File as an argument and return a Promise. If the upload completes successfully, a Promise will return a FileId that is a string representing the CID of uploaded content.

Example​

import {Fula, createClient} from '@functionland/fula';

const fulaClient = await createClient();
await fulaClient.connect(serverId);
...
const selectedFile = document.getElementById('input').files[0];
const id = await fulaClient.sendFile(selectedFile);

sendStreamFile​

sendStreamFile(source, meta) => Promise<FileId>

sendStreamFile will take a source and meta as argument and return a Promise. If upload is done successfully, a Promise will return a FileId that is a string representing the CID of uploaded content. (This is useful when you're working with stream or outside the browser.)

  • source: AsyncIterable<Uint8Array>
  • meta: {name,type,lastModified,size}

Example​

import {Fula, createClient} from '@functionland/fula';

const fulaClient = await createClient();
await fulaClient.connect(serverId);
...
export async function* fileToAsyncItrable(file:File) {
const reader = (file.stream()).getReader();
while (true) {
const {value, done} = await reader.read();
if (done) {
break;
}
yield value;
}
}
const selectedFile = document.getElementById('input').files[0];
const id = await fulaClient.sendStreamFile(fileToAsyncItrable(selectedFile),
{
name: selectedFile.name,
type: selectedFile.type,
size: selectedFile.size,
lastModified: selectedFile.lastModified
});

Download​

receiveFile​

(fileId: FileId) => Promise<File>

receiveFile will take FileId and return Promise. if file retrieved successfully Promise return a File

  • fileId: FileId

Example​

import {Fula, createClient} from '@functionland/fula';

const fulaClient = await createClient();
await fulaClient.connect(serverId);
...
const data = await fulaClient.receiveFile(fileId);

receiveMeta​

(fileId: FileId) => Promise<Meta>

receiveMeta will take FileId and return Promise. if meta for the file retrieved successfully Promise return a Meta

  • fileId: FileId

Example​

import {Fula, createClient} from '@functionland/fula';

const fulaClient = await createClient();
await fulaClient.connect(serverId);
...
const {name, type, size, lastModified} = await fulaClient.receiveMeta(fileId);

receiveStreamFile​

(fileId: FileId) => Promise<{ source: AsyncIterable<Uint8Array>, meta: Meta }>

receiveStreamFile will take FileId and return a Promise. If the FileId exists, a Promise will return a { source: AsyncIterable<Uint8Array>, meta: Meta }

That source is a stream of content of the file and Meta is the Meta. (This is useful when you're working with a stream or outside of the browser.)

  • fileId: FileId

Example​

import {Fula, createClient} from '@functionland/fula';

const fulaClient = await createClient();
await fulaClient.connect(serverId);
...
const {source, meta} = await fulaClient.receiveStreamFile(fileId);
const {name, type, size, lastModified} = meta;
const content: Array<Uint8Array> = [];
for await (const chunk of source) {
content.push(Uint8Array.from(chunk));
}
const blob = new Blob(content, {type})


WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

- + \ No newline at end of file diff --git a/api/graph-api.html b/api/graph-api.html index 1384b045..b298c8f8 100644 --- a/api/graph-api.html +++ b/api/graph-api.html @@ -5,7 +5,7 @@ Graph API | Functionland - + @@ -27,7 +27,7 @@ takes an array of filters.

Example​

This example demonstrates the filter use:

filter: {
and: [
{name: {nin: ["keyvan", "mahdi"]}},
{
or: [
{age: {gt: 45}},
{age: {lt: 15}}
]
}
]
}

Subscription​

Fula client's Graph API provides subscription for queries. You can subscribe to a query's result and get the new result on each change using the graphqlSubscription method.

async function* graphqlSubscribe(query: string, variableValues?: never, operationName?: string)

The interface is almost identical to the graphql method, except that graphqlSubscribe returns an AsyncIterable.

Arguments are:

The method returns an AsyncIterable that generates a new result based on query filters every time the collection is changed.

Example​

const readQuery = `
query {
read(input:{
collection:"profile",
filter:{
age: {gt: 50}
}
}){
id
name
age
}
}
`;

const resultIterator = client.graphqlSubscribe(readQuery)

for await (const res of resultIterator){
console.log(res)
}

WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

- + \ No newline at end of file diff --git a/assets/js/97dabe39.e53fff2c.js b/assets/js/97dabe39.5371dc50.js similarity index 62% rename from assets/js/97dabe39.e53fff2c.js rename to assets/js/97dabe39.5371dc50.js index 8fbfe9b1..7b6ef18f 100644 --- a/assets/js/97dabe39.e53fff2c.js +++ b/assets/js/97dabe39.5371dc50.js @@ -1 +1 @@ -"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7746],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>c});var n=a(7294);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var p=n.createContext({}),s=function(e){var t=n.useContext(p),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=s(e.components);return n.createElement(p.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,i=e.mdxType,r=e.originalType,p=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=s(a),c=i,h=u["".concat(p,".").concat(c)]||u[c]||m[c]||r;return a?n.createElement(h,o(o({ref:t},d),{},{components:a})):n.createElement(h,o({ref:t},d))}));function c(e,t){var a=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=a.length,o=new Array(r);o[0]=u;var l={};for(var p in t)hasOwnProperty.call(t,p)&&(l[p]=t[p]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var s=2;s{a.r(t),a.d(t,{contentTitle:()=>o,default:()=>d,frontMatter:()=>r,metadata:()=>l,toc:()=>p});var n=a(7462),i=(a(7294),a(3905));const r={title:"FxBlox Lite (CM4)",id:"fxblox-hardware-rpi"},o=void 0,l={unversionedId:"functionyard/fxblox-hardware-rpi",id:"functionyard/fxblox-hardware-rpi",title:"FxBlox Lite (CM4)",description:"Updating Your FxBlox Lite (RPI)",source:"@site/docs/functionyard/fxblox-hardware-rpi.md",sourceDirName:"functionyard",slug:"/functionyard/fxblox-hardware-rpi",permalink:"/functionyard/fxblox-hardware-rpi",tags:[],version:"current",frontMatter:{title:"FxBlox Lite (CM4)",id:"fxblox-hardware-rpi"},sidebar:"tutorialSidebar",previous:{title:"Functionyard",permalink:"/functionyard/"},next:{title:"FxBlox Lite Plus (RK1)",permalink:"/functionyard/fxblox-hardware"}},p=[{value:"Updating Your FxBlox Lite (RPI)",id:"updating-your-fxblox-lite-rpi",children:[{value:"Step 1: Download the firmware",id:"step-1-download-the-firmware",children:[],level:3},{value:"Step 2: Unzip and Write image to USB",id:"step-2-unzip-and-write-image-to-usb",children:[],level:3},{value:"Step 3: Updating FxBlox",id:"step-3-updating-fxblox",children:[],level:3},{value:"Step 4: Post-Update",id:"step-4-post-update",children:[],level:3}],level:2},{value:"First Time Setup",id:"first-time-setup",children:[{value:"Troubleshoot",id:"troubleshoot",children:[],level:3}],level:2}],s={toc:p};function d(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"updating-your-fxblox-lite-rpi"},"Updating Your FxBlox Lite (RPI)"),(0,i.kt)("div",{className:"admonition admonition-warning alert alert--danger"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))),"warning")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"If you were helping test nightly firmware releases ",(0,i.kt)("strong",{parentName:"p"},"before")," official testnet launch, you will be required to format drive to clear out old/incompatible chain data. ",(0,i.kt)("strong",{parentName:"p"},"See more ",(0,i.kt)("a",{parentName:"strong",href:"/functionyard/fxblox-app/#format-drive"},"details here."))))),(0,i.kt)("h3",{id:"step-1-download-the-firmware"},"Step 1: Download the firmware"),(0,i.kt)("div",{className:"admonition admonition-info alert alert--info"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))),"info")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"If this is your very first time setting up your FxBlox Lite, see these ",(0,i.kt)("a",{parentName:"p",href:"#first-time-setup"},"instructions first")))),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Download"),": Find ",(0,i.kt)("inlineCode",{parentName:"p"},"rpi_update.zip")," in the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/functionland/rk1-image/releases/latest"},"latest release")," under the Assets section on GitHub.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Download: Download ",(0,i.kt)("inlineCode",{parentName:"p"},"Win32 Disk Imager")," for writing update firmware to USB.\n",(0,i.kt)("a",{parentName:"p",href:"https://win32diskimager.org/"},"https://win32diskimager.org/"),"\n"))),(0,i.kt)("h3",{id:"step-2-unzip-and-write-image-to-usb"},"Step 2: Unzip and Write image to USB"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Unzipping"),": Unzip ",(0,i.kt)("inlineCode",{parentName:"p"},"rpi_update.zip")," on your computer. After unzipping there must be a .img file.")),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Writing Image to USB"),": "),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"In Image File section select ",(0,i.kt)("inlineCode",{parentName:"li"},"rpi_update.img")," file."),(0,i.kt)("li",{parentName:"ul"},"In Device section select USB Disk Partion letter."),(0,i.kt)("li",{parentName:"ul"},"Click Write to start flashing USB Disk.")),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("img",{alt:"Win32 Disk Imager",src:a(4558).Z,width:"501",height:"353"})))),(0,i.kt)("h3",{id:"step-3-updating-fxblox"},"Step 3: Updating FxBlox"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"Turn Off"),": Ensure your FxBlox (RPI) Lite is turned off."),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"USB Connection"),": Connect the USB drive to the BOTTOM USB port of the FxBlox Lite (RPI)."),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"Power On"),": Turn on your FxBlox Lite (RPI). After about 30 sec, the LED will blink yellow 5 times that indicating the update process started.",(0,i.kt)("div",{parentName:"li",className:"admonition admonition-warning alert alert--danger"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))),"warning")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"In update process the LED blinks red and green. This phase is very critical, and any mistake in this phase cause breaking FxBlox Lite (RPI). ")))),(0,i.kt)("li",{parentName:"ol"},"After about 10 minutes, the LED blinks red only. Remove the USB drive."),(0,i.kt)("li",{parentName:"ol"},"Restart the FxBlox Lite (RPI) by unplugging and plugging back the power.")),(0,i.kt)("h3",{id:"step-4-post-update"},"Step 4: Post-Update"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Be patient on the first boot, post-update!")," The FxBlox automatically reboots 3 times, and will go through a series of lights. This ",(0,i.kt)("strong",{parentName:"p"},"full process")," should take about ",(0,i.kt)("strong",{parentName:"p"},"30 minutes")," to fully process the update and show the FxBlox WiFi."),(0,i.kt)("p",null,"Please wait for ",(0,i.kt)("inlineCode",{parentName:"p"},"10 minutes")," before doing anything. You may think it is done or stuck or it is turned off, but be sure that it is processing the update for ",(0,i.kt)("inlineCode",{parentName:"p"},"10 minutes")," after the frist boot. We will add LED indicators in the future updates."),(0,i.kt)("div",{className:"admonition admonition-info alert alert--info"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))),"info")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},(0,i.kt)("strong",{parentName:"p"},"Future firmware updates will be automatic, eliminating the need for manual updates.")))),(0,i.kt)("h2",{id:"first-time-setup"},"First Time Setup"),(0,i.kt)("p",null,'If this is your very first time setting up your FxBlox Lite (RPI), you will not be able to install the latest usb update. The reason for that is because "updating via usb" feature was not added in until a later firmware version. '),(0,i.kt)("p",null,"To automatically get that version, you need to connect the Blox to the wifi first. You can do so by following these steps:"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"Download the latest iOS/Android app."),(0,i.kt)("li",{parentName:"ol"},"Follow prompts to create password and connect Metamask."),(0,i.kt)("li",{parentName:"ol"},"If possible, skip format disk. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"Connect Blox to wifi. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"Now, wait 24 hours for the update to install. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"With new version installed, you can proceed with the ",(0,i.kt)("a",{parentName:"li",href:"#step-1-download-the-firmware"},"normal upgrading process."))),(0,i.kt)("h3",{id:"troubleshoot"},"Troubleshoot"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"You may need to wait somewhere between 20-30 seconds for the button to appear."),(0,i.kt)("li",{parentName:"ul"},"You may not get a ",(0,i.kt)("inlineCode",{parentName:"li"},"setup complete")," message afer connecting to wifi, because you don't have the latest firmware version. Check your router settings to see if it connected properly."),(0,i.kt)("li",{parentName:"ul"},"We recommend waiting 24 hours, because there are no indicators for when it is completed.")))}d.isMDXComponent=!0},4558:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/win32DiskImager-470a740c8f557a1dd4e6e0d0ced281eb.png"}}]); \ No newline at end of file +"use strict";(self.webpackChunkdocs=self.webpackChunkdocs||[]).push([[7746],{3905:(e,t,a)=>{a.d(t,{Zo:()=>d,kt:()=>c});var n=a(7294);function i(e,t,a){return t in e?Object.defineProperty(e,t,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[t]=a,e}function r(e,t){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),a.push.apply(a,n)}return a}function o(e){for(var t=1;t=0||(i[a]=e[a]);return i}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(i[a]=e[a])}return i}var s=n.createContext({}),p=function(e){var t=n.useContext(s),a=t;return e&&(a="function"==typeof e?e(t):o(o({},t),e)),a},d=function(e){var t=p(e.components);return n.createElement(s.Provider,{value:t},e.children)},m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},u=n.forwardRef((function(e,t){var a=e.components,i=e.mdxType,r=e.originalType,s=e.parentName,d=l(e,["components","mdxType","originalType","parentName"]),u=p(a),c=i,h=u["".concat(s,".").concat(c)]||u[c]||m[c]||r;return a?n.createElement(h,o(o({ref:t},d),{},{components:a})):n.createElement(h,o({ref:t},d))}));function c(e,t){var a=arguments,i=t&&t.mdxType;if("string"==typeof e||i){var r=a.length,o=new Array(r);o[0]=u;var l={};for(var s in t)hasOwnProperty.call(t,s)&&(l[s]=t[s]);l.originalType=e,l.mdxType="string"==typeof e?e:i,o[1]=l;for(var p=2;p{a.r(t),a.d(t,{contentTitle:()=>o,default:()=>d,frontMatter:()=>r,metadata:()=>l,toc:()=>s});var n=a(7462),i=(a(7294),a(3905));const r={title:"FxBlox Lite (CM4)",id:"fxblox-hardware-rpi"},o=void 0,l={unversionedId:"functionyard/fxblox-hardware-rpi",id:"functionyard/fxblox-hardware-rpi",title:"FxBlox Lite (CM4)",description:"Updating Your FxBlox Lite (RPI)",source:"@site/docs/functionyard/fxblox-hardware-rpi.md",sourceDirName:"functionyard",slug:"/functionyard/fxblox-hardware-rpi",permalink:"/functionyard/fxblox-hardware-rpi",tags:[],version:"current",frontMatter:{title:"FxBlox Lite (CM4)",id:"fxblox-hardware-rpi"},sidebar:"tutorialSidebar",previous:{title:"Functionyard",permalink:"/functionyard/"},next:{title:"FxBlox Lite Plus (RK1)",permalink:"/functionyard/fxblox-hardware"}},s=[{value:"Updating Your FxBlox Lite (RPI)",id:"updating-your-fxblox-lite-rpi",children:[{value:"Step 1: Download the firmware",id:"step-1-download-the-firmware",children:[],level:3},{value:"Step 2: Unzip and Write image to USB",id:"step-2-unzip-and-write-image-to-usb",children:[],level:3},{value:"Step 3: Updating FxBlox",id:"step-3-updating-fxblox",children:[],level:3},{value:"Step 4: Post-Update",id:"step-4-post-update",children:[],level:3}],level:2},{value:"First Time Setup",id:"first-time-setup",children:[{value:"Troubleshoot",id:"troubleshoot",children:[],level:3}],level:2}],p={toc:s};function d(e){let{components:t,...r}=e;return(0,i.kt)("wrapper",(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,i.kt)("h2",{id:"updating-your-fxblox-lite-rpi"},"Updating Your FxBlox Lite (RPI)"),(0,i.kt)("div",{className:"admonition admonition-warning alert alert--danger"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))),"warning")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"If you were helping test nightly firmware releases ",(0,i.kt)("strong",{parentName:"p"},"before")," official testnet launch, you will be required to format drive to clear out old/incompatible chain data. ",(0,i.kt)("strong",{parentName:"p"},"See more ",(0,i.kt)("a",{parentName:"strong",href:"/functionyard/fxblox-app/#format-drive"},"details here."))))),(0,i.kt)("h3",{id:"step-1-download-the-firmware"},"Step 1: Download the firmware"),(0,i.kt)("div",{className:"admonition admonition-info alert alert--info"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))),"info")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"If this is your very first time setting up your FxBlox Lite, see these ",(0,i.kt)("a",{parentName:"p",href:"#first-time-setup"},"instructions first")))),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Download"),": Find ",(0,i.kt)("inlineCode",{parentName:"p"},"rpi_update.zip")," in the ",(0,i.kt)("a",{parentName:"p",href:"https://github.com/functionland/rk1-image/releases/latest"},"latest release")," under the Assets section on GitHub.")),(0,i.kt)("li",{parentName:"ul"},(0,i.kt)("p",{parentName:"li"},"Download: Download ",(0,i.kt)("inlineCode",{parentName:"p"},"Win32 Disk Imager")," for writing update firmware to USB.\n",(0,i.kt)("a",{parentName:"p",href:"https://win32diskimager.org/"},"https://win32diskimager.org/"),"\n"))),(0,i.kt)("h3",{id:"step-2-unzip-and-write-image-to-usb"},"Step 2: Unzip and Write image to USB"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Unzipping"),": Unzip ",(0,i.kt)("inlineCode",{parentName:"p"},"rpi_update.zip")," on your computer. After unzipping there must be a .img file.")),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("p",{parentName:"li"},(0,i.kt)("strong",{parentName:"p"},"Writing Image to USB"),": "),(0,i.kt)("ul",{parentName:"li"},(0,i.kt)("li",{parentName:"ul"},"In Image File section select ",(0,i.kt)("inlineCode",{parentName:"li"},"rpi_update.img")," file."),(0,i.kt)("li",{parentName:"ul"},"In Device section select USB Disk Partion letter."),(0,i.kt)("li",{parentName:"ul"},"Click Write to start flashing USB Disk.")),(0,i.kt)("p",{parentName:"li"},(0,i.kt)("img",{alt:"Win32 Disk Imager",src:a(4558).Z,width:"501",height:"353"})))),(0,i.kt)("h3",{id:"step-3-updating-fxblox"},"Step 3: Updating FxBlox"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"Turn Off"),": Ensure your FxBlox (RPI) Lite is turned off."),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"USB Connection"),": Connect the USB drive to the BOTTOM USB port of the FxBlox Lite (RPI)."),(0,i.kt)("li",{parentName:"ol"},(0,i.kt)("strong",{parentName:"li"},"Power On"),": Turn on your FxBlox Lite (RPI). After about 30 sec, the LED will blink yellow 5 times that indicating the update process started.",(0,i.kt)("div",{parentName:"li",className:"admonition admonition-warning alert alert--danger"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"12",height:"16",viewBox:"0 0 12 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M5.05.31c.81 2.17.41 3.38-.52 4.31C3.55 5.67 1.98 6.45.9 7.98c-1.45 2.05-1.7 6.53 3.53 7.7-2.2-1.16-2.67-4.52-.3-6.61-.61 2.03.53 3.33 1.94 2.86 1.39-.47 2.3.53 2.27 1.67-.02.78-.31 1.44-1.13 1.81 3.42-.59 4.78-3.42 4.78-5.56 0-2.84-2.53-3.22-1.25-5.61-1.52.13-2.03 1.13-1.89 2.75.09 1.08-1.02 1.8-1.86 1.33-.67-.41-.66-1.19-.06-1.78C8.18 5.31 8.68 2.45 5.05.32L5.03.3l.02.01z"}))),"warning")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},"In update process the LED blinks red and green. This phase is very critical, and any mistake in this phase cause breaking FxBlox Lite (RPI). ")))),(0,i.kt)("li",{parentName:"ol"},"After about 10 minutes, the LED blinks red only. Remove the USB drive."),(0,i.kt)("li",{parentName:"ol"},"Restart the FxBlox Lite (RPI) by unplugging and plugging back the power (Make sure an external storage, without the img files, is plugged to the bottom port of blox before powering it back on or the sequence of lighting you would see might defer from this documentation). The best partitioning format for storage devices is ",(0,i.kt)("inlineCode",{parentName:"li"},"ext4")," but ",(0,i.kt)("inlineCode",{parentName:"li"},"vfat")," is also acceptable.")),(0,i.kt)("h3",{id:"step-4-post-update"},"Step 4: Post-Update"),(0,i.kt)("p",null,(0,i.kt)("strong",{parentName:"p"},"Be patient on the first boot, post-update!")," The FxBlox automatically reboots 3 times, and will go through a series of lights. This ",(0,i.kt)("strong",{parentName:"p"},"full process")," should take about ",(0,i.kt)("strong",{parentName:"p"},"30 minutes")," to fully process the update and show the ",(0,i.kt)("inlineCode",{parentName:"p"},"FxBlox")," WiFi."),(0,i.kt)("p",null,"Please wait for ",(0,i.kt)("inlineCode",{parentName:"p"},"10-30 minutes")," before doing anything. You may think it is done or stuck or it is turned off, but be sure that it is processing the update for ",(0,i.kt)("inlineCode",{parentName:"p"},"10-30 minutes")," after the frist boot. At the end of process the LED starts blinking light blue (cyan) consistently if an external storage is plugged to the blox. If no external storage is plugged, then you cannot see this sequence."),(0,i.kt)("div",{className:"admonition admonition-info alert alert--info"},(0,i.kt)("div",{parentName:"div",className:"admonition-heading"},(0,i.kt)("h5",{parentName:"div"},(0,i.kt)("span",{parentName:"h5",className:"admonition-icon"},(0,i.kt)("svg",{parentName:"span",xmlns:"http://www.w3.org/2000/svg",width:"14",height:"16",viewBox:"0 0 14 16"},(0,i.kt)("path",{parentName:"svg",fillRule:"evenodd",d:"M7 2.3c3.14 0 5.7 2.56 5.7 5.7s-2.56 5.7-5.7 5.7A5.71 5.71 0 0 1 1.3 8c0-3.14 2.56-5.7 5.7-5.7zM7 1C3.14 1 0 4.14 0 8s3.14 7 7 7 7-3.14 7-7-3.14-7-7-7zm1 3H6v5h2V4zm0 6H6v2h2v-2z"}))),"info")),(0,i.kt)("div",{parentName:"div",className:"admonition-content"},(0,i.kt)("p",{parentName:"div"},(0,i.kt)("strong",{parentName:"p"},"Future firmware updates will be automatic, eliminating the need for manual updates.")))),(0,i.kt)("h2",{id:"first-time-setup"},"First Time Setup"),(0,i.kt)("p",null,'If this is your very first time setting up your FxBlox Lite (RPI), you will not be able to install the latest usb update. The reason for that is because "updating via usb" feature was not added in until a later firmware version. '),(0,i.kt)("p",null,"To automatically get that version, you need to connect the Blox to the wifi first. You can do so by following these steps:"),(0,i.kt)("ol",null,(0,i.kt)("li",{parentName:"ol"},"Download the latest iOS/Android app."),(0,i.kt)("li",{parentName:"ol"},"Follow prompts to create password and connect Metamask."),(0,i.kt)("li",{parentName:"ol"},"If possible, skip format disk. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"Connect Blox to wifi. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"Now, wait 24 hours for the update to install. ",(0,i.kt)("a",{parentName:"li",href:"#troubleshoot"},(0,i.kt)("strong",{parentName:"a"}," * "))),(0,i.kt)("li",{parentName:"ol"},"With new version installed, you can proceed with the ",(0,i.kt)("a",{parentName:"li",href:"#step-1-download-the-firmware"},"normal upgrading process."))),(0,i.kt)("h3",{id:"troubleshoot"},"Troubleshoot"),(0,i.kt)("ul",null,(0,i.kt)("li",{parentName:"ul"},"You may need to wait somewhere between 20-30 seconds for the button to appear."),(0,i.kt)("li",{parentName:"ul"},"You may not get a ",(0,i.kt)("inlineCode",{parentName:"li"},"setup complete")," message afer connecting to wifi, because you don't have the latest firmware version. Check your router settings to see if it connected properly."),(0,i.kt)("li",{parentName:"ul"},"We recommend waiting 24 hours, because there are no indicators for when it is completed.")))}d.isMDXComponent=!0},4558:(e,t,a)=>{a.d(t,{Z:()=>n});const n=a.p+"assets/images/win32DiskImager-470a740c8f557a1dd4e6e0d0ced281eb.png"}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.af948529.js b/assets/js/runtime~main.906d6544.js similarity index 99% rename from assets/js/runtime~main.af948529.js rename to assets/js/runtime~main.906d6544.js index e40813e1..0c018642 100644 --- a/assets/js/runtime~main.af948529.js +++ b/assets/js/runtime~main.906d6544.js @@ -1 +1 @@ -(()=>{"use strict";var e,a,f,b,c,d={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={id:e,loaded:!1,exports:{}};return d[e].call(f.exports,f,f.exports,r),f.loaded=!0,f.exports}r.m=d,r.c=t,e=[],r.O=(a,f,b,c)=>{if(!f){var d=1/0;for(i=0;i=c)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[f,b,c]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,b){if(1&b&&(e=this(e)),8&b)return e;if("object"==typeof e&&e){if(4&b&&e.__esModule)return e;if(16&b&&"function"==typeof e.then)return e}var c=Object.create(null);r.r(c);var d={};a=a||[null,f({}),f([]),f(f)];for(var t=2&b&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,r.d(c,d),c},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({53:"935f2afb",553:"39968117",710:"4321c919",771:"f19b4864",815:"a98adb27",1082:"665bb1c2",1142:"27873332",1413:"b7a78bd3",1477:"b2f554cd",1564:"c9e48236",1565:"eb64892a",1648:"72fa51da",1752:"01430d47",1919:"1cc0488f",1969:"395b74f0",1973:"ec9cc4dd",1989:"ffb0c1a3",2027:"da49a82e",2217:"1299eea8",2369:"e58963f1",2523:"be614d59",2696:"63c3a5f4",2746:"68453654",2794:"2b0a0def",3300:"17e75398",3334:"48a74962",3557:"b0d6fa48",3608:"9e4087bc",3616:"f7d1f36e",3772:"bc2ced7b",3780:"313672b0",3854:"8a24b94f",4004:"f277957b",4100:"c7806b8e",4205:"952b5e81",4492:"5a04bf5c",4566:"c4cee058",5006:"8ef82ac0",5065:"0ab2a066",5153:"6f0e7e6f",5192:"74636f36",5194:"37866fe0",5213:"32415a15",5326:"831e3b29",5389:"79f59562",5490:"736647ea",5507:"ef6fc643",6208:"7dbfe80c",6235:"ec73ac1d",6358:"7e50ec22",6936:"18f5500a",6938:"f9725412",6950:"e9a5100a",6971:"c377a04b",7118:"f0ae19a0",7162:"d589d3a7",7235:"254fd3a3",7648:"0f3c4d9e",7738:"2a6dab62",7746:"97dabe39",7823:"00e8b4a4",7868:"7ad88a01",7877:"649c7e91",7878:"799a1b22",7918:"17896441",8010:"b48a96ee",8265:"f2d4d1e7",8358:"f3ebba76",8432:"256e3dd8",8489:"b80db04d",8839:"bd78fdc3",8930:"eb9f70f2",9104:"07401f6a",9124:"533b8a8b",9514:"1be78505"}[e]||e)+"."+{53:"c48777e4",553:"2fc350e4",710:"fa9bf934",771:"550109ad",815:"53690edd",1082:"8715b56d",1142:"5aaceec2",1413:"4ab1d864",1477:"c8d67205",1564:"41f33c51",1565:"47fc0fd2",1648:"9929271a",1752:"a9f034fa",1919:"26666b79",1969:"b9af20b7",1973:"7f8a44a2",1989:"6046128c",2027:"40c9df2e",2217:"106f011d",2369:"0bc6ff47",2523:"76ec7f64",2696:"853d0290",2746:"cccdd557",2794:"14c267da",3300:"a64b1917",3334:"23562350",3557:"b94fe364",3608:"afe79f3d",3616:"399b5b88",3772:"8ce58896",3780:"7d871103",3854:"3cf62e6c",4004:"abee8faa",4100:"5d5783da",4205:"8ed02872",4492:"1b65df73",4566:"e5b16854",4608:"edbf3a69",5006:"e5bc3ab0",5065:"fcd18960",5153:"02549f34",5192:"84ff5a20",5194:"80e497bc",5213:"b9978fbe",5326:"e6b73445",5389:"b0fa8dc6",5490:"0fd8e11e",5507:"4ac00692",6208:"e58569e6",6235:"5cb354d3",6358:"8a08ab64",6936:"5767e142",6938:"b47c2931",6950:"694634ee",6971:"9a5244cf",7118:"de4a295b",7162:"e46a01e0",7235:"5a551b43",7648:"51a8acc9",7738:"cb2608c8",7746:"e53fff2c",7823:"732cc844",7868:"f87a36a9",7877:"3b4ed3a0",7878:"3719d371",7918:"4e7c453d",8010:"fcce28aa",8265:"32ec1ac2",8358:"b166dc93",8432:"97248456",8489:"c9da7313",8839:"e440c154",8930:"353aa1bf",9104:"a7df8159",9124:"754c12c9",9514:"1d073e0b"}[e]+".js",r.miniCssF=e=>"assets/css/styles.2682a2a9.css",r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),b={},c="docs:",r.l=(e,a,f,d)=>{if(b[e])b[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(l);var c=b[e];if(delete b[e],t.parentNode&&t.parentNode.removeChild(t),c&&c.forEach((e=>e(f))),a)return a(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=u.bind(null,t.onerror),t.onload=u.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"7918",27873332:"1142",39968117:"553",68453654:"2746","935f2afb":"53","4321c919":"710",f19b4864:"771",a98adb27:"815","665bb1c2":"1082",b7a78bd3:"1413",b2f554cd:"1477",c9e48236:"1564",eb64892a:"1565","72fa51da":"1648","01430d47":"1752","1cc0488f":"1919","395b74f0":"1969",ec9cc4dd:"1973",ffb0c1a3:"1989",da49a82e:"2027","1299eea8":"2217",e58963f1:"2369",be614d59:"2523","63c3a5f4":"2696","2b0a0def":"2794","17e75398":"3300","48a74962":"3334",b0d6fa48:"3557","9e4087bc":"3608",f7d1f36e:"3616",bc2ced7b:"3772","313672b0":"3780","8a24b94f":"3854",f277957b:"4004",c7806b8e:"4100","952b5e81":"4205","5a04bf5c":"4492",c4cee058:"4566","8ef82ac0":"5006","0ab2a066":"5065","6f0e7e6f":"5153","74636f36":"5192","37866fe0":"5194","32415a15":"5213","831e3b29":"5326","79f59562":"5389","736647ea":"5490",ef6fc643:"5507","7dbfe80c":"6208",ec73ac1d:"6235","7e50ec22":"6358","18f5500a":"6936",f9725412:"6938",e9a5100a:"6950",c377a04b:"6971",f0ae19a0:"7118",d589d3a7:"7162","254fd3a3":"7235","0f3c4d9e":"7648","2a6dab62":"7738","97dabe39":"7746","00e8b4a4":"7823","7ad88a01":"7868","649c7e91":"7877","799a1b22":"7878",b48a96ee:"8010",f2d4d1e7:"8265",f3ebba76:"8358","256e3dd8":"8432",b80db04d:"8489",bd78fdc3:"8839",eb9f70f2:"8930","07401f6a":"9104","533b8a8b":"9124","1be78505":"9514"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,f)=>{var b=r.o(e,a)?e[a]:void 0;if(0!==b)if(b)f.push(b[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((f,c)=>b=e[a]=[f,c]));f.push(b[2]=c);var d=r.p+r.u(a),t=new Error;r.l(d,(f=>{if(r.o(e,a)&&(0!==(b=e[a])&&(e[a]=void 0),b)){var c=f&&("load"===f.type?"missing":f.type),d=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+c+": "+d+")",t.name="ChunkLoadError",t.type=c,t.request=d,b[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var b,c,d=f[0],t=f[1],o=f[2],n=0;if(d.some((a=>0!==e[a]))){for(b in t)r.o(t,b)&&(r.m[b]=t[b]);if(o)var i=o(r)}for(a&&a(f);n{"use strict";var e,a,f,b,c,d={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={id:e,loaded:!1,exports:{}};return d[e].call(f.exports,f,f.exports,r),f.loaded=!0,f.exports}r.m=d,r.c=t,e=[],r.O=(a,f,b,c)=>{if(!f){var d=1/0;for(i=0;i=c)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[f,b,c]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,b){if(1&b&&(e=this(e)),8&b)return e;if("object"==typeof e&&e){if(4&b&&e.__esModule)return e;if(16&b&&"function"==typeof e.then)return e}var c=Object.create(null);r.r(c);var d={};a=a||[null,f({}),f([]),f(f)];for(var t=2&b&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,r.d(c,d),c},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({53:"935f2afb",553:"39968117",710:"4321c919",771:"f19b4864",815:"a98adb27",1082:"665bb1c2",1142:"27873332",1413:"b7a78bd3",1477:"b2f554cd",1564:"c9e48236",1565:"eb64892a",1648:"72fa51da",1752:"01430d47",1919:"1cc0488f",1969:"395b74f0",1973:"ec9cc4dd",1989:"ffb0c1a3",2027:"da49a82e",2217:"1299eea8",2369:"e58963f1",2523:"be614d59",2696:"63c3a5f4",2746:"68453654",2794:"2b0a0def",3300:"17e75398",3334:"48a74962",3557:"b0d6fa48",3608:"9e4087bc",3616:"f7d1f36e",3772:"bc2ced7b",3780:"313672b0",3854:"8a24b94f",4004:"f277957b",4100:"c7806b8e",4205:"952b5e81",4492:"5a04bf5c",4566:"c4cee058",5006:"8ef82ac0",5065:"0ab2a066",5153:"6f0e7e6f",5192:"74636f36",5194:"37866fe0",5213:"32415a15",5326:"831e3b29",5389:"79f59562",5490:"736647ea",5507:"ef6fc643",6208:"7dbfe80c",6235:"ec73ac1d",6358:"7e50ec22",6936:"18f5500a",6938:"f9725412",6950:"e9a5100a",6971:"c377a04b",7118:"f0ae19a0",7162:"d589d3a7",7235:"254fd3a3",7648:"0f3c4d9e",7738:"2a6dab62",7746:"97dabe39",7823:"00e8b4a4",7868:"7ad88a01",7877:"649c7e91",7878:"799a1b22",7918:"17896441",8010:"b48a96ee",8265:"f2d4d1e7",8358:"f3ebba76",8432:"256e3dd8",8489:"b80db04d",8839:"bd78fdc3",8930:"eb9f70f2",9104:"07401f6a",9124:"533b8a8b",9514:"1be78505"}[e]||e)+"."+{53:"c48777e4",553:"2fc350e4",710:"fa9bf934",771:"550109ad",815:"53690edd",1082:"8715b56d",1142:"5aaceec2",1413:"4ab1d864",1477:"c8d67205",1564:"41f33c51",1565:"47fc0fd2",1648:"9929271a",1752:"a9f034fa",1919:"26666b79",1969:"b9af20b7",1973:"7f8a44a2",1989:"6046128c",2027:"40c9df2e",2217:"106f011d",2369:"0bc6ff47",2523:"76ec7f64",2696:"853d0290",2746:"cccdd557",2794:"14c267da",3300:"a64b1917",3334:"23562350",3557:"b94fe364",3608:"afe79f3d",3616:"399b5b88",3772:"8ce58896",3780:"7d871103",3854:"3cf62e6c",4004:"abee8faa",4100:"5d5783da",4205:"8ed02872",4492:"1b65df73",4566:"e5b16854",4608:"edbf3a69",5006:"e5bc3ab0",5065:"fcd18960",5153:"02549f34",5192:"84ff5a20",5194:"80e497bc",5213:"b9978fbe",5326:"e6b73445",5389:"b0fa8dc6",5490:"0fd8e11e",5507:"4ac00692",6208:"e58569e6",6235:"5cb354d3",6358:"8a08ab64",6936:"5767e142",6938:"b47c2931",6950:"694634ee",6971:"9a5244cf",7118:"de4a295b",7162:"e46a01e0",7235:"5a551b43",7648:"51a8acc9",7738:"cb2608c8",7746:"5371dc50",7823:"732cc844",7868:"f87a36a9",7877:"3b4ed3a0",7878:"3719d371",7918:"4e7c453d",8010:"fcce28aa",8265:"32ec1ac2",8358:"b166dc93",8432:"97248456",8489:"c9da7313",8839:"e440c154",8930:"353aa1bf",9104:"a7df8159",9124:"754c12c9",9514:"1d073e0b"}[e]+".js",r.miniCssF=e=>"assets/css/styles.2682a2a9.css",r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),b={},c="docs:",r.l=(e,a,f,d)=>{if(b[e])b[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(l);var c=b[e];if(delete b[e],t.parentNode&&t.parentNode.removeChild(t),c&&c.forEach((e=>e(f))),a)return a(f)},l=setTimeout(u.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=u.bind(null,t.onerror),t.onload=u.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"7918",27873332:"1142",39968117:"553",68453654:"2746","935f2afb":"53","4321c919":"710",f19b4864:"771",a98adb27:"815","665bb1c2":"1082",b7a78bd3:"1413",b2f554cd:"1477",c9e48236:"1564",eb64892a:"1565","72fa51da":"1648","01430d47":"1752","1cc0488f":"1919","395b74f0":"1969",ec9cc4dd:"1973",ffb0c1a3:"1989",da49a82e:"2027","1299eea8":"2217",e58963f1:"2369",be614d59:"2523","63c3a5f4":"2696","2b0a0def":"2794","17e75398":"3300","48a74962":"3334",b0d6fa48:"3557","9e4087bc":"3608",f7d1f36e:"3616",bc2ced7b:"3772","313672b0":"3780","8a24b94f":"3854",f277957b:"4004",c7806b8e:"4100","952b5e81":"4205","5a04bf5c":"4492",c4cee058:"4566","8ef82ac0":"5006","0ab2a066":"5065","6f0e7e6f":"5153","74636f36":"5192","37866fe0":"5194","32415a15":"5213","831e3b29":"5326","79f59562":"5389","736647ea":"5490",ef6fc643:"5507","7dbfe80c":"6208",ec73ac1d:"6235","7e50ec22":"6358","18f5500a":"6936",f9725412:"6938",e9a5100a:"6950",c377a04b:"6971",f0ae19a0:"7118",d589d3a7:"7162","254fd3a3":"7235","0f3c4d9e":"7648","2a6dab62":"7738","97dabe39":"7746","00e8b4a4":"7823","7ad88a01":"7868","649c7e91":"7877","799a1b22":"7878",b48a96ee:"8010",f2d4d1e7:"8265",f3ebba76:"8358","256e3dd8":"8432",b80db04d:"8489",bd78fdc3:"8839",eb9f70f2:"8930","07401f6a":"9104","533b8a8b":"9124","1be78505":"9514"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,f)=>{var b=r.o(e,a)?e[a]:void 0;if(0!==b)if(b)f.push(b[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((f,c)=>b=e[a]=[f,c]));f.push(b[2]=c);var d=r.p+r.u(a),t=new Error;r.l(d,(f=>{if(r.o(e,a)&&(0!==(b=e[a])&&(e[a]=void 0),b)){var c=f&&("load"===f.type?"missing":f.type),d=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+c+": "+d+")",t.name="ChunkLoadError",t.type=c,t.request=d,b[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var b,c,d=f[0],t=f[1],o=f[2],n=0;if(d.some((a=>0!==e[a]))){for(b in t)r.o(t,b)&&(r.m[b]=t[b]);if(o)var i=o(r)}for(a&&a(f);n Account | Functionland - +

Account

Create​

Description:​

This function generates a new SugarFunge key pair to interact with the node.

Steps:​

  1. Call the account/create endpoint.

Expected Output:​

{
"seed": "//074a488cc87418a474b5ac30dbcf979caf2099110af805fa208b1a0c53097fc2",
"account": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b"
}
  • seed: represents the private key of the new account.
  • account: represents the public key of the new account.

Fund​

Description:​

This function funds an account to be able to carry out different operations on the node. By funding an account, that key pair its inserted in the node's keystore.

Previous Steps:​

  1. Create an account

Steps:​

  1. Call the account/fund endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"amount": 750000000000,
"to": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b"
}
  • seed: the seed of the account that would be doing the funding.
  • to: the account address that will be funded.
  • amount: the specific amount to be added to the account.

Expected Output:​

{
"from": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"to": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"amount": 750000000000
}
  • from: the account address that did the funding.
  • to: the account address that was funded.
  • amount: the specific amount that was added to the account.

Exists​

**Description:​

This function checks if the account exists and is active.

Note: This function will return false if the account has not been funded yet

Previous Steps:​

  1. Create an account
  2. Fund an account

Steps:​

  1. Call the account/exists endpoint with the following request body:

Example Input:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • account: the account address that will be checked.

Expected Output:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"exists": true
}
  • account: the checked account address.
  • exists: the account current status.

Seeded​

**Description:**​

This function computes the account from seed.

Previous Steps:​

  1. Create an account

Steps:​

  1. Call the account/seeded endpoint with the following request body:

Example Input:​

{
"seed": "//Alice"
}
  • seed: the seed of the account to be computed.

Expected Output:​

{
"seed": "//Alice",
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • seed: the seed of the account.
  • account: the account address that was computed.

Balance​

Description:​

This function checks the balance of sugar in an account.

Previous Steps:​

  1. Create an account

Steps:​

  1. Call the account/balance endpoint with the following request body:

Example Input:​

{
"account": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b"
}
  • account: the account address that will be checked.

Expected Output:​

{
"amount": 750000000000
}
  • amount: the amount of sugar in that given account.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Asset.html b/blockchain/Recipes/Asset.html index f5380bc4..e2c5182d 100644 --- a/blockchain/Recipes/Asset.html +++ b/blockchain/Recipes/Asset.html @@ -5,13 +5,13 @@ Asset | Functionland - +

Asset

Create Class​

Description:​

This function creates a new class of assets. Classes being a set that includes related assets that have common characteristics.

Previous Steps:​

  1. Create an account
  2. Fund an account

Steps:​

  1. Call the assets/create_class endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"metadata": {
"userdata": "Type 1"
},
"class_id": 1,
"owner": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b"
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier (must be unique).
  • owner: the account address that will have ownership of the class.
  • metadata: additional information about the class.

Expected Output:​

{
"class_id": 1,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • class_id: the class identifier.
  • who: the account address of the class owner.

Class Info​

Description:​

This function returns information about a class.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class

Steps:​

  1. Call the assets/class_info endpoint with the following request body:

Example Input:​

{
"class_id": 1
}
  • class_id: the class identifier.

Expected Output:​

{
"info": {
"class_id": 1,
"owner": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"metadata": {
"userdata": "data"
}
}
}
  • class_id: the class identifier.
  • owner: the account address of the class owner.
  • metadata: additional information about the asset.

Create​

Description:​

This function creates an asset.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class

Steps:​

  1. Call the assets/create endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"account": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1,
"asset_id": 1,
"metadata": {
"userdata": "Type 1"
}
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier (must be unique).
  • account: the account address that will have ownership of the asset.
  • metadata: additional information about the asset.

Expected Output:​

{
"class_id": 1,
"asset_id": 1,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • class_id: the class identifier.
  • asset_id: the asset identifier.
  • who: the account address of the asset owner.

Info​

Description:​

This function returns information about an asset.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset

Steps:​

  1. Call the assets/info endpoint with the following request body:

Example Input:​

{
"class_id": 1,
"asset_id": 1
}
  • class_id: the class identifier.
  • asset_id: the asset identifier.

Expected Output:​

{
"info": {
"class_id": 1,
"asset_id": 1,
"owner": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"metadata": {
"userdata": "data"
}
}
}
  • class_id: the class identifier.
  • asset_id: the asset identifier.
  • owner: the account address of the asset owner.
  • metadata: additional information about the asset.

Update Metadata​

Description:​

This function updates the asset class metadata.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset

Steps:​

  1. Call the assets/update_metadata endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"metadata": {
"userdata": "some new data"
},
"class_id": 1,
"asset_id": 1
}
  • seed: the seed of the account that will pay for the transaction.
  • metadata: the new metadata to be set by this function.
  • class_id: the class identifier.
  • asset_id: the asset identifier.

Expected Output:​

{
"class_id": 1,
"asset_id": 1,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"metadata": {
"userdata": "some new data"
}
}
  • class_id: the class identifier.
  • asset_id: the asset identifier.
  • who: the account address that paid for the transaction.
  • metadata: the information updated by the function.

Mint​

Description:​

This function mints an asset by a given amount.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset

Steps:​

  1. Call the assets/mint endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"to": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1
"asset_id": 1,
"amount": 500000
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • to: the account address that will have ownership of the assets.
  • amount: the specific amount of assets to be minted.

Expected Output:​

{
"to": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1,
"asset_id": 1,
"amount": 500000,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address that paid for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • to: the account address that has the ownership of the assets.
  • amount: the specific amount of assets minted.

Burn​

Description:​

This function burns an asset by a given amount.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset

Steps:​

  1. Call the assets/burn endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"from": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1,
"asset_id": 1,
"amount": 4000
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • from: the account address that will burn the assets.
  • amount: the specific amount of assets to be burned.

Expected Output:​

{
"from": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1,
"asset_id": 1,
"amount": 4000,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address that paid for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • from: the account address that burned the assets.
  • amount: the specific amount of assets burned.

Balance​

Description:​

This function checks the balance of an asset in the given account.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset

Steps:​

  1. Call the assets/balance endpoint with the following request body:

Example Input:​

{
"account": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 1,
"asset_id": 1
}
  • class_id: the class identifier
  • asset_id: the asset identifier
  • account: the account address that will be checked.

Expected Output:​

{
"amount": 500000
}
  • amount: the specific amount of assets in the given account.

Transfer​

Description:​

This function transfers a given amount of assets from one account to another.

Previous Steps:​

  1. Create an account
  2. Fund an account
  3. Create a class
  4. Create an asset
  5. Mint an asset

Steps:​

  1. Call the assets/transfer_from endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"from": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"class_id": 1,
"asset_id": 1,
"amount": 50000
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • from: the account address that will send the assets.
  • to: the account address that will receive the assets
  • amount: the specific amount of assets to be sent.

Expected Output:​

{
"from": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"class_id": 1,
"asset_id": 1,
"amount": 50000,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address that paid for the transaction.
  • class_id: the class identifier
  • asset_id: the asset identifier
  • from: the account address that sent the assets.
  • to: the account address that received the assets
  • amount: the specific amount of assets sent.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Bag.html b/blockchain/Recipes/Bag.html index 6ae04b46..2c09f75c 100644 --- a/blockchain/Recipes/Bag.html +++ b/blockchain/Recipes/Bag.html @@ -5,13 +5,13 @@ Bag | Functionland - +

Bag

Register​

Description:​

This function register a bag transaction.

Steps:​

  1. Call the bag/register endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"class_id": 100000,
"metadata": {
"userdata": "somedata"
}
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the new class identifier that the bag will manage.
  • metadata: additional information about the bag.

Expected Output:​

{
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"class_id": 100000
}
  • who: the account address that paid for the transaction.
  • class_id: the class identifier managed by the bag.

Create​

Description:​

This function creates a bag transaction.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Register bag.

Steps:​

  1. Call the bag/create endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"class_id": 100000,
"owners": ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"],
"shares": [1]
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the class identifier that the bag manages.
  • owners: array of account addresses that will be associated with the bag.
  • shares: the amount of share held by the corresponding owners.

Expected Output:​

{
"bag": "5EYCAe5jLQkbmk7kHzj7VNqTGExAEDCjwnnzSh1UEC9N9PgP",
"class_id": 100000,
"asset_id": 0,
"owners": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
]
}
  • owners: array of account addresses associated with the bag.
  • bag: the bag account.
  • class_id: the class identifier that the bag manages.
  • asset_id: the asset identifier that the bag manages.

Deposit​

Description:​

This function creates a new deposit to the bag account.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a class.
  4. Create an asset.
  5. Mint an asset.
  6. Register bag.
  7. Create a bag.

Steps:​

  1. Call the bag/deposit endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"bag": "5EYCAe5jLQkbmk7kHzj7VNqTGExAEDCjwnnzSh1UEC9N9PgP",
"class_ids": [1],
"asset_ids": [[0,1]],
"amounts": [[100,200]]
}
  • seed: the seed of the account that will pay for the transaction.
  • bag: the bag account where the deposit will be made.
  • class_ids: an array of the class identifiers that will be part of the transaction.
  • asset_ids: an array of asset_ids arrays that will be related to each class_id.
  • amounts: an array of amount arrays that will be related to each asset_id.

Expected Output:​

{
"bag": "5EYCAe5jLQkbmk7kHzj7VNqTGExAEDCjwnnzSh1UEC9N9PgP",
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address that paid for the transaction.
  • bag: the bag account.

Sweep​

Description:​

This function sweep the deposits made on an bag account to a given account.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a class.
  4. Create an asset.
  5. Mint an asset.
  6. Register bag.
  7. Create a bag.
  8. Bag deposit.

Steps:​

  1. Call the bag/sweep endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"bag": "5EYCAe5jLQkbmk7kHzj7VNqTGExAEDCjwnnzSh1UEC9N9PgP"
}
  • seed: the seed of the account that will pay for the transaction.
  • bag: the bag account where the deposit were made.
  • to: the receiver account address.

Expected Output:​

{
"bag": "5EYCAe5jLQkbmk7kHzj7VNqTGExAEDCjwnnzSh1UEC9N9PgP",
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address that paid for the transaction.
  • bag: the bag account.
  • to: the receiver account address.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Bundle.html b/blockchain/Recipes/Bundle.html index 2f38f1d8..638d9800 100644 --- a/blockchain/Recipes/Bundle.html +++ b/blockchain/Recipes/Bundle.html @@ -5,13 +5,13 @@ Bundle | Functionland - +

Bundle

Register​

Description:​

This function registers a new bundle schema.

Previous Steps:​

  1. Create a class.
  2. Create an asset.
  3. Mint an asset.

Steps:​

  1. Call the bundle/register endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"class_id": 3,
"asset_id": 0,
"schema": {
"class_ids": [1],
"asset_ids": [
[1]
],
"amounts": [
[5]
]
},
"metadata": {
"userdata": ""
}
}
  • seed: the seed of the account that will pay for the transaction.
  • class_id: the new class identifier that the bundle will manage.
  • asset_id: the new asset identifier that the bundle will manage.
  • schema: this will represent all the classes and assets that need to be present in order to fulfill the other transactions
    • class_ids: an array of the class identifiers that will be part of the schema.
    • asset_ids: an array of asset_ids arrays that will be related to each class_id.
    • amounts: an array of amount arrays that will be related to each asset_id.
  • metadata: additional information about the bundle.

Expected Output:​

{
"bundle_id": "460bf8be553867922d58c434b3e672ffee40d163d4e744d28c1f67f93d0b3a3c",
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"class_id": 3,
"asset_id": 0
}
  • who: the account address associated with the bundle.
  • bundle_id: the bundle identifier.
  • class_id: the class identifier managed by the bundle.
  • asset_id: the asset identifier managed by the bundle.

Mint​

Description:​

This function mints a bundle.

Previous Steps:​

  1. Create an account.
  2. Register a bundle schema.

Steps:​

  1. Call the bundle/mint endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"from": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"bundle_id": "460bf8be553867922d58c434b3e672ffee40d163d4e744d28c1f67f93d0b3a3c",
"amount": 10
}
  • seed: the seed of the account that will pay for the transaction.
  • from: the account address of the sender.
  • to: the account address of the receiver.
  • bundle_id: the bundle identifier.
  • amount: the amount to be minted.

Expected Output:​

{
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"from": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"to": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"bundle_id": "460bf8be553867922d58c434b3e672ffee40d163d4e744d28c1f67f93d0b3a3c",
"amount": 10
}
  • who: the account address that paid for the transaction.
  • from: the account address of the sender.
  • to: the account address of the receiver.
  • bundle_id: the bundle identifier.
  • amount: the amount minted.

Get​

Description:​

Fetches the bundles registered

Previous Steps:​

  1. Create an account.
  2. Register a bundle schema.

Steps:​

  1. Call the bundle endpoint with the following request body:

Example Input:​

{}

Expected Output:​

{
"bundles": [
{
"bundle_id": "460bf8be553867922d58c434b3e672ffee40d163d4e744d28c1f67f93d0b3a3c",
"class_id": 5,
"asset_id": 1
}
]
}
  • bundle: an array with all the bundle registered.

Get Data​

Description:​

Fetches the data of the bundles registered

Previous Steps:​

  1. Create an account.
  2. Register a bundle schema.

Steps:​

  1. Call the bundle/data endpoint with the following request body:

Example Input:​

{}

Expected Output:​

{
"bundles": [
{
"bundle_id": "460bf8be553867922d58c434b3e672ffee40d163d4e744d28c1f67f93d0b3a3c",
"creator": "5EcFZ4EkYFMYcpJWyjgDde4zG8tVvmdanXeSyNTyD42r552b",
"class_id": 5,
"asset_id": 1
"schema": {
"class_ids": [1],
"asset_ids": [
[1]
],
"amounts": [
[5]
]
},
"metadata": {
"userdata": "info"
}
}
]
}
  • bundle: an array with all the bundle registered and its respective data.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Challenges.html b/blockchain/Recipes/Challenges.html index 6cebd5ab..ceb4f48e 100644 --- a/blockchain/Recipes/Challenges.html +++ b/blockchain/Recipes/Challenges.html @@ -5,13 +5,13 @@ Challenges | Functionland - +

Challenges

The Challenges were implemented to improve the security of the proof-engine and the claim of the Fula Tokens. The challenges consist of a series of random proof of storage of a manifest and they are made each cycle in the proof-engine, here:

  • The challenger doesn’t select the file to be challenged, it’s selected randomly between all the CIDs stored on the chain.
  • The challenged users have to send their current stored CIDs since they don’t know which CID is being challenged: These cids are checked with the IPFS information and the values stored on the chain. This promotes the challenged always to have their corresponding CIDs stored, since if it’s not stored in IPFS the challenge tokens for that CID could be lost.

The purpose of the Challenges is to collect Challenge Tokens that depends on the size of the file being challenged, these tokens are differentΒ from the Labor Tokens. The labor tokens are minted by each user in their proof-engine, while the challenge tokens need you to receive a challenge first from another user. In each cycle of the proof-engine the following actions are performed

  • Generate a random challenge to a CID of the chain.
  • Checks if a challenge against him is currently active
    • If thats the case, the challenge is verified and on a successful result the challenge tokens are minted for the challenged account, if failed no challenge tokens are gained this way.

The challenge tokens are going to be used with the labor tokens to transform them into claimed tokens:

  • In a regular case 1 Claimed token = 1 Labor token + 1 Challenge token.
  • In cases where the values minted by the labor tokens differ from the expected amounts each cycle (In case some error or attack is being made to get more tokens than they are supposed), a correction to the proportion will be made.

Generate Challenge​

Description:​

Starts a new random challenge of a CID.

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.

Steps:​

  1. Call the fula/challenge/generate endpoint with the following request body:

Example Input:​

{
"seed": "//Alice"
}
  • seed: the seed of the account challenger.

Example Output:​

{
"challenger": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"challenged": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": "CIDTest1",
"state": "Open"
}
  • challenger: the account of the challenger that made the request.
  • challenged: the selected account of the random challenge.
  • cid: the content identifier associated to the challenge.
  • state: the current state of this challenge (Open as its just been created)

Verify Challenge​

Description:​

Verifies the challenges made to an account and returns the successful and failed ones

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.
  3. Generate a challenge.

Steps:​

  1. Call the fula/challenge/verify endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": 1,
"cids": ["CIDTest1","CIDTest2"],
"class_id": 2000,
"asset_id": 3000
}
  • seed: the seed of the account to verify.
  • cid: an array of the content identifiers.
  • pool_id: the pool identifier.
  • class_id: the class identifier of labor token.
  • asset_id: the asset identifier of labor token.

Example Output:​

{
"challenged": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"successful": ["CIDTest1"],
"failed": ["CIDTest2"]
}
  • challenged: the account of the account being verified.
  • successful: and array of the contend identifiers thats were successful.
  • failed: and array of the contend identifiers thats were failed.

Mint Labor Tokens​

Description:​

This function mint labor tokens

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.
  3. Generate a challenge.
  4. Verify a challenge

Steps:​

  1. Call the fula/mint_labor_tokens endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": 1
"class_id": 2000,
"asset_id": 3000
}
  • seed: the seed of the account to verify.
  • pool_id: the pool identifier.
  • class_id: the class identifier of labor token.
  • asset_id: the asset identifier of labor token.

Example Output:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"amount": 12345,
"class_id": 2000,
"asset_id": 3000
}
  • account: the account minting the labor tokens.
  • amount: the amount of labor tokens that were minted.
  • class_id: the class identifier of labor token.
  • asset_id: the asset identifier of labor token.

Verify Pending Challenge​

Description:​

Verifies if the given account has open challenges

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.
  3. Generate a challenge.

Steps:​

  1. Call the fula/challenge/pending endpoint with the following request body:

Example Input:​

{
"seed": "//Alice"
}
  • seed: the seed of the account thats verifying if its got challenges.

Example Output:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pending": true
}
  • account: the account being verified.
  • pending: indicates if the account has some challenges open

Verify File Size​

Description:​

Cheks that the cids associate with an account are correct

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.

Steps:​

  1. Call the fula/file/verify endpoint with the following request body:

Example Input:​

{
"seed": "//Alice"
}
  • seed: the seed of the account associated with the CIDs.

Example Output:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"cids": ["CIDTest1","CIDTest2"]
}
  • account: the account being verified.
  • pending: an array of content identifiers

Provide Files Sizes​

Description:​

Updates the file of the sized for each cid provided.

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.

Steps:​

  1. Call the fula/file/provide endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": 1,
"cids": ["CIDTest1","CIDTest2"],
"sizes": [88359,23456],
}
  • seed: the seed of the account associated with the CIDs.
  • cid: an array of the content identifiers.
  • pool_id: the pool identifier.
  • sizes: an array of the file sized corresponding to the array of CIDs.

Example Output:​

{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pool_id": 1,
"cids": ["CIDTest1","CIDTest2"],
"sizes": [88359,23456],
}
  • account: the account associated with the given CIDs.
  • cid: an array of the content identifiers.
  • pool_id: the pool identifier.
  • sizes: an array of the file sized corresponding to the array of CIDs.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Claims.html b/blockchain/Recipes/Claims.html index e16900ac..924b5fb9 100644 --- a/blockchain/Recipes/Claims.html +++ b/blockchain/Recipes/Claims.html @@ -5,13 +5,13 @@ Claims | Functionland - +

Claims

Claim tokens​

Description:​

Its retrives all the claims done by the clients.

Steps:​

  1. Call the fula/claims endpoint with the following request body:

Expected Input:​

{}

Example Output:​

{
"claims": [
{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"minted_labor_tokens": 10,
"expected_labor_tokens": 0,
"minted_challenge_tokens": 1000
}
}
  • account: the account associated with the claims tokens.
  • minted_labor_tokens: the amount of labor tokens minted.
  • expected_labor_tokens: the amount of labor tokens expected.
  • minted_challenge_tokens: the amount of challenge tokens minted.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Manifest.html b/blockchain/Recipes/Manifest.html index 90c135d8..755202dc 100644 --- a/blockchain/Recipes/Manifest.html +++ b/blockchain/Recipes/Manifest.html @@ -5,13 +5,13 @@ Manifest | Functionland - +

Manifest

Upload Manifest​

Description:​

Allows the user to upload a manifest to the chain so it's available to be stored.

Previous Steps:​

  1. Upload the file on IPFS and copy the file CID.

Steps:​

  1. Call the manifest/upload endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": 1,
"cid": "CIDTest1",
"replication_factor":2,
"manifest_metadata": {
"job": {
"work": "Storage",
"engine": "IPFS",
"uri": "CIDTest1"
}
}
}
  • seed: the seed of the account uploader.
  • replication_factor: the amount of times that file can be replicated.
  • pool_id: the pool identifier where the file its going to be uploaded.
  • manifest_metadata: the corresponding metadata of the manifest being uploaded.

Example Output:​

{
"uploader": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"storage": [],
"manifest_metadata": {
"job": {
"engine": "IPFS",
"uri": "CIDTest1",
"work": "Storage"
}
},
"pool_id": 1
}
  • uploader: the account of the file uploader.
  • storage: the accounts that are storing the file currently (initialized as empty).
  • manifest_metadata: the corresponding metadata of the manifest uploaded.
  • pool_id: the pool identifier where the file its going to be uploaded.

Batch Upload Manifest​

Description:​

Allows the user to upload multiple manifest to the chain so they’re available to be stored.

Previous Steps:​

  1. Upload the files on IPFS and copy the file CIDs.

Steps:​

  1. Call the manifest/batch_upload endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": [1,1],
"cid":["CIDTest2", "CIDTest3"],
"replication_factor": [2,3],
"manifest_metadata": [{
"job": {
"work": "Storage",
"engine": "IPFS",
"uri": "CIDTest1"
}
},{
"job": {
"work": "Storage",
"engine": "IPFS",
"uri": "CIDTest2"
}
}]
}
  • seed: the seed of the account uploader.
  • replication_factor: the amount of times that file can be replicated.
  • pool_id: the pool identifier where the file its going to be uploaded.
  • manifest_metadata: the corresponding metadata of the manifest being uploaded.

Example Output:​

{
"uploader": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pool_id": [1,1],
"manifest_metadata": [
{
"job": {
"engine": "IPFS",
"uri": "CIDTest1",
"work": "Storage"
}
},
{
"job": {
"engine": "IPFS",
"uri": "CIDTest2",
"work": "Storage"
}
}
]
}
  • uploader: the account of the file uploader.
  • manifest_metadata: the corresponding array of metadata of the manifests uploaded.
  • pool_id: the array of pool identifiers where the file its going to be uploaded.

Store Manifest​

Description:​

Allows the user to store a specific manifest through the cid of a manifest.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest/storage endpoint with the following request body:

Example Input:​

{
"seed": "//Bob"
"cid": "CIDTest1",
"pool_id": 1
}
  • seed: the seed of the storage account.
  • cid: the content identifier associated with the file uploaded.
  • pool_id: the pool identifier where the file is uploaded.

Example Output:​

{
"storage": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": "CIDTest1",
"pool_id": 1
}
  • storage: the account that's storing the file.
  • cid: the content identifier of the manifest being stored.
  • pool_id: the pool identifier where the file is uploaded.

Batch Store Manifest​

Description:​

Allows the user to store all the manifest he wants through the cids of those manifest.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest/batch_storage endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"pool_id": 1,
"cid": ["CIDTest1","CIDTest2"]
}
  • seed: the seed of the storage account.
  • cid: an array of the content identifiers associated with the files uploaded.
  • pool_id: the pool identifier where the file is uploaded.

Example Output:​

{
"storer": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": ["CIDTest1","CIDTest2"]
"pool_id": 1
}
  • storer: the account that's storing the file.
  • cid: an array of the content identifiers associated with the files uploaded.
  • pool_id: the pool identifier where the file is uploaded.

Get Available​

Description:​

Fetches all the available manifests to be stored.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest/available endpoint with the following request body:

Example Input:​

{
"pool_id": 1
}
  • pool_id: the pool identifier where the file is uploaded.

Example Output:​

{
"manifests": [
{
"pool_id": 1,
"manifest_data": {
"manifest_metadata": {
"job": {
"engine": "IPFS",
"uri": "CIDTest1",
"work": "Storage"
}
}
},
"replication_available": 1
}
]
}
  • manifests: an array of all the manifest that are available to be stored in that pool.

Get All​

Description:​

Fetches all the manifest there are or those related to the parameters given as filter.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest endpoint with the following request body:

Note: If you call the function with empty parameters: { }. This will bring all the manifest there are.

Example Input:​

{
"pool_id": 1,
"account":"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • pool_id: the pool identifier where the files are uploaded.
  • account: the account that uploaded the files.

Example Output:​

{
"manifests": [
{
"pool_id": 1,
"uploaders": [
{
"uploader": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"storers": [],
"replication_available": 2
}
],
"manifest_metadata": {
"job": {
"engine": "IPFS",
"uri": "CIDTest1",
"work": "Storage"
}
}
}
]
}
  • manifests: an array of all the manifest that were fetch according to the parameters given.

Remove​

Description:​

The uploader or admin can remove a manifest from the pool.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest/remove endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"cid": "CIDTest1",
"pool_id": 1
}
  • seed: the seed of the account uploader.
  • cid: the content identifier of the manifest being removed.
  • pool_id: the pool identifier where the file is being removed.

Example Output:​

{
"uploader": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"cid": "CIDTest1",
"pool_id": 1
}
  • uploader: the account of the file uploader.
  • cid: the content identifier of the manifest removed.
  • pool_id: the pool identifier where the file was removed.

Batch Remove​

Description:​

The uploader or admin can remove a manifest from the pool.

Previous Steps:​

  1. Upload a manifest.

Steps:​

  1. Call the manifest/batch_remove endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": [1,1],
"cid": ["CIDTest1","CIDTest2"]
}
  • seed: the seed of the storage account.
  • cid: an array of the content identifiers associated with manifest being removed.
  • pool_id: the pool identifier where the file is being removed.

Example Output:​

{
"uploader": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": ["CIDTest1","CIDTest2"],
"pool_id": [1,1],
}
  • uploader: the account of the file uploader.
  • cid: the array of content identifiers of the manifest removed.
  • pool_id: the pool identifier where the file was removed.

Remove Stored Manifest​

Description:​

The storer can stop storing a given manifest

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.

Steps:​

  1. Call the manifest/remove_storing_manifest endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"cid": "CIDTest1",
"pool_id": 1
}
  • seed: the seed of the account storer.
  • cid: the content identifier of the manifest to no longer be stored.
  • pool_id: the pool identifier.

Example Output:​

{
"storer": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": "CIDTest1",
"pool_id": 1
}
  • storer: the account of the file storer.
  • cid: the content identifier of the manifest no longer being stored.
  • pool_id: the pool identifier.

Batch Remove Stored Manifest​

Description:​

The storer can stop storing the given manifests

Previous Steps:​

  1. Upload a manifest.
  2. Store a manifest.

Steps:​

  1. Call the manifest/batch_remove_storing_manifest endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"cid": ["CIDTest1","CIDTest2"]
"pool_id": 1
}
  • seed: the seed of the account storer.
  • cid: the array of content identifiers of the manifests to no longer be stored.
  • pool_id: the pool identifier.

Example Output:​

{
"storer": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"cid": ["CIDTest1","CIDTest2"]
"pool_id": 1
}
  • storer: the account of the file storer.
  • cid: the array of content identifiers of the manifests no longer being stored.
  • pool_id: the pool identifier.
- + \ No newline at end of file diff --git a/blockchain/Recipes/Market.html b/blockchain/Recipes/Market.html index dbb3f1ae..d725d780 100644 --- a/blockchain/Recipes/Market.html +++ b/blockchain/Recipes/Market.html @@ -5,13 +5,13 @@ Market | Functionland - +

Market

Create​

Description:​

This function creates a new market.

Previous Steps:​

  1. Create an account.
  2. Fund an account.

Steps:​

  1. Call the market/create_market endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"market_id": 1
}
  • seed: the seed of the account that will pay for the transaction.
  • market_id: the market identifier.

Expected Output:​

{
"market_id": 1,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address associated with the market.
  • market_id: the market identifier.

Create Market Rate​

Description:​

This function creates a new market rate.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a class.
  4. Create an asset.
  5. Mint an asset.
  6. Create a market.

Steps:​

  1. Call the market/create_market_rate endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"market_id": 1,
"market_rate_id": 1,
"rates": {
"rates": [
{
"class_id": 2000,
"asset_id": 1,
"action": {
"Transfer": 1
},
"from": "Market",
"to": "Buyer"
},
{
"class_id": 2000,
"asset_id": 2,
"action": {
"Mint": 1
},
"from": "Market",
"to": "Buyer"
},
{
"class_id": 3000,
"asset_id": 1,
"action": {
"Has": [
"GreaterEqualThan",
5000
]
},
"from": "Buyer",
"to": "Market"
},
{
"class_id": 3000,
"asset_id": 2,
"action": {
"Transfer": 5
},
"from": "Buyer",
"to": "Market"
},
{
"class_id": 3000,
"asset_id": 3,
"action": {
"Burn": 50
},
"from": "Buyer",
"to": "Market"
},
{
"class_id": 4000,
"asset_id": 1,
"action": {
"Transfer": 2
},
"from": "Market",
"to": {
"Account": "//Alice"
}
},
{
"class_id": 4000,
"asset_id": 2,
"action": {
"Transfer": 1
},
"from": "Buyer",
"to": {
"Account": "//Alice"
}
}
],
"metadata": []
}
}
  • seed: the seed of the account that will pay for the transaction.
  • market_id: the market identifier
  • market_rate_id: the market rate identifier
  • rates:
    • rates: an array of the requirements that the transaction needs to fulfilled.
    • metadata: additional information about the rates.

Expected Output:​

{
"market_id": 1,
"market_rate_id": 1,
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
}
  • who: the account address associated with the market.
  • market_id: the market identifier.
  • market_rate_id: the market rate identifier.

Deposit Assets​

Description:​

This function deposits a given amount of assets in the market.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a class.
  4. Create an asset.
  5. Mint an asset.
  6. Create a market.
  7. Create a market rate.

Steps:​

  1. Call the market/deposit_assets endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"market_id": 1,
"market_rate_id": 1,
"amount": 1000
}
  • seed: the seed of the account that will pay for the transaction.
  • market_id: the market identifier
  • market_rate_id: the market rate identifier
  • amount: the specific amount of assets to be deposited.

Expected Output:​

{
"who": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"market_id": 1,
"market_rate_id": 1,
"amount": 1000,
"balances": [],
"success": true
}
  • who: the account address associated with the market.
  • market_id: the market identifier.
  • market_rate_id: the market rate identifier.
  • amount: the specific amount of assets deposited.
  • balances: an array of the results of each operation after the deposit
  • success: an indicator to see if the deposited was successful

Exchange Assets​

Description:​

This function deposits a given amount of assets in the market.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a class.
  4. Create an asset.
  5. Mint an asset.
  6. Create a market.
  7. Create a market rate.
  8. Deposit assets.

Steps:​

  1. Call the market/exchange_assets endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"market_id": 1,
"market_rate_id": 1,
"amount": 1000
}
  • seed: the seed of the account that will pay for the transaction.
  • market_id: the market identifier
  • market_rate_id: the market rate identifier
  • amount: the specific amount of assets to be exchanged.

Expected Output:​

{
"buyer": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"market_id": 1,
"market_rate_id": 1,
"amount": 1000,
"balances": [
{
"rate": {
"class_id": 1,
"asset_id": 1,
"action": "Mint",
"amount": 1000,
"from": "Market",
"to": "Buyer"
},
"balance": 1000000
}
],
"success": true
}
  • who: the account address associated with the market.
  • market_id: the market identifier.
  • market_rate_id: the market rate identifier.
  • amount: the specific amount of assets exchanged.
  • balances: an array of the results of each operation after the exchange
  • success: an indicator to see if the deposited was successful
- + \ No newline at end of file diff --git a/blockchain/Recipes/Pool.html b/blockchain/Recipes/Pool.html index 4df85911..800248d8 100644 --- a/blockchain/Recipes/Pool.html +++ b/blockchain/Recipes/Pool.html @@ -5,13 +5,13 @@ Pool | Functionland - +

Pool

Create​

Description:​

Allows the user to create a pool and is set as the owner of the pool

Previous Steps:​

  1. Create an account.
  2. Fund an account.

Steps:​

  1. Call the fula/pool/create endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_name":"PoolNro1",
"peer_id": "PeerIdTest1",
"region": "Ontario"
}
  • seed: the seed of the account that will pay for the transaction.
  • pool_name: the name of the pool.
  • peer_id: the peer identifier

Expected Output:​

{
"owner": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pool_id": 1
}
  • owner: the account address associated with the pool.
  • pool_id: the pool identifier.

Join​

Description:​

Sends a request to join a pool to its members, that will vote to decide if the user is Accepted or Denied

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.

Steps:​

  1. Call the fula/pool/join endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"pool_id": 1,
"peer_id": "PeerIdBob"
}
  • seed: the seed of the account that wants to join and will pay for the transaction.
  • pool_id: the pool identifier.
  • peer_id: the peer identifier

Expected Output:​

{
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
}
  • account: the account address that requested to join the pool.
  • pool_id: the pool identifier.

Cancel Join​

Description:​

Withdraw the latest pool request sent to the given pool by that user.

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.
  4. Request to join the pool.

Steps:​

  1. Call the fula/pool/cancel_join endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"pool_id": 1
}
  • seed: the seed of the account that no longer wants to join the pool.
  • pool_id: the pool identifier.

Expected Output:​

{
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
}
  • account: the account address that no longer wants to join the pool.
  • pool_id: the pool identifier.

Pool Requests​

Description:​

Allows the user to get all the current pool requests (can be filtered by pool_id and account of the requester)

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.
  4. Request to join the pool.

Steps:​

  1. Call the fula/pool/poolrequests endpoint with the following request body:

Note: If you call the function with empty parameters: { }. This will bring all the pool requests there are.

Example Input:​

{
"pool_id": 1
}
  • pool_id: the pool identifier.

Expected Output:​

{
"poolrequests": [
{
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"voted": [],
"positive_votes": 0,
"peer_id": "PeerIdBob"
}
]
}
  • poolrequests: an array of all the pool requests associated with the queried parameters

Pools​

Description:​

Fetches all the pools that exist in the chain

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.

Steps:​

  1. Call the fula/pool/all endpoint

Expected Output:​

{
"pools": [
{
"pool_id": 1,
"creator": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pool_name": "PoolTest1",
"region": "Ontario",
"parent": null,
"participants": [
"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY"
]
}
]
}
  • pools: an array of all the pools and their respective information.

Users​

Description:​

Get all the accounts that are/were members of a pool or are requesting to be in one

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.
  4. Join a pool.

Steps:​

  1. Call the fula/pool/users endpoint with the following request body:

Note: If you call the function with empty parameters: { }. This will bring all users.

Example Input:​

{
"pool_id": 1
}
  • pool_id: the pool identifier.

Expected Output:​

{
"users": [
{
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"pool_id": null,
"request_pool_id": 1,
"peer_id": ""
},
{
"account": "5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY",
"pool_id": 1,
"request_pool_id": null,
"peer_id": "PeerIdTest1"
}
]
}
  • users: an array of all the users and their respective information.

Vote​

Description:​

Allows the members of a pool to vote to accept or denied a new given member into the pool

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.
  4. Join a pool.
  5. Get pool requests.

Steps:​

  1. Call the fula/pool/vote endpoint with the following request body:

Example Input:​

{
"seed": "//Alice",
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty",
"vote_value": true,
"peer_id": "PeerIdTest"
}
  • seed: the seed of the user voting.
  • pool_id: the pool identifier.
  • account: the account address of the user requesting to join.
  • vote_value: the vote of the user.

Expected Output:​

{
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
}
  • pool_id: the pool identifier.
  • account: the account address of the user requesting to join.

Leave​

Description:​

The user leaves their pool and this will also remove the storing manifests that from their latest pool if they had any

Previous Steps:​

  1. Create an account.
  2. Fund an account.
  3. Create a pool.
  4. Join a pool.

Steps:​

  1. Call the fula/pool/leave endpoint with the following request body:

Example Input:​

{
"seed": "//Bob",
"pool_id": 1
}
  • seed: the seed of the user that wants to leave the pool.
  • pool_id: the pool identifier.

Expected Output:​

{
"pool_id": 1,
"account": "5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty"
}
  • pool_id: the pool identifier.
  • account: the account address of the user that left the pool.
- + \ No newline at end of file diff --git a/blockchain/Services/BuildNode.html b/blockchain/Services/BuildNode.html index 0193597f..3044bb3e 100644 --- a/blockchain/Services/BuildNode.html +++ b/blockchain/Services/BuildNode.html @@ -5,13 +5,13 @@ Build Node | Functionland - +

Build Node

1- Install Rust

curl https://sh.rustup.rs -sSf | sh

source ~/.bashrc

2- Install dependencies:

sudo apt-get install protobuf-compiler libclang-dev build-essential

3- Clone node repo

git clone https://github.com/functionland/sugarfunge-node.git

4- Enter the folder

cd ./sugarfunge-node

5- Install wasm32

rustup target add wasm32-unknown-unknown

6- Build

cargo build --release

Now a folder named "./target/release" is create where it contains all the compiled codes. If any error occured, your system might still be missing some dependancies. Please follow the full guide below and run step 6 again afterwards:

Install OS dependencies and Rust​

- + \ No newline at end of file diff --git a/blockchain/Services/Explorer.html b/blockchain/Services/Explorer.html index 363590a9..9cbec537 100644 --- a/blockchain/Services/Explorer.html +++ b/blockchain/Services/Explorer.html @@ -5,13 +5,13 @@ Explorer | Functionland - +

Explorer

Compile from Source

Install NodeJS​

Install Yarn​

Clone the Explorer​

git clone https://github.com/functionland/sugarfunge-explorer.git

Run the Explorer​

Requires a Node running.

yarn
WS_URL=ws://127.0.0.1:9944 yarn start

Using Docker

Install Docker​

Build the image​

docker build -t sugarfunge-explorer:local -f docker/Dockerfile .

Run the Explorer​

Requires a Node running.

docker run --rm -d --network host --env WS_URL=ws://127.0.0.1:9944 sugarfunge-explorer:local

Functionyard Network

If you want to run an explorer for functionyard network:

docker run --rm --name Explorer --network host --env WS_URL=wss://node.functionyard.fx.land --env WSS_URL=wss://node.functionyard.fx.land sugarfunge-explorer:local

Or set it as a service:

sudo nano /etc/systemd/system/docker-sugarfunge-explorer.service

And fill it with:

[Unit]
Description=Docker Sugarfunge Explorer
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
Type=simple
ExecStart=/usr/bin/docker run --rm --name Explorer --network host --env WS_URL=wss://node.functionyard.fx.land --env WSS_URL=wss://node.functionyard.fx.land sugarfunge-explorer:local
ExecStop=/usr/bin/docker stop Explorer
Restart=always
StandardOutput=file:/var/log/Explorer.log
StandardError=file:/var/log/Explorer.err

[Install]
WantedBy=multi-user.target
- + \ No newline at end of file diff --git a/blockchain/Services/FulaContractAPI.html b/blockchain/Services/FulaContractAPI.html index 2c3d122d..50324c3f 100644 --- a/blockchain/Services/FulaContractAPI.html +++ b/blockchain/Services/FulaContractAPI.html @@ -5,13 +5,13 @@ Fula Contract API | Functionland - +

Fula Contract API

This is the end point that interacts with Fula blockchain contract

Run the Node API​

Requires a Node running.

Install dependencies​

sudo apt-get install build-essential

Set up the .env file​

Using the .env.example create the .env file and fill the needed values

LAUNCH THE FULA CONTRACT API​

Run the following command

cargo run --release -- --node-server=wss://node3.functionyard.fx.land

Alternatively, if you want to set it up as a service:

cargo build --release

then:

sudo nano /etc/systemd/system/fula-contract-api.service

And enter hte below in the file:

[Unit]
Description=Fula Contract API

[Service]
TimeoutStartSec=0
Type=simple
ExecStart=/home/user/fula-contract-api/target/release/functionland-contract-api --node-server=wss://node3.functionyard.fula.network
Restart=always
StandardOutput=file:/var/log/fula-contract-api.log
StandardError=file:/var/log/fula-contract-api.err

[Install]
WantedBy=multi-user.target

Then enable the service and start it. You can test the end points like below:

curl -X POST http://127.0.0.1:4001/health

Available endpoints​

Health: Verifies that the API is running

path: "health"

Read endpoints​

Supply: Consult the total supply of the token

paths: "goerli/supply", "mumbai/supply"

Allowance: Consult the current allowance of the given accounts

paths: "goerli/allowance", "mumbai/allowance"

Write endpoints​

Mint: Mint tokens to the given account

paths: "goerli/mint", "mumbai/mint"

Burn: Burn tokens from the given account if the necessary allowance

paths: "goerli/burn", "mumbai/burn"

Transfer: Transfer the tokens from the given account if the necessary allowance

paths: "goerli/transfer", "mumbai/transfer"

Increase_allowance: Increase the amount of tokens to be able to burn or transfer

paths: "goerli/increase_allowance", "mumbai/increase_allowance"

Decrease_allowance: Decrease the amount of tokens to be able to burn or transfer

paths: "goerli/decrease_allowance", "mumbai/decrease_allowance"
- + \ No newline at end of file diff --git a/blockchain/Services/Node.html b/blockchain/Services/Node.html index 3f686b9a..bfe8cf8a 100644 --- a/blockchain/Services/Node.html +++ b/blockchain/Services/Node.html @@ -5,13 +5,13 @@ Test Node | Functionland - +

Test Node

This document explains how to run sample nodes. However, for an actual node with custom keys please refer to Run Node

Compile from Source

Install OS dependencies and Rust​

Clone the Node​

git clone https://github.com/functionland/sugarfunge-node.git

Run a Local Testnet​

alice node:​

cargo run --release -- --chain=local --enable-offchain-indexing true --alice --base-path=.tmp/a --port=30334 --ws-port 9944 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external

bob node:​

cargo run --release -- --chain=local --enable-offchain-indexing true --bob --base-path=.tmp/b --port=30335 --ws-port 9945 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWNxmYfzomt7EXfMSLuoaK68JzXnZkNjXyAYAwNrQTDx7Y

charlie node:​

cargo run --release -- --chain=local --enable-offchain-indexing true --charlie --base-path=.tmp/c --port=30336 --ws-port 9946 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWNxmYfzomt7EXfMSLuoaK68JzXnZkNjXyAYAwNrQTDx7Y

Using Docker

Install Docker​

Build the image​

docker build -t sugarfunge-node:local -f docker/Dockerfile .

Run a Local Testnet​

alice node:​

docker run --rm -d --network host sugarfunge-node:local --chain=local --enable-offchain-indexing true --alice --base-path=.tmp/a --port=30334 --ws-port 9944 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external

bob node:​

docker run --rm -d --network host sugarfunge-node:local --chain=local --enable-offchain-indexing true --bob --base-path=.tmp/b --port=30335 --ws-port 9945 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWNxmYfzomt7EXfMSLuoaK68JzXnZkNjXyAYAwNrQTDx7Y

charlie node:​

docker run --rm -d --network host sugarfunge-node:local --chain=local --enable-offchain-indexing true --charlie --base-path=.tmp/c --port=30336 --ws-port 9946 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWNxmYfzomt7EXfMSLuoaK68JzXnZkNjXyAYAwNrQTDx7Y
- + \ No newline at end of file diff --git a/blockchain/Services/NodeAPI.html b/blockchain/Services/NodeAPI.html index 8016afb8..18664d40 100644 --- a/blockchain/Services/NodeAPI.html +++ b/blockchain/Services/NodeAPI.html @@ -5,13 +5,13 @@ Node API | Functionland - +

Node API

Compile from Source

Install OS dependencies and Rust​

Clone the Node API​

git clone https://github.com/functionland/sugarfunge-api.git

Run the Node API​

Requires a Node running.

cargo run --release

Using Docker

Install Docker​

Build the image​

docker build -t sugarfunge-api:local -f docker/Dockerfile .

Edit the .env​

sudo nano .ev.example

Save it and then:

sudo mv .env.example /var/lib/.sugarfunge-node/.env

Run the Node API​

Requires a Node running.

docker run --rm -d --name MyNode03API --network host -v /var/lib/.sugarfunge-node/.env:/.env -v /var/lib/.sugarfunge-node/data/node03:/data sugarfunge-api:local --db-uri=/data --node-server ws://127.0.0.1:9946

Available arguments

sugarfunge-api 0.1.0

USAGE:
sugarfunge-api [OPTIONS]

FLAGS:
-h, --help Prints help information
-V, --version Prints version information

OPTIONS:
-d, --db-uri <db>
-l, --listen <listen> [default: http://127.0.0.1:4000]
-s, --node-server <node-server> [default: ws://127.0.0.1:9944]

Subscriptions

Basic support for WebSockets subscriptions is available. Any tool that offers features for WebSockets connections and subscriptions will apply. For example, websocat

websocat ws://127.0.0.1:4000/ws

API Metadata Generation

If you update the Node manually and added pallets, it's required to generate the metadata with the SugarFunge fork of subxt to access the new state of the chain using the API.

cargo install subxt-cli

subxt-cli metadata -f bytes > sugarfunge_metadata.scale --url http://localhost:9934/
- + \ No newline at end of file diff --git a/blockchain/Services/ProofEngine.html b/blockchain/Services/ProofEngine.html index 0e398efb..343e845e 100644 --- a/blockchain/Services/ProofEngine.html +++ b/blockchain/Services/ProofEngine.html @@ -5,13 +5,13 @@ Proof Engine | Functionland - +

Proof Engine

Compile from Source

Install OS dependencies and Rust​

Install Bevy dependencies for your OS​

Clone the Proof Engine​

git clone https://github.com/functionland/proof-engine.git

Run the Proof Engine​

Requires a Node, Node API and an IPFS node running.

RUST_LOG="warn,proof_engine=info" cargo run --release -- //Alice --pool-id 1000000

Using Docker

Install Docker​

Build the image​

docker build -t proof-engine:local -f docker/Dockerfile .

Run the Proof Engine​

Requires a Node, Node API and an IPFS node running.

docker run --rm -d --network host proof-engine:local
- + \ No newline at end of file diff --git a/blockchain/Services/RunNode.html b/blockchain/Services/RunNode.html index 0805d0a0..9160aeb0 100644 --- a/blockchain/Services/RunNode.html +++ b/blockchain/Services/RunNode.html @@ -5,7 +5,7 @@ Run Node | Functionland - + @@ -16,7 +16,7 @@ --base-path= .temp/node02 --suri β€œ the corresponding secret phrase”

5) COMMANDS TO START THE NODES

a) For the main validator node execute (replace the node-key with correct key of peer id):

cargo run --release -- --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=.tmp/node01 --port=30334 --ws-port 9944 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --validator --name MyNode01 --password-interactive --node-key=4ac42a38b622dd9943c49ca9300000236406d35a43f0ce82eef556c1d81a4157

b) For the rest of validator nodes execute (replacing node-key with second peer id key and peerID after /p2p/ with the main node peer id) :

cargo run --release -- --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=.tmp/node02 --port=30335 --ws-port 9945 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/12D3KooWC9nU1QzG8m3dZKSNqssmasdupLPhgu9adYe1h4ToBW7r --validator --name MyNode02 --password-interactive --node-key=5ed89682d5d0d2efd35f98a248b97cc1f6155e6af169719f3d54900d34a98a4a

Note: For each of the commands the following fields should be change accordingly:

--base-path = .temp/node02 or .temp/node03
--port = To a port not used in other commands
--ws-port = To a port not used in other commands
--bootnodes = Update the last segment value to the peer-id of the main validator obtained in step 2
--name = to the given name
--node-key with the node key values obtained in step 2 for each account

Run Non-Validator Nodes

To add new nodes to the network that are not authorized:

1) GENERATE THE NODE-KEY AND PEER-ID FOR THE USER-THREE

a) Generate a random node key and peer-id

./target/release/sugarfunge-node key generate-node-key

sample output:

Peer-id: 12D3KooWF3MLTqgFRAKVqAdscdfZSSb9xXKFJ8paNEbtETKczUto
key: 239afb9dae01b5c010c454f1e1df64ce83b3e13803540df079677860a745d168

b) Save the key as a file

echo -n "239afb9dae01b5c010c454f1e1df64ce83b3e13803540df079677860a745d168" > user-three-key

c) Verify that the peer-id is correct using the node-key stored

./target/release/sugarfunge-node key inspect-node-key --file user-three-key

2) START NODE COMMAND FOR THE NOT AUTHORIZE NODE

cargo run --release -- --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=.tmp/node03 --port=30336 --ws-port 9946 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /dns4/node.functionyard.fx.land/tcp/30334/p2p/12D3KooWBeXV65svCyknCvG1yLxXVFwRxzBLqvBJnUF6W84BLugv --name MyNode03 --node-key=[key3] --offchain-worker always

Note: For each of the commands the following fields should be change accordingly:

--base-path = .temp/node02 or .temp/node03
--port = To a port not used in other commands
--ws-port = To a port not used in other commands
--name = to the given name
--node-key with the node key values obtained in step 2 for each account

Here is the official Fula customSpecRaw.json file: Fula official raw specs


Using Docker

Install Docker​

Build the image​

cd sugarfunge-node

sudo mkdir /var/lib/.sugarfunge-node
sudo chmod 777 /var/lib/.sugarfunge-node
sudo mkdir /var/lib/.sugarfunge-node/passwords
sudo mkdir /var/lib/.sugarfunge-node/keys
sudo mkdir /var/lib/.sugarfunge-node/keys/node01
sudo mkdir /var/lib/.sugarfunge-node/keys/node02
sudo mkdir /var/lib/.sugarfunge-node/data
sudo mkdir /var/lib/.sugarfunge-node/data/node01
sudo mkdir /var/lib/.sugarfunge-node/data/node02

Now insert Keys:

./target/release/sugarfunge-node key insert --base-path=/var/lib/.sugarfunge-node/keys/node01 --chain customSpecRaw.json --scheme Sr25519 --suri "YOUR SECRET WORDS" --password-interactive --key-type aura

./target/release/sugarfunge-node key insert --base-path=/var/lib/.sugarfunge-node/keys/node01 --chain customSpecRaw.json --scheme Sr25519 --suri "YOUR SECRET WORDS" --password-interactive --key-type gran

Redo the same for node02 and put the keys for node02.

sudo nano /var/lib/.sugarfunge-node/passwords/password1.txt

Insert the password for node1 and redo with password2 for node2. Then revert the permission:

sudo chmod 755 /var/lib/.sugarfunge-node

Build:

docker build -t sugarfunge-node:local -f docker/Dockerfile .

Then you can run the validator nodes like:

docker run --rm -d --name MyNode01 --network host -v /var/lib/.sugarfunge-node/passwords/password1.txt:/password.txt -v /var/lib/.sugarfunge-node/keys/node01:/keys -v /var/lib/.sugarfunge-node/data/node01:/data sugarfunge-node:local --chain /customSpecRaw.json --enable-offchain-indexing true --base-path=/data --keystore-path=/keys --port=30334 --ws-port 9944 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --validator --name MyNode01 --password-filename "/password.txt" --node-key=[key1]

docker run --rm -d --name MyNode02 --network host -v /var/lib/.sugarfunge-node/passwords/password2.txt:/password.txt -v /var/lib/.sugarfunge-node/keys/node02:/keys -v /var/lib/.sugarfunge-node/data/node02:/data sugarfunge-node:local --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=/data --keystore-path=/keys --port=30335 --ws-port 9945 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/[peerId1] --validator --name MyNode02 --password-filename "/password.txt" --node-key=[key2]

For non-validator node on Functionyard network, you can run:

docker run --rm -d --name MyNode03 --network host -v /var/lib/.sugarfunge-node/passwords/password3.txt:/password.txt -v /var/lib/.sugarfunge-node/keys/node03:/keys -v /var/lib/.sugarfunge-node/data/node03:/data sugarfunge-node:local --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=/data --keystore-path=/keys --port=30336 --ws-port 9946 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /dns4/node.functionyard.fx.land/tcp/30334/p2p/12D3KooWBeXV65svCyknCvG1yLxXVFwRxzBLqvBJnUF6W84BLugv --name MyNode03 --node-key=[key3] --offchain-worker always

Run as service​

sudo nano /etc/systemd/system/docker-sugarfunge-node1.service

And insert:

[Unit]
Description=Docker Sugarfunge Node 1
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
Type=simple
ExecStart=/usr/bin/docker run --rm --name MyNode01 --network host -v /var/lib/.sugarfunge-node/passwords/password1.txt:/password.txt -v /var/lib/.sugarfunge-node/keys/node01:/keys -v /var/lib/.sugarfunge-node/data/node01:/data sugarfunge-node:local --chain /customSpecRaw.json --enable-offchain-indexing true --base-path=/data --keystore-path=/keys --port=30334 --ws-port 9944 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --validator --name MyNode01 --password-filename "/password.txt" --node-key=[key]
ExecStop=/usr/bin/docker stop MyNode01
Restart=always
StandardOutput=file:/var/log/MyNode01.log
StandardError=file:/var/log/MyNode01.err

[Install]
WantedBy=multi-user.target
sudo nano /etc/systemd/system/docker-sugarfunge-node2.service

And insert:

[Unit]
Description=Docker Sugarfunge Node 2
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
Type=simple
ExecStart=/usr/bin/docker run --rm --name MyNode02 --network host -v /var/lib/.sugarfunge-node/passwords/password2.txt:/password.txt -v /var/lib/.sugarfunge-node/keys/node02:/keys -v /var/lib/.sugarfunge-node/data/node02:/data sugarfunge-node:local --chain ./customSpecRaw.json --enable-offchain-indexing true --base-path=/data --keystore-path=/keys --port=30335 --ws-port 9945 --ws-external --rpc-cors=all --rpc-methods=Unsafe --rpc-external --bootnodes /ip4/127.0.0.1/tcp/30334/p2p/[peerId1] --validator --name MyNode02 --password-filename "/password.txt" --node-key=[Key2]
ExecStop=/usr/bin/docker stop MyNode02
Restart=always
StandardOutput=file:/var/log/MyNode02.log
StandardError=file:/var/log/MyNode02.err

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable docker-sugarfunge-node1.service
sudo systemctl enable docker-sugarfunge-node2.service
sudo systemctl start docker-sugarfunge-node1.service
sudo systemctl start docker-sugarfunge-node2.service
- + \ No newline at end of file diff --git a/blockchain/Services/Status.html b/blockchain/Services/Status.html index a1a0e9f0..e60b74ed 100644 --- a/blockchain/Services/Status.html +++ b/blockchain/Services/Status.html @@ -5,13 +5,13 @@ Status | Functionland - +

Status

Compile from Source

Install NodeJS​

Install Yarn​

Clone the Status​

git clone https://github.com/functionland/functionland-status.git

Run the Status​

Requires a Node running.

yarn
PORT=8000 REACT_APP_PROVIDER_SOCKET=ws://127.0.0.1:9944 yarn start

Using Docker

Install Docker​

Build the image​

docker build -t sugarfunge-status:local -f docker/Dockerfile .

Run the Status​

Requires a Node running.

docker run --rm -d --network host --env PORT=8000 --env REACT_APP_PROVIDER_SOCKET=ws://127.0.0.1:9944 sugarfunge-status:local
- + \ No newline at end of file diff --git a/blockchain/blockchain-intro.html b/blockchain/blockchain-intro.html index 4c9750a0..fdae415d 100644 --- a/blockchain/blockchain-intro.html +++ b/blockchain/blockchain-intro.html @@ -5,13 +5,13 @@ Blockchain Documentation | Functionland - +

Blockchain Documentation

Here you can find the documenation on blockchain API and Services.

FULA Testnet

  • Network Name: Functionyard
  • Token Name: $BORG
  • Total Token Cap: 20B

Audit​

An Audit Report ic created by 0xMacro

Functionyard Audit Report

Contracts​

And also smart contracts are deployed:

1- Goerli Network

2- Mumbai Network

Explorer​

And a network explorer is made avaialbe here:

Network Explorer

Simulation​

Finally functionlard token simulations are available here:

Token Simulation

- + \ No newline at end of file diff --git a/blockchain/recipes.html b/blockchain/recipes.html index 19a04e3e..5b936bee 100644 --- a/blockchain/recipes.html +++ b/blockchain/recipes.html @@ -5,13 +5,13 @@ Blockchain APIs | Functionland - + - + \ No newline at end of file diff --git a/blockchain/services.html b/blockchain/services.html index 3db2513d..8c2b0b2a 100644 --- a/blockchain/services.html +++ b/blockchain/services.html @@ -5,13 +5,13 @@ Blockchain Services | Functionland - + - + \ No newline at end of file diff --git a/blog/archive.html b/blog/archive.html index a4fa2d3f..7be80084 100644 --- a/blog/archive.html +++ b/blog/archive.html @@ -5,13 +5,13 @@ Archive | Functionland - +

Archive

Archive

- + \ No newline at end of file diff --git a/components/WorkInProgress.html b/components/WorkInProgress.html index ee354c22..a72154c3 100644 --- a/components/WorkInProgress.html +++ b/components/WorkInProgress.html @@ -5,13 +5,13 @@ WorkInProgress | Functionland - +

WorkInProgress

WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

- + \ No newline at end of file diff --git a/design/encryption.html b/design/encryption.html index 518ab286..96758c92 100644 --- a/design/encryption.html +++ b/design/encryption.html @@ -5,13 +5,13 @@ encryption | Functionland - +

encryption

Current Process:

Upload:

1- Get the wallet address and signature (time-based) from metamask

2- randomly create symmetric key on client per content

3- encrypt the file and send it to the backend

Sharing:

1- I get the person DID (which can be seeded with wallet address)

2- I generate the jwe specific to the DID

3- If we want the revoke, we need to also put some information in the jwe that we need to fetch from a globally accessible source(ceramic, blockchain,...) to validate access. Otherwise, we still have the time-based revokation feature

4- Share the jwe with the signature included in the header

5- The other person can validate and open the file

Cons:

1- Encryption is CPU insentive

2- revokation before the time expires require a globally accessible source

Pros:

1- size of jwe does not depend on the size of the file

2- one encrypted file can be shared with multiple people

3- jwe file can be shared on public ipfs without any security problem

- + \ No newline at end of file diff --git a/design/test.html b/design/test.html index b677b9bb..06313ddd 100644 --- a/design/test.html +++ b/design/test.html @@ -5,13 +5,13 @@ test | Functionland - +

test

this is a test

- + \ No newline at end of file diff --git a/functionyard.html b/functionyard.html index d30eb5f2..e5a24827 100644 --- a/functionyard.html +++ b/functionyard.html @@ -5,13 +5,13 @@ Functionyard | Functionland - +

Functionyard Testnet Launch Guide

This comprehensive guide is designed to assist in preparing a FxBlox owner for the testnet launch. The testnet is called "Functionyard" and the token is "BORG".

- + \ No newline at end of file diff --git a/functionyard/add-storage.html b/functionyard/add-storage.html index b6fa826d..287bb185 100644 --- a/functionyard/add-storage.html +++ b/functionyard/add-storage.html @@ -5,13 +5,13 @@ Add Storage | Functionland - +

Add Storage

Compatible Storage Drives​

Almost all types of storage mediums are compatible with the FxBlox. The Blox has internal slots for:

  • MicroSD
  • M.2 NVMe
  • And any internal/external drives via USB-C (or USB-C adaptor)

For the Blox to recognize and use the drive as storage, it must be formatted to ext4. This is automatically done for all drives connected to the Blox during the setup. If you want to add more storage after the fact, then you will have to manually partition and format it.

Install Internal Storage​

To install an NVMe or MicroSD drive, you'll have to open the Blox to gain access to the Single Board Computer (SBC) inside.

  1. Remove the four black screws of the 3-port USB-C housing.
  2. Remove the four silver screws on the bottom of the Blox.
  3. Slowly slide out the SBC.
  4. Remove light orange cover on the nvme screw mounting point.

Install M.2 NVMe drive​

With nvme drives, there are a lot of options to choose from. Which ever you choose, M.2 NVMe drives are plenty fast enough to maintain a quality speed for reads, writes, and data transfers.

To install your first NVMe drive:

  1. Follow steps above to open the case.
  2. Insert NVMe drive into M.2 slot at an angle. Make sure no pins are showing.
  3. Hold drive down, while you screw it into place. (Screw not included with FxBlox)
  4. Follow steps in reverse order to put the case back together.

Install MicroSD Card​

MicroSD cards have comparitively slow read & write speeds. We don't have enough data to recommend them as a method of storage for Fula net, but it should still be possible to run a high-speed, high-capacity card. The port is located under the wifi card. To access it:

  1. Follow steps above to open the case.
  2. Wifi card does not need to be removed to insert microsd card. Insert microSD card from the side of the board.
  3. Follow steps in reverse order to put the case back together.

Install External Storage​

You can use any type of drive as long as it can be connected via USB-C cable or adapter. Plug it in to any of the three USB-C ports available on the side of the FxBlox. These include, but not limited to:

  • SATA drives (2.5-inch internal SSDs or 3.5-inch internal HDDs)
  • External SSD's or HDDs
  • External NVMe drives
  • Docking stations
  • Hardware RAID arrays
  • etc...

Format Drive​

If you want to add additional storage at some point after initial setup. You will need to manually parition and format the drive before it can be used by the FxBlox.

You will need to parition 100% of the drive and format to ext4. To do this on Mac and Linux, you will want to be comfortable with the command line.

Linux (Terminal)​

Although the drive can not be used by the Fula net yet, we can manually format it through the Blox's desktop interface. At this point, your Blox must already have an internet connection, so you can either remotely login from another computer with ssh, or connect keyboard, video, & mouse. Checkout this article, made by a community member, for more information on how to do that.

  1. Connect your drive to the FxBlox
  2. Connect to your FxBlox via ssh or keyboard, video, & mouse
  3. Log in to pi account using password fxblox
  4. Open up Terminal app with Ctrl + Alt + T
  5. Update current packages with sudo apt update && sudo apt upgrade
  6. Enter password fxblox
  7. Confirm install with y
  8. Download parted app with sudo apt install parted
  9. Identify new disk(s) with sudo parted -l | grep Error
info

In the following commands, replace sdx with the device name(s) found in the output of the above command. Repeat steps 10-12 for any new drives you have, one at a time.

  1. Assign your drive the GPT paritioning standard with sudo parted /dev/sdx mklabel gpt
  2. Partition your drive with sudo parted -a opt /dev/sdx mkpart primary ext4 0% 100%
  3. Format the newly created parition with sudo mkfs.ext4 /dev/sdx1
  4. Close FxBlox app if its currently opened, otherwise open your Fxblox app now
  5. You should now see that your total maximum storage has increased by the size of the drive you installed.

MacOS (Terminal)​

Ext4 is a linux standard that MacOS does not support without some third-party help. We do not need to mount our drive to Mac, we just need to partition and format it. To do so:

  1. Start by downloading the fdisk command-line tool on sourceforge
  2. Install app by double-clicking on the downloaded dpkg file
  3. You will not be able to open it, because of Apple security measures. To circumvent them, open Settings -> Privacy & Security -> Security
  4. Click on Allow Anyways
  5. Connect drive to Mac, if not already done. Click Allow to allow access to drive and now click Ignore to keep it discoverable
  6. Open up your Terminal app by searching your Applications or search with Spotlight by pressing CMD + SPACEBAR, then type Terminal
  7. Identify disk location with diskutil list. You'll want to keep note of the path, it should be something like /dev/disk#
  8. Now start command-line utility with sudo gdisk
  9. Hit n, to create a new GPT partition
  10. Accept the default partition number (1)
  11. Accept the default starting and ending sectors (creates a partition that spans 100% of the drive)
  12. Enter 8300 for the Hex-code/GUID. This is shortform to select the 'Linux Filesystem'
  13. Enter w to write table to disk and exit tool
  14. Hit y to proceed, wait for it to complete, and safely eject drive
  15. Connect your drive to the FxBlox
  16. Close FxBlox app if its currently opened, otherwise open your Fxblox app now and see your total maximum storage increase in the FxBlox app.

Windows (Free Third-Party App)​

Ext4 is a linux standard that Windows does not support without some third-party help. There are various paid and free options out there, but we recommend Parition Master Free by EaseUS.

  1. Install Parition Master Free by EaseUS if not already done
  2. Plug in storage device to your Windows computer, if not already done
  3. Open the app. Select Parition Manager from the left sidebar.
  4. Select the new drive
  5. On the right sidebar, click Create
  6. Make sure EXT4 is selected under File system
  7. Click OK
  8. Click Execute # Task(s) at the bottom of the right sidebar of the main window
  9. Close app and eject drive
  10. Connect your drive to the FxBlox
  11. Close FxBlox app if its currently opened, otherwise open your Fxblox app now and see your total maximum storage increase in the FxBlox app.

Troubleshoot​

  • Drive not recognized in Windows. If your windows computer doesn't see the connected drive, try restarting your computer first. Then look into potentially installing drivers for the storage device.
  • FxBlox not updating storage capacity. If your FxBlox doesn't update the storage the maximum storage capactity even after formatting, try restarting the FxBlox by unplug-plugging it back in.
  • Additional storage devices not showing up under Device Tab. This is a known bug, as of app version 1.6.2.
info

Our apps are open-source and built in React Native for cross-platform support. So if you would like to contribute to the project, that would be greatly appreciated!

- + \ No newline at end of file diff --git a/functionyard/dapps.html b/functionyard/dapps.html index 25c2e6bf..be70d5a0 100644 --- a/functionyard/dapps.html +++ b/functionyard/dapps.html @@ -5,13 +5,13 @@ Decentralized Apps | Functionland - +

Decentralized Apps

Download FxFotos App​

  • Download FxFotos from Google Play for decentralized media storage. FxFotos app is available as a replacement for other Media storage apps (like Apple Photos or Google Photos).
  • We are also working on the FxFiles app which is right now available on Google Play but the integration with Fula protocol is not completed, so acts as a local file storage right now but with very cool features.
- + \ No newline at end of file diff --git a/functionyard/fxblox-app.html b/functionyard/fxblox-app.html index 703ebe3e..e64a273b 100644 --- a/functionyard/fxblox-app.html +++ b/functionyard/fxblox-app.html @@ -5,13 +5,13 @@ FxBlox App Setup | Functionland - +

FxBlox App Setup

Installing the FxBlox App​

warning

If you were helping test nightly firmware releases before official testnet launch, you will be required to format drive to clear out old/incompatible chain data. See more details here.

Initial Setup​

  1. Download the App:
  2. Metamask Wallet: Ensure you have a Metamask wallet for setting up your identity.

App Configuration Steps​

  1. Open Metamask Wallet. We recommend having the opening network set to "Ethereum Mainnet" for a smoother setup process.
  2. Minimize Metamask (not close) and open the FxBlox app.
  3. Read the Terms and Condition and if you agree, then select Agree and Setup Blox in the app.
  4. Enter a memorable password for data encryption and click Sign (Note: This is not your Metamask password).
  5. Complete the connection in the Metamask app, then return to the FxBlox app.
    • You may need to click back to manually return to the app if it does not open Blox automatically after you sign in Metamask
    • It does not matter which chain (Ethereum, Mumbai, etc) you are on in your Metamask wallet.
  6. Tap Connect to new blox.
  7. Manually connect your phone to the "FxBlox" WiFi/Hotspot, and turn off "mobile data", then continue in the app.
  8. Attach at least 500GB of external storage to your FxBlox. Proceed by clicking Next once the app recognizes the storage.
    • If the storage is not recognized ensure that is it correctly formatted by clicking on the Format button.
      • The light will turn purple, to indicate it is formatting. Formatting times depend on storage medium and capacity, so be patient during this time. Device will reboot automatically and eventually start flashing cyan again when it is ready to proceed.
    • If you have an FxBlox version with internal storage, there is no need to attach external storage.
  9. Select your desired WiFi network for the FxBlox and enter the password.
    • If you entered the wrong password, double check you're connected to FxBlox Wifi and just go back to the wifi selection screen to choose and re-enter your password.
  10. Finally, on the last screen reconnect your mobile device to your home WiFi and you can turn on the mobile data again if you want to. The app will confirm the successful setup. Please note the app does not continue if you do not have an active internet connection. When Blox is connected to the internet, the LEDs turn green for 30 seconds and then turn off.
  11. We recommend unplugging and replugging the Blox after the initial setup once for a hard reboot and ensuring that everything is set. After you re-plug the power and it boots, it may reboot automatically once as well.

Troubleshoot​

  • Final step connection issues: Connect to mobile or home wifi, restart the FxBlox app, select Connect to Existing Blox. If that doesn't work, restart the FxBlox device. Close app and reopen to proceed with Connect to new Blox.
  • If Metamask doesn't redirect after signing transaction: Manually go back to the FxBlox app.
  • App issues with Metamask: On some phones, if you cannot get the "Connect" and "sign" prompts in Metamask, you may need to put both the Metamask app and Blox app in Unrestricted mode from the "Battery Optimization". Go to: Settings > Apps > FxBlox > Battery / App Battery > Choose Unrestricted. Do the same for the Metamask app. After the setup, you can return it back to the default of Optimized

Add Multiple FxBlox's​

As of Android/iOS app version 1.6.2, there is not an easy way to add more than one blox to your account. Follow these additional steps if you would like to connect more than one blox:

  1. If not already done, complete setup of your first Blox.
  2. Verify Blox is listed as Authorized under Settings->Blox Discovery. If not, restart your Blox by unplug/plug-ing it back in.
  3. Log Out of your account by going to Settings -> Log Out.
  4. Proceed and complete set-up of your next FxBlox.
  5. Repeat steps 2-4 for all the FxBloxes you have, except for the last one.
  6. When you've finally added the last FxBlox, go to Settings -> Blox Discovery.
  7. All FxBloxes should say Authorized, so select them and click Add selected blox(s).
  8. Verify you can see all of them by going to Blox tab and swiping left/right between them.
info

As you can see the functionality is there, but priotization of an easier way to add them is scheduled for after testnet launch.

Our apps are open-source and built in React Native for cross-platform support. So if you would like to contribute to the project, that would be greatly appreciated!

Format Drive​

If you were eager to test out nightly releases on your own, you may have trouble joining the official launch of the testnet. This is because the blocks from the temporary chains are incompatible with the official testnet blocks. To fix this, you need to erase all previous blocks, easiest way is to format the drive.

To format your drive:

  1. Click on the Blox tab.
  2. Click and hold the Hard Disk you want to format.
  3. When the pop-up shows, click the Format button.
  4. Now wait! The light will turn purple. This process may take more or less than 5 minutes, dependent on the speed of your drive.
  5. The FxBlox will auto-reboot, after it is done the lights will turn off.

FxBlox will automatically connect to testnet and save chain history. You should be able to join testnet now.

- + \ No newline at end of file diff --git a/functionyard/fxblox-hardware-rpi.html b/functionyard/fxblox-hardware-rpi.html index c733d457..3d1cb79e 100644 --- a/functionyard/fxblox-hardware-rpi.html +++ b/functionyard/fxblox-hardware-rpi.html @@ -5,15 +5,15 @@ FxBlox Lite (CM4) | Functionland - +

FxBlox Lite (CM4)

Updating Your FxBlox Lite (RPI)​

warning

If you were helping test nightly firmware releases before official testnet launch, you will be required to format drive to clear out old/incompatible chain data. See more details here.

Step 1: Download the firmware​

info

If this is your very first time setting up your FxBlox Lite, see these instructions first

Step 2: Unzip and Write image to USB​

  1. Unzipping: Unzip rpi_update.zip on your computer. After unzipping there must be a .img file.

  2. Writing Image to USB:

    • In Image File section select rpi_update.img file.
    • In Device section select USB Disk Partion letter.
    • Click Write to start flashing USB Disk.

    Win32 Disk Imager

Step 3: Updating FxBlox​

  1. Turn Off: Ensure your FxBlox (RPI) Lite is turned off.
  2. USB Connection: Connect the USB drive to the BOTTOM USB port of the FxBlox Lite (RPI).
  3. Power On: Turn on your FxBlox Lite (RPI). After about 30 sec, the LED will blink yellow 5 times that indicating the update process started.
    warning

    In update process the LED blinks red and green. This phase is very critical, and any mistake in this phase cause breaking FxBlox Lite (RPI).

  4. After about 10 minutes, the LED blinks red only. Remove the USB drive.
  5. Restart the FxBlox Lite (RPI) by unplugging and plugging back the power.

Step 4: Post-Update​

Be patient on the first boot, post-update! The FxBlox automatically reboots 3 times, and will go through a series of lights. This full process should take about 30 minutes to fully process the update and show the FxBlox WiFi.

Please wait for 10 minutes before doing anything. You may think it is done or stuck or it is turned off, but be sure that it is processing the update for 10 minutes after the frist boot. We will add LED indicators in the future updates.

info

Future firmware updates will be automatic, eliminating the need for manual updates.

First Time Setup​

If this is your very first time setting up your FxBlox Lite (RPI), you will not be able to install the latest usb update. The reason for that is because "updating via usb" feature was not added in until a later firmware version.

To automatically get that version, you need to connect the Blox to the wifi first. You can do so by following these steps:

  1. Download the latest iOS/Android app.
  2. Follow prompts to create password and connect Metamask.
  3. If possible, skip format disk. *
  4. Connect Blox to wifi. *
  5. Now, wait 24 hours for the update to install. *
  6. With new version installed, you can proceed with the normal upgrading process.

Troubleshoot​

  • You may need to wait somewhere between 20-30 seconds for the button to appear.
  • You may not get a setup complete message afer connecting to wifi, because you don't have the latest firmware version. Check your router settings to see if it connected properly.
  • We recommend waiting 24 hours, because there are no indicators for when it is completed.
- +

Step 2: Unzip and Write image to USB​

  1. Unzipping: Unzip rpi_update.zip on your computer. After unzipping there must be a .img file.

  2. Writing Image to USB:

    • In Image File section select rpi_update.img file.
    • In Device section select USB Disk Partion letter.
    • Click Write to start flashing USB Disk.

    Win32 Disk Imager

Step 3: Updating FxBlox​

  1. Turn Off: Ensure your FxBlox (RPI) Lite is turned off.
  2. USB Connection: Connect the USB drive to the BOTTOM USB port of the FxBlox Lite (RPI).
  3. Power On: Turn on your FxBlox Lite (RPI). After about 30 sec, the LED will blink yellow 5 times that indicating the update process started.
    warning

    In update process the LED blinks red and green. This phase is very critical, and any mistake in this phase cause breaking FxBlox Lite (RPI).

  4. After about 10 minutes, the LED blinks red only. Remove the USB drive.
  5. Restart the FxBlox Lite (RPI) by unplugging and plugging back the power (Make sure an external storage, without the img files, is plugged to the bottom port of blox before powering it back on or the sequence of lighting you would see might defer from this documentation). The best partitioning format for storage devices is ext4 but vfat is also acceptable.

Step 4: Post-Update​

Be patient on the first boot, post-update! The FxBlox automatically reboots 3 times, and will go through a series of lights. This full process should take about 30 minutes to fully process the update and show the FxBlox WiFi.

Please wait for 10-30 minutes before doing anything. You may think it is done or stuck or it is turned off, but be sure that it is processing the update for 10-30 minutes after the frist boot. At the end of process the LED starts blinking light blue (cyan) consistently if an external storage is plugged to the blox. If no external storage is plugged, then you cannot see this sequence.

info

Future firmware updates will be automatic, eliminating the need for manual updates.

First Time Setup​

If this is your very first time setting up your FxBlox Lite (RPI), you will not be able to install the latest usb update. The reason for that is because "updating via usb" feature was not added in until a later firmware version.

To automatically get that version, you need to connect the Blox to the wifi first. You can do so by following these steps:

  1. Download the latest iOS/Android app.
  2. Follow prompts to create password and connect Metamask.
  3. If possible, skip format disk. *
  4. Connect Blox to wifi. *
  5. Now, wait 24 hours for the update to install. *
  6. With new version installed, you can proceed with the normal upgrading process.

Troubleshoot​

  • You may need to wait somewhere between 20-30 seconds for the button to appear.
  • You may not get a setup complete message afer connecting to wifi, because you don't have the latest firmware version. Check your router settings to see if it connected properly.
  • We recommend waiting 24 hours, because there are no indicators for when it is completed.
+ \ No newline at end of file diff --git a/functionyard/fxblox-hardware.html b/functionyard/fxblox-hardware.html index 46873809..505abb38 100644 --- a/functionyard/fxblox-hardware.html +++ b/functionyard/fxblox-hardware.html @@ -5,13 +5,13 @@ FxBlox Lite Plus (RK1) | Functionland - +

FxBlox Lite Plus (RK1)

Updating Your FxBlox Lite Plus (RK1)​

warning

If you were helping test nightly firmware releases before official testnet launch, you will be required to format drive to clear out old/incompatible chain data. See more details here.

Step 1: Download the Firmware​

Step 2: Unzip and Transfer to FAT32 USB​

info

Before starting, make sure that your USB stick is 32GB or smaller. Anything larger than 32GB may not work due to the FAT32 file system limitations. Instructions must be done in this order to avoid complications.

  1. Use a USB drive formatted as FAT32.

  2. First, unzip minimal_update.zip onto your computer.

  3. Then, copy unzipped files to USB drive to avoid potential file corruption.

  4. Make sure to copy unzipped files directly to the root of the USB drive. So the files boot.scr, update.img.0, update.img.1 and update.img.2 , etc... must be in the root of your USB disk.

Step 3: Updating FxBlox​

  1. Ensure your FxBlox is turned off.

  2. Connect the USB drive to the top USB port of the FxBlox. (Only the top port is designed for updates)

  3. Turn on your FxBlox. The LED will display green, blue, and then yellow, indicating the update process.

  4. After about 15 minutes, the LED blinks green and blue. Remove the USB drive.

  5. Restart the FxBlox by unplugging and plugging back the power.

Step 4: Post-Update​

Be patient on the first boot, post-update! The FxBlox automatically reboots 3 times, and will go through a series of lights. This full process should take about 30 minutes to fully process the update and show the FxBlox WiFi.

Leave it plugged in! At any time, you may think it is done or stuck or it is turned off, but be rest assured that it is processing the update. After automatic restarts are done, the FxBlox will proceed to show a variety of colors including: blue, green, cyan, yellow, off, red; in that order. This process make take around 10 minutes until LEDs turn flashing cyan.

info

Future firmware updates will be over the air, eliminating the need for manual updates.

- + \ No newline at end of file diff --git a/functionyard/fxfotos.html b/functionyard/fxfotos.html index 37c24e84..e7b6d170 100644 --- a/functionyard/fxfotos.html +++ b/functionyard/fxfotos.html @@ -5,14 +5,14 @@ FxFotos Apps | Functionland - +

FxFotos Apps

Use case​

FxFotos is a decentralized media manager. It automatically syncs up your media files (pictures and videos), and allows you to open and view media files on your phone. It comes with features such as:

  • Thumb scroll to quickly browse earlier dates
  • Pinch to change number of columns
  • Highlights
  • Video and Photos player support for a variety of formats
  • Basic search functionality

Use FxFotos App​

  1. Install FxFotos from Google Play

  2. Wait for a minute for the loading bar to disappear (This makes the experience smoother and just needed for the first time)

It is smoother if you open Metamask here before continuing with login
  1. Click on the profile icon on the top right

  2. Click allow notifications

  3. Enter an arbitrary password (This can be the same or different from FxBlox and other dApps). Make sure you do not lose this password as there is no way to retrieve it.

  4. Click Login and complete the signing steps in Metamask. After which you will be redirected back to FxFotos automatically.

  5. After a successful login, you will see relevant information about your account:

  • Your Did: This is your decentralized ID based on your password
  • Your Content Root CID (This is hidden by default): This value is needed in order to retrieve your data on another account. We are working to enhance the protocol side to make this value retrievable but right now if you lose it there is no retrieval method. This value changes after each upload (Private)
  • Your Private Key (This is hidden by default): This value is needed in order to retrieve your data on another account. There is no need to save this as this is automatically being created from the DID (Private)
  • Fula Account: This is the Fula account that the tokens/payments for backing up your data will be deducted from. For testnet initially there is no charge but also no guarantee for hte data you upload (Not private)
  • Your PeerID: This is the peer id that the application uses to connect to other nodes (Not private)
  1. Click on Choose a pool for uploads and select a pool close to you. If you make a mistake, you can Clear pool selection and select another pool.

  2. Click back and go to main screen.

  3. To upload/backup a media file, click on it to open, then tap one time on the screen and you see a back up icon shown at the bottom of screen.

info

We have deactivated the auto-sync initially during testnet launch to give us better troubleshooting and debugging opportunity. We thank you for your patience.

How to see my uploaded/backed-up data?​

We are working on a web interface that shows you the backed up data, but for now there is an unreleased app which you can copy the "Private Key" and "root Cid" From FxFotos over to that application, and it shows you the list of uploaded files. The app does not transfer the keys outside or to any third party and is totally safe. It can be downloaded from here:

Future Plans​

  1. Completing the browser based application
  2. Sharing with others. You can easily share the uploaded files with others in or outside of Fula network and set expiry date, give write permission, and anything you can do on the cloud. This feature already exists in the protocol and we just need to implement the required interfaces for it.
  3. Integration with AI. We are working on integrating the application with on-device face-detection algorithms.
  4. Easy import from Google/Apple Photos. We implement a feature to easily migrate your files over from other applications.
- + \ No newline at end of file diff --git a/functionyard/join.html b/functionyard/join.html index 01644f8b..df159593 100644 --- a/functionyard/join.html +++ b/functionyard/join.html @@ -5,13 +5,13 @@ Joining Testnet | Functionland - +

Joining Testnet

Joining the Testnet​

  1. In the FxBlox App, go to the Users Page and click Join Testnet
  • Or you can manually visit the testnet page at Functionyard Testnet and enter your Indiegogo campaign order details and account id from the Blox app.
  • If the Account and Join buttons are greyed out, it means the blox is still syncing the chain data. It may take a few minutes to up to a day depending on the speed of the attached USB and internet speed. We will add a more visual indicator of this in future releases.
warning

If you were helping test nightly firmware releases before official testnet launch, you will be required to format drive to clear out old/incompatible chain data. See more details here.

  1. In the FxBlox app, go to Settings > Pools. Join a pool nearest to your city. Choose the one closest to you from the list. Please note, that if you choose a pool that is far from you, the request will automatically rejected by the system.
  1. Wait for approval from 5 pool members (may take up to 24 hours right now).
  1. Once approved, the pool button changes to "Leave". You can now start storing and earning.
- + \ No newline at end of file diff --git a/functionyard/metamask.html b/functionyard/metamask.html index 1b73f881..f0efacb8 100644 --- a/functionyard/metamask.html +++ b/functionyard/metamask.html @@ -5,13 +5,13 @@ Token in Metamask | Functionland - +

Token in Metamask

Adding BORG Token to MetaMask on Mumbai Chain​

This guide explains how to add the BORG token, which is not automatically listed in MetaMask, to your wallet on the Mumbai test network. There is an easy way and a manual way!

Easy Way (Desktop)​

  1. Adding Mumbai Network to Metamask: First, open this link to add Mumbai testnet to your MetaMask. Now click on the Add to Metamask button. It will open your Metamask extension on Chrome and add Mumbai Network to it (if not already added).

mumbai connect button

  1. Adding the BORG token on Mumbai: First, open this link to add Borg to Mumbai network and on the bottom right (you may need to scroll), click on the Send Request button. It opens your Metamask extension on Chrome and adds the BORG token to the Mumbai network (if not already added).

Easy Way (Mobile)​

In Metamask mobile, you have to be using the browser that is available in the MetaMask app for the sites to recognize your Metamask wallet.

  1. Copy/Paste https://chainlist.org/chain/80001 into the Metamask web browser.
  2. Click on Connect Wallet under where it says Mumbai. Confirm popup.
  3. Copy/Paste, into a new tab of the Metamask web browser, https://docs.metamask.io/wallet/reference/wallet_watchasset/?type=ERC20&options[address]=0x99a8b2B50c4bFBf916Add5DFdf680fc873FA81f4&options[symbol]=BORG&options[decimals]=18&options[image]=https://raw.githubusercontent.com/functionland/sugarfunge-explorer/master/assets/BORG.svg&options[tokenId]=BORG.
  4. Scroll all the way down to the Send Request button. Confirm popup.

Manual Way (Mobile/Desktop)​

Step 1: Select the Mumbai Network in MetaMask​

Ensure you have MetaMask installed and select the Mumbai Testnet. If Mumbai is not listed:

  1. Select "Add Network" manually.

    • Mobile: First, click on circled button. Then, Add Network

    • Desktop: First, click on circled button. Then, Add Network

    • Alternatively, you can go to Settings -> Networks -> Add network, then Custom Networks or Add a network manually.

  2. Enter the following details:

    • Network Name: Mumbai Testnet
    • New RPC URL: https://rpc-mumbai.maticvigil.com/
    • Chain ID: 80001
    • Currency Symbol: MATIC
    • Block Explorer URL: https://polygonscan.com/

Step 2: Add BORG Token​

  1. Open the MetaMask extension
  2. Go to the Assets or Tokens tab
  3. Scroll down and click Import Tokens
  4. Switch to the Custom Token tab
  5. Enter the BORG Token Contract Address: 0x99a8b2B50c4bFBf916Add5DFdf680fc873FA81f4
    • The token symbol and decimals should auto-fill. If not, you may need to enter them manually.
  6. Click Add Custom Token
  7. Review the token details and click Import Tokens

Congratulations, the BORG token is now added to your MetaMask wallet on the Mumbai chain!

Troubleshoot​

  1. BORG token no longer shows in Metamask wallet. This may be because the Mumbai chain rpc provider is unavailable. You can remedy this by redoing the steps outlined in this guide (easy way or manual way).
  2. Error when adding Mumbai chain. This may occur because the Mumbai chain rpc provider is unavailable, if you are selecting a provider from the list, make sure that it has a green check mark for both Score and Privacy. This will most likely occur when doing the manual way.

mumbai chain options

- + \ No newline at end of file diff --git a/getting-started.html b/getting-started.html index 48498cd3..0c896897 100644 --- a/getting-started.html +++ b/getting-started.html @@ -5,13 +5,13 @@ Getting Started | Functionland - +

Getting Started

In order to start developing your own DApps on Fula, complete these two steps:

  1. Get the Box server up and running.

  2. Develop your own front-end, leveraging the Fula API.

- + \ No newline at end of file diff --git a/getting-started/box-setup.html b/getting-started/box-setup.html index c862ec5b..1fab950d 100644 --- a/getting-started/box-setup.html +++ b/getting-started/box-setup.html @@ -5,13 +5,13 @@ Running a Box locally | Functionland - +

Running a Box locally

The easiest way to get your Box server running locally is to clone our repo and use docker.

  > git clone https://github.com/functionland/fula
> docker-compose -f docker-compose.dev.yaml up

Next, take note of the PeerID the Box server creates on startup. You can find this by taking a look at your docker-compose logs for the following -

box_1             | Swarm listening on /dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star/p2p/12D3KooWPeEhynWyG7dHytppDP6ZG6jhEv7LcDLWsExGq1YD784E

Now head over to using the samples to verify that the Box server is running properly and you are able to connect to it.

- + \ No newline at end of file diff --git a/getting-started/fula-client.html b/getting-started/fula-client.html index 9050b18b..48682aba 100644 --- a/getting-started/fula-client.html +++ b/getting-started/fula-client.html @@ -5,13 +5,13 @@ The Fula Client Library | Functionland - +

The Fula Client Library

Fula client lets you connect your web application to the Box using libp2p. It helps DApp developers to use a Box as the back-end for their applications. You can use the File and Graph APIs to store and retrieve your data.

Installation​

The Fula client is available in javascript, and it can be installed like any other NPM package:

npm i @functionland/fula

Alternatively, you can use the CDN version:

<script src="https://cdn.jsdelivr.net/npm/@functionland/fula/dist/index.js"></script>

Usage​

Once you've imported the package in your project, in order to connect to your Box you should create a client:

import {createClient} from '@functionland/fula'

const fulaClient = await createClient();

Now that you have a Fula client instance, you can connect it to the Box server. You must have the base58 PeerID string provided by your Box server.

await fulaClient.connect(serverId)

Helper Libraries​

In addition to the Fula client library you might also find one of our framework helpers useful.

We currently support:

What Next?​

Now that you are up and running, head on over to the Fula Reference API to see everything you can do with Box.

WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

- + \ No newline at end of file diff --git a/getting-started/rpi-setup.html b/getting-started/rpi-setup.html index 10876db5..e306003e 100644 --- a/getting-started/rpi-setup.html +++ b/getting-started/rpi-setup.html @@ -5,13 +5,13 @@ Installing Box on Raspberry Pi OS | Functionland - +

Installing Box on Raspberry Pi OS

WIP Alert

Please note: these instructions remain a work in progress as we continue to evolve, refine and perfect the Fula API. Make sure to check back soon for more details!

Pre-requisites​

It is assumed you have taken the necessary steps to appropriately secure the linux environment before installing the Box software.

For example, you should change the default pi user password if starting from the current release of raspberry Pi OS.

You might also create a different user with root priviledges and remove ssh / sudo access for the pi user.

This guide was written using Debian GNU/Linux 11 (bullseye) on a Raspberry Pi 4.

Setup Steps​

  1. Install git to clone the FULA repo.
  > sudo apt update
> sudo apt install git
  1. Install docker and docker-compose according to your linux distro. If you get an error during the install process see troubleshooting below.

  2. Create a non-sudo user for the Box server app and other dependencies to run under and add them to the docker group.

  > sudo adduser -m fuman
> sudo passwd fuman
> sudo usermod -a -G docker fuman

Log in as 'fuman' in a new shell

  > ssh fuman@yourhost
  1. Run docker in rootless mode.

  2. Start Box and it's dependencies.

  > git clone https://github.com/functionland/fula
> docker-compose -f docker-compose.dev.yaml up
  1. Verify you are able to connect to the Box on the rPi from a sample DApp. The most straightforward way to do that is to follow the regular 'getting-started' process. On the step to connect to a Box just enter the PeerId of the Box running on your rPi instead of the one that is running on your local dev. machine.

Troubleshooting​

Ensure the there is a directory matching kernel version in /lib/modules

- + \ No newline at end of file diff --git a/getting-started/using-samples.html b/getting-started/using-samples.html index 4e6f21a4..8c8e7a95 100644 --- a/getting-started/using-samples.html +++ b/getting-started/using-samples.html @@ -5,13 +5,13 @@ Using Fula Samples | Functionland - +

Using the Fula Samples

All the Fula samples can be found in the Fula GitHub repo under examples.

To get things started and give you an idea of how to work with the Graph API, we will set up the TODO Sample App.

Running the TODO Sample​

If you followed the previous step, it should already be running. All you have to do is navigate to http://localhost:3001 in a browser.

There you should see the following dialog:

Todo Connect Prompt

Todo Connect Prompt

Connect to the Box​

Copy the PeerId from the Box server logs available in the previous step and paste it into the text input.

After clicking 'Connect'...

The app should redirect you to the TODOs app.

Todo App

Todo App

Editing the Sample​

Open /path/to/fula/examples/react-todo-app/src/components/TodoList.tsx in your favorite editor.

Change the headline from -

<h1>Functionland Todo App</h1>

to -

<h1>My Todo App</h1>

You should now see the change reflected in your browser.

Congrats! Your Box server is now up and running, and you've verified you can connect to it. You have also learned how to update one of the samples so that you can use it as a starting point for your own DApp.

Now that you are up and running, head on over to the Fula Reference API to see everything you can accomplish with Box.

- + \ No newline at end of file diff --git a/index.html b/index.html index 906ff0f3..bcf41856 100644 --- a/index.html +++ b/index.html @@ -5,13 +5,13 @@ Welcome | Functionland - +

Welcome to Functionland

Functionland was founded on a core set of Web3 principles. At the heart of these principles is a simple premise: We each have an inalienable right to own our own data.

We set out to build a better future around this simple premise. We started by developing an app that liberates a set of "own data" we think is particularly important to people: personal home photos and video.

We developed Fotos as a Web3 alternative to available photo and video sharing and backup applications.

But while developing Fotos, we realized there are still many pieces missing from the Web3 stack; pieces that are necessary to achieving the better future we envision.

What we realized:

There is currently no single chain agnostic token we can use to pay for decentralized infrastructure or software services.

Enter $FULA token

There is currently no easy way for us to take advantage of cloud convenience without losing our data the moment we stop paying the bills. In other words, once you start paying, you can never stop.

Enter BAS

There is currently no modular, open-source, datacenter-grade server hardware option available. Hardware that is fully customizable and aesthetically appealing enough to sit comfortably in your home.

Enter Box

There are currently no freemium options for consumers to compute on and store larger sets of data.

Enter Fula local pools

There is currently no platform based on open, interoperable specifications that enables developers to write permissionless, decentralized apps for consumers and get paid for doing so.

Enter the Fula API

We decided to build them. We call it the Fula network.

Fula Network Architectuer

Tell me more about the Fula network. How does it work?​

To become a truly viable alternative to Big Tech cloud storage, we need to guarantee:

  • reliability

  • availability

  • security

To guarantee reliability, availability and security, we designed a system that utilizes an already existent decentralized web.

The Fula network is peer-to-peer architecture designed with open protocols and specifications such as libp2p, IPFS and decentralized identity.

This allows us to achieve an unprecedented level of interoperability and makes every participant in the ecosystem future proof, including DApp developers.

By developing on the Fula platform, you earn $FULA from your open-source contributions. At the same time, you avoid locking yourself in to a single platform with proprietary APIs and archaic approval processes.

By decoupling data from the application, DApp developers can focus on providing rich user experiences without having to worry about what happens to customer data.

It also means Box customers will not be locked in to using any one, single DApp.

The Fula network provides a free, open market for service providers. Box customers are not just consumers; they can become producers within this new ecosystem too.

In short, it's a positive sum protocol for everyone.

Like what you hear? Become a pioneer. Join us on our journey to bring Web3 into the mainstream.

You can do that by:

  • backing us on indiegogo

  • heading over to Fula API docs to learn how to develop your own DApps on the Box

  • providing feedback/input on our RFCs

  • sign into one of our socials and join the conversation!

- + \ No newline at end of file diff --git a/mvp.html b/mvp.html index fab9b74f..151161b6 100644 --- a/mvp.html +++ b/mvp.html @@ -5,13 +5,13 @@ Minimum Valuable Product | Functionland - +

Minimum Valuable Product

The following describes how the Fula network software will work from the network participant's perspective.

Fotos

Pools

- + \ No newline at end of file diff --git a/mvp/admin-reporting.html b/mvp/admin-reporting.html index c77d70fb..4eaebbb5 100644 --- a/mvp/admin-reporting.html +++ b/mvp/admin-reporting.html @@ -5,13 +5,13 @@ Admin Reporting & Alerts | Functionland - +

Admin Reporting & Alerts

- + \ No newline at end of file diff --git a/mvp/box-admin.html b/mvp/box-admin.html index 871a29ee..e68027ba 100644 --- a/mvp/box-admin.html +++ b/mvp/box-admin.html @@ -5,13 +5,13 @@ Box Admin | Functionland - +

Box Admin

After loading the Box Admin DApp.

I am asked to enter the username and password I created during Unboxing

After logging in.

I am presented with a dashboard where I can:

  • update my personal info
  • manage my $FULA token account
  • view a list of Boxes that I own and their resource usage
  • view installed DApps
  • manage private pool
  • manage public pools
  • manage other members of their Box
- + \ No newline at end of file diff --git a/mvp/forgot-password.html b/mvp/forgot-password.html index 93abe849..d36437d7 100644 --- a/mvp/forgot-password.html +++ b/mvp/forgot-password.html @@ -5,14 +5,14 @@ Forgot Password | Functionland - +

Forgot Password

If I ever lose or forget my password. I can recover it by...

  • email recovery?
  • two factor authentication?
    • email + mobile device?
  • having a group of friends multisig it back to me?
- + \ No newline at end of file diff --git a/mvp/fotos.html b/mvp/fotos.html index aef80608..0d6fe260 100644 --- a/mvp/fotos.html +++ b/mvp/fotos.html @@ -5,13 +5,13 @@ Fotos | Functionland - + - + \ No newline at end of file diff --git a/mvp/fotos/availability.html b/mvp/fotos/availability.html index c460ff9a..df4aba0c 100644 --- a/mvp/fotos/availability.html +++ b/mvp/fotos/availability.html @@ -5,13 +5,13 @@ Fotos Availability | Functionland - +

Fotos Availability

Acceptance Criteria​

You uploaded a photo to your Fula API server.

Your Fula environment goes offline and you are still able to retrieve the photo from a second Fula environment in your pool.

Preconditions​

  1. You have already set up a cluster.

  2. You have already set up Fotos with your own wallet account and connected it to your Fula API server.

  3. You already backed up a photo that you would like to share.

Steps​

Here is a video demonstrating the following steps.

  1. Delete the photo from your device by long pressing the photo and selecting the 'delete' icon.

  2. Remove the first Box from your list and add the second using the multiaddress from the server logs of the second Box.

  3. Verify that the second Box is in fact storing the image and that you are able to retrieve it by tapping on the placeholder thumbnail that appears in the deleted image's place.

- + \ No newline at end of file diff --git a/mvp/fotos/backup.html b/mvp/fotos/backup.html index 1b3082f7..4a01a209 100644 --- a/mvp/fotos/backup.html +++ b/mvp/fotos/backup.html @@ -5,13 +5,13 @@ Fotos Backup to Fula environment | Functionland - +

Fotos Backup to Fula environment

Acceptance Criteria​

You can backup a photo to your Fula environment and retrieve it from the Fula environment at a later date.

Preconditions​

  1. You already have a Fula environment running.

  2. You have already set up Fotos with your own wallet account and connected it to your Fula environment.

Steps​

Here is a video demonstrating the following steps.

  1. Tap on a photo to enter browse mode and tap the 'upload to cloud' icon in the top right.

  2. After the image has uploaded succesfully you should see a 'cloud with a checkbox' icon and a 'share' icon in browse mode for the image.

  3. You can verify that the Fula environment is in fact storing the image for you and that you are able to retrieve it by deleting the image from your device and tapping on the placeholder thumbnail that appears in its place to download it.

- + \ No newline at end of file diff --git a/mvp/fotos/setup.html b/mvp/fotos/setup.html index 15b5427a..2775ccb4 100644 --- a/mvp/fotos/setup.html +++ b/mvp/fotos/setup.html @@ -5,13 +5,13 @@ Fotos Setup | Functionland - +

Fotos Setup

Acceptance Criteria​

You set up Fotos with your wallet account and connect it to the Fula API server.

Once set up correctly you are able to perform all other Fotos stories.

Preconditions​

  1. You have already downloaded and installed Fotos.

  2. You already have a Fula environment running and have acquired the Fula API server's multiaddress from the server logs that is reachable from your phone.

Steps​

Connect Fotos to your wallet​

Here is a video demonstrating the following steps.

  1. Go to Account -> Connect your wallet

  2. Authorize the Dapp from your wallet.

  3. Tap 'sign your address' when redirected back to Fotos.

  4. Perform the signing request from the wallet.

Connect Fotos to your Fula API server​

Here is a video demonstrating the following steps.

  1. Acquire the Fula API server multiaddress from it's server logs.

  2. Copy the Fula API server's multiaddress to your clipboard.

  3. Go to Account -> Boxes.

  4. Add a new Box.

    a ) Give the Box a name for identification purposes (can be anything).

    b ) Paste the Box's multiaddress .

- + \ No newline at end of file diff --git a/mvp/fotos/sharing.html b/mvp/fotos/sharing.html index 2023f2f6..f60b54f6 100644 --- a/mvp/fotos/sharing.html +++ b/mvp/fotos/sharing.html @@ -5,13 +5,13 @@ Fotos Sharing | Functionland - +

Fotos Sharing

Story​

You can share a photo with a friend.

Preconditions​

  1. You already have a running Fula environment.

  2. You have already set up Fotos with your own wallet account and connected it to your Fula environment.

  3. You already backed up a photo that you would like to share.

  4. You have already set up Fotos on a second device you would like to share the photo with (connected to the same Fula environment with a different wallet).

Steps​

Have your friend send you there DID​

Here is a video demonstrating the following steps.

  1. Tell them to go to 'Account' -> 'share' icon.

  2. Tell them to send their DID to you in a secure/private channel (eg/ copy to their clipboard and send it to you as an email) back to your friend.

Here is a video demonstrating the following steps.

  1. Tap on the photo to share.

  2. Tap the 'share' icon.

  3. Paste the DID that your friend sent you.

  4. You should see a 'shared' message stating the asset was added to a shared collection. Tap 'yes' to get the sharing link and send it over a secure/private channel.

Your friend views the shared photo​

Here is a video demonstrating the following steps.

  1. Have your friend tap on the link and it should open Fotos on their phone and display the image you shared with them.
- + \ No newline at end of file diff --git a/mvp/my-account.html b/mvp/my-account.html index f5bc65d6..c3b75f71 100644 --- a/mvp/my-account.html +++ b/mvp/my-account.html @@ -5,14 +5,14 @@ My Account | Functionland - +

My Account

On my account page. I am able to edit my password.

- + \ No newline at end of file diff --git a/mvp/pools.html b/mvp/pools.html index 79eb38ec..4cece3c1 100644 --- a/mvp/pools.html +++ b/mvp/pools.html @@ -5,13 +5,13 @@ Pools | Functionland - + - + \ No newline at end of file diff --git a/mvp/pools/storage-provide.html b/mvp/pools/storage-provide.html index cfe6ca42..066a81ec 100644 --- a/mvp/pools/storage-provide.html +++ b/mvp/pools/storage-provide.html @@ -5,13 +5,13 @@ Providing Storage | Functionland - +

Providing Storage

Acceptance Criteria​

You see your balance increase on the chain explorer after uploading a file to your node using Fotos.

Preconditions​

  1. You are a running a fula testnet environment.

  2. You have already set up Fotos and connected it to your Box running in the fula testnet environment.

Steps​

Here is a video demonstrating the following steps.

  1. In the Fotos app, tap on a photo to enter browse mode and tap the 'upload to cloud' icon in the top right.

  2. Take note of the CID for the file that you just uploaded.

  3. Add the file you uploaded to your IPFS node's MFS (so that it can be found by the proof engine).

  4. Take note of your Account ID.

  5. Let the proof engine know that you are storing the file by creating a new manifest for the file you just uploaded.

  6. Restart the proof engine to ensure it picks up the latest manifest.

  7. See that your balance has increased either by viewing the proof engine logs from docker-compose or by looking for your account in the chain explorer.

- + \ No newline at end of file diff --git a/mvp/privacy-dashboard.html b/mvp/privacy-dashboard.html index 8dd3d324..8adfd808 100644 --- a/mvp/privacy-dashboard.html +++ b/mvp/privacy-dashboard.html @@ -5,13 +5,13 @@ privacy-dashboard | Functionland - +

privacy-dashboard

  • I can see all of my data and what DApps are creating/encrypting content.
- + \ No newline at end of file diff --git a/mvp/questions.html b/mvp/questions.html index 3eb10ccf..bfa92537 100644 --- a/mvp/questions.html +++ b/mvp/questions.html @@ -5,13 +5,13 @@ questions | Functionland - +

Questions about the MVP

New Questions​

  • who has control over my pinset?

    • only I can delete them?
  • what should happen if someone gets access to my phone?

Local Pools​

  • local pools

    • public pools = anyone can join?
    • private pools = you must have invite or approval from a pool admin?
  • global pools = ?

  • is there a name for a pool of Boxes that I own?

    • is the availability story for pools of Boxes that I own only or for local pools (private + public)?
  • what happens if everyone in my pool pulls the plug all of a sudden?

  • can I choose to join as either a consumer or a producer or do I have to join as both a consumer and a producer?

  • what happens when I run out of $FULA tokens to:

    • the data stored by peers in my local pool?
  • does any member of a pool have administrator privileges?

  • what are the tradeoffs we are making that Filecoin is not making?

Storage​

  • when I join a pool should I be able to tell it how much storage I want to allocate to the pool?

  • what happens if I offer 1 Tb and there is no demand?

  • whitelisting

    • where will I whitelist photos and other files/data to be included in a pool?

    • is there a separate whitelist for each pool I am a member of?

  • member of multiple pools?

    • should I select what photos to back up in each pool I join?
  • if I am the only member of my local pool, will I have to pay myself?

  • how does proof of resource work and what is difference between this and proof of space-time / proof of replication?

  • how will I know that my data is safely stored and that I won't have to worry about data loss?

  • confirmation = if database is replicated then only protection is encryption (no gatekeeping process)?

  • sharing

    • in order to share a photo with someone I need to give them access - does that mean they need to be a member of my pool or are the concepts decoupled?

Computation​

  • how will I know that my data is being shared with peers to be computed on in a way that preserves my privacy?

Administration​

  • if I lose or forget my account password then how will I recover it?

    • email recovery means no zero knowledge?

    • other options

      • two factor auth?

$FULA Account​

  • should I know what my $FULA is being spent on?
    • eg/ in the last month I spent 50 $FULA on Fotos and 200 on 'Pool A' and 150 on 'Pool B'?
  • should there also be a way to tell my balance and earnings over time?
  • should I give approval before $FULA is spent?
- + \ No newline at end of file diff --git a/mvp/technical-questions.html b/mvp/technical-questions.html index ecabd5ca..8638a33e 100644 --- a/mvp/technical-questions.html +++ b/mvp/technical-questions.html @@ -5,13 +5,13 @@ technical questions | Functionland - +

Questions about the MVP

Local Pools​

  • what is purpose of the swarm key in a public pool?

  • how is PoR going to work on an rPi?

    • for our PoR algo to work on the rPi we are going to have to consume a lot less resources

Hardware​

  • what is devkit and what are framework extension cards for?
- + \ No newline at end of file diff --git a/mvp/unboxing.html b/mvp/unboxing.html index 42113852..e41f8472 100644 --- a/mvp/unboxing.html +++ b/mvp/unboxing.html @@ -5,7 +5,7 @@ Unboxing | Functionland - + @@ -16,7 +16,7 @@ I am told to load the Box Admin DApp on another device.

When I first load the Box Admin DApp. I am prompted to enter some information about my identity and to create a new administrative password.

After creating my account. I am redirected to a Box Admin dashboard.

- + \ No newline at end of file diff --git a/reference-api.html b/reference-api.html index 181891bc..11c980b6 100644 --- a/reference-api.html +++ b/reference-api.html @@ -5,13 +5,13 @@ Reference | Functionland - +

Fula API Reference

The Fula API includes the following:

  • a Graph API for storing and querying structured data (JSON) over a graphql interface

  • a File API for uploading and retrieving files

Typical API Usage​

The File and Graph APIs can be used together to build many different types of DApps.

To better understand how they work together, here is an illustration of the basic flow you would use if you wanted to build your own photos DApp.

At a high level you will write a client that enables the user to upload a bunch of files and retrieve a list of the files so that they can be displayed in your DApp.

In order to do this you need to tell the Graph API where to store the collection of photos. You can give this collection any name you choose.

Photo Upload​

Photo-Upload

Photo-Upload

Gallery-Retrieve

Gallery-Retrieve

Under the Covers​

To understand how the Fula client connects to a Box, it may help to understand what is going on under the covers.

The following Box <-> Client class diagram shows relationships and responsibilities for each component.

Client Box architecture

- + \ No newline at end of file diff --git a/release/testnet-alpha.html b/release/testnet-alpha.html index 3ed06320..37cc6df2 100644 --- a/release/testnet-alpha.html +++ b/release/testnet-alpha.html @@ -5,13 +5,13 @@ Protocol Testnet Alpha Pre-release | Functionland - +

Protocol Testnet Alpha Pre-release

Last updated: July 29, 2022

What is it?​

The protocol testnet alpha pre-release includes the Fotos mobile application and some of the Fula components that will be pre-installed on FxBlox customer's raspberry Pis when they are shipped.

What to expect​

The software we are delivering to you today can give you an idea of how the Fotos mobile app will back up and store your photos to the Fula testnet environment.

Once you have everything set up, you should have a Fula API server, IPFS and Fula funge components all talking to each other running on your host machine.

You should be able to upload your media using Fotos from your mobile phone to the Fula testnet environment encrypted with a key from your own wallet.

You can also get an idea of how a decentralized identity might be generated from your and your friend' wallets in order to enable sharing of photos with each other.

Lastly, you can get a first glimpse of how backing up files (that you uploaded with Fotos) will cause rewards to be generated for you on the Fula testnet blockchain.

Requirements​

  • one Android phone

  • a second Android phone for sharing photos with a friend

  • your own computer that can run Docker

    • Linux is required for the last step
  • each phone must be on the same network as the computer where the Fula testnet environment is running

  • a mobile ethereum compatible wallet (eg/ Metamask or Trust Wallet)

Submitting feedback​

We would love to know how it went for you!

Especially if you cannot complete any of the steps due to a bug you encountered or because you cannot satisfy the above requirements.

You can send us feedback via Github or as an email.

Here is some boilerplate text you can copy/paste when you are ready to send the feedback.

Subject: Protocol testnet alpha

Feedback Type: [ Bug | Feature Request ]

Feedback:

[ I completed all of the steps successfully. This rocked but I have a few suggestions for the next release...]

OR

[ I was unable to complete X step(s). The following happened when I tried to complete the step: ...]

If you believe the issue is happening in the Fula API then you can create an issue on the Fula repo and include the docker-compose server logs.

If you believe the issue has something to do with the testnet setup you can create an issue on the testnet repo and include the docker-compose server logs.

If you believe the issue is happening in the Fotos mobile client then you can create an issue on the Fotos repo and describe what is going wrong.

If you don't know where the problem exists or don't have a Github account then please send us an email and attach the server logs if you are reporting a bug.

To output the server logs to a file​

Open a terminal and enter the following in the same directory that you ran docker-compose in the previous steps.

  > docker-compose logs >  out.log

Beware of Risks​

The Functionland protocol testnet alpha pre-release includes client side encryption as a first layer of security to help prevent others from gaining access to your photos and video.

However, because the software we are delivering is fresh off the press and still not properly audited, PLEASE USE WITH CAUTION.

At this point, we recommend you not upload any highly sensitive media to the Fula testnet environment, use it as a primary backup facility or expose any of the services over untrusted networks.

How to get started​

Fula testnet environment setup​

First, you can follow the instructions over here for setting up a Fula testnet environment on your host machine with Docker.

Fotos installation​

Download the latest release of Fotos from the google play store and install it.

Testing steps​

Once you have Fotos and the Fula testnet environment properly installed you can proceed with the following steps:

  1. See here for instructions on setting up Fotos before moving on to anything else.

  2. See here for instructions on backing up an image from your device to the Fula API server using Fotos.

  3. See here for instructions on sharing the image with a friend.

  4. See here for instructions on how to give yourself $FULA rewards for storing a file uploaded from your Fotos application.

- + \ No newline at end of file diff --git a/whitepaper.html b/whitepaper.html index bab114e1..d9f5f7cf 100644 --- a/whitepaper.html +++ b/whitepaper.html @@ -5,13 +5,13 @@ Whitepaper | Functionland - + - + \ No newline at end of file diff --git a/work_in_progress.html b/work_in_progress.html index 26858031..c7b3e6fe 100644 --- a/work_in_progress.html +++ b/work_in_progress.html @@ -5,13 +5,13 @@ work_in_progress | Functionland - +

work_in_progress

- + \ No newline at end of file