{"id":20975254,"url":"https://github.com/functionland/fula-testnet","last_synced_at":"2025-10-15T05:45:23.763Z","repository":{"id":47475418,"uuid":"515635586","full_name":"functionland/fula-testnet","owner":"functionland","description":null,"archived":false,"fork":false,"pushed_at":"2022-08-27T11:39:17.000Z","size":450,"stargazers_count":0,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-20T05:43:14.513Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/functionland.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-07-19T15:12:40.000Z","updated_at":"2022-07-20T15:08:32.000Z","dependencies_parsed_at":"2022-09-15T03:41:43.487Z","dependency_job_id":null,"html_url":"https://github.com/functionland/fula-testnet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functionland%2Ffula-testnet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functionland%2Ffula-testnet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functionland%2Ffula-testnet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/functionland%2Ffula-testnet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/functionland","download_url":"https://codeload.github.com/functionland/fula-testnet/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243374326,"owners_count":20280661,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T04:41:35.971Z","updated_at":"2025-10-15T05:45:18.712Z","avatar_url":"https://github.com/functionland.png","language":"Shell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fula Testnet\n\n## Requirements\n\n- A linux host OS for running docker (linux is required for 'host' network mode)\n\n- Install [Docker](https://docs.docker.com/engine/install)\n\n- Install [Docker Compose](https://docs.docker.com/compose/install)\n\n## Before you start\n\nAll of the software included in the Fula testnet environment is in 'alpha' status and should be run behind a firewall that restricts all incoming traffic.\n\n## Running\n\n- Clone the repository with the configuration\n\n```\ngit clone https://github.com/functionland/fula-testnet.git\n```\n\n- Run with docker-compose\n\n```\ndocker-compose up -d\n```\n\n- The following services will be available after everything is running\n\n1. [Sugarfunge Node](https://github.com/functionland/sugarfunge-node/tree/functionland/fula): Local blockchain node (Accessible at `ws://localhost:9944`) \n2. [Sugarfunge API](https://github.com/functionland/sugarfunge-api/tree/functionland/fula): Blockchain API (API available at http://localhost:4000)\n3. [IPFS](https://ipfs.io): Distributed storage (API available at http://localhost:8001)\n6. [Proof Engine](https://github.com/functionland/proof-engine): Proof of Storage validator for the chain.\n7. [Fula API Server](https://github.com/functionland/fula/tree/main/apps/box): The server API that is used by Fotos\n8. [IPFS Cluster](https://ipfscluster.io/): Used as a proxy between the Fula API server app and IPFS for logging the CID when a file is uploaded with Fotos\n\n## Storage Provider Steps\n\nAfter performing the following steps you will have uploaded a file to your node and received rewards on the Fula testnet for storing the file.\n\n### Add a file to the IPFS service running inside Docker\n\n- Copy the file that you want to add to the IPFS docker container\n\n```\ndocker-compose cp examples/meet_box.jpg ipfs:/\n```\n\n- Add the file to IPFS by running `ipfs add`\n\n```\ndocker-compose exec ipfs ipfs add /meet_box.jpg\n```\n\n- The console should have a similar output showing the progress, the CID and the file added.\n\n```\n84.88 KiB / 84.88 KiB  100.00%added QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf meet_box.jpg\n```\n\n- Keep the CID for the next section. In this case the CID is `QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf`.\n\n\n### Find your Account ID\n\n- Wait a few minutes after the `docker-compose.yaml` starts the services so it can configure everything for you and get the account ID by running the following command on the same folder as the `docker-compose.yaml`.\n\n```bash\ndocker-compose logs proof-engine | grep Account \n```\n\nThe console should output logs similar to these\n```bash\n2022-07-20T00:35:06.668944Z  INFO proof_engine::sugarfunge: Account(\"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\")\n2022-07-20T00:35:06.766789Z  INFO proof_engine::sugarfunge: operator: Account(\"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\")\n2022-07-20T00:35:06.847557Z  INFO proof_engine::sugarfunge: AccountExistsOutput { account: Account(\"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\"), exists: false }\n2022-07-20T00:35:06.847596Z  WARN proof_engine::sugarfunge: invalid: Account(\"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\")\n2022-07-20T00:35:06.847604Z  WARN proof_engine::sugarfunge: registering: Account(\"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\")\n```\n\nThe Account ID in this case is `5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j`.\n\n### Upload a Manifest\n\n- A manifest is required to confirm to the proof engine that a file was stored in your IPFS storage. You will need to do a `POST` request to `http://localhost:4000/fula/update_manifest`.\n\n1. `seed`: The operator that is owner of the asset pool (Default: `//Alice`)\n2. `from`: The account ID of the owner of the asset pool (Default: `5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY` which represents `//Alice`)\n3. `to:`: The account ID that contains the IPFS file stored. (In this example it is `5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j` which is your own account)\n4. `manifest`.`job`.`uri`: The CID of a file that is stored in the account used in the `to` field (In this example the CID is `QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf` from the file that we added above)\n\n```json\n{\n    \"seed\": \"//Alice\",\n    \"from\": \"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\n    \"to\": \"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\",\n    \"manifest\": {\n        \"job\": {\n            \"work\": \"Storage\",\n            \"engine\": \"IPFS\",\n            \"uri\": \"QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf\"\n        }\n    }\n}\n```\n\n### Restart the proof engine\n\nIn order for the proof engine to pick up the new manifest it must be restarted.\n\n```\n$ docker-compose restart proof-engine\n```\n\n## Viewing your rewards\n\nThere are two options for seeing your rewards for storing a file.\n\n### See mint output from proof engine logs\n\nTail the proof engine logs:\n\n```\n$ docker-compose logs -f proof-engine\n```\n\nHere is sample output you should see once your provider account is rewarded on the blockchain.\n\n```\nproof-engine_1  | 2022-07-29T18:36:37.851570Z  INFO proof_engine::sugarfunge: MintOutput {\nproof-engine_1  |     to: Account(\nproof-engine_1  |         \"5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j\",\nproof-engine_1  |     ),\nproof-engine_1  |     class_id: ClassId(\nproof-engine_1  |         1000000,\nproof-engine_1  |     ),\nproof-engine_1  |     asset_id: AssetId(\nproof-engine_1  |         13510586523404404513,\nproof-engine_1  |     ),\nproof-engine_1  |     amount: Balance(\nproof-engine_1  |         590768,\nproof-engine_1  |     ),\nproof-engine_1  |     who: Account(\nproof-engine_1  |         \"5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY\",\nproof-engine_1  |     ),\nproof-engine_1  | }\n```\n\n- `5HDndLhyKjfxSZHb9zz88pPN3RPmBpaaz8PFbgmKQZz5LJ7j` is your account ID (as acquired in the previous step).\n\n- `590768` is your current $FULA balance for receiving storage rewards.\n\n### View rewards in the testnet explorer\n\nAfter the manifest is added to the chain you should see it in the testnet explorer at https://explorer.testnet.fx.land/#/explorer and the account ID (as acuiqred in the previous step) is getting rewarded.\n\n## Fula Integration Notes\n\n### Find the CID for files uploaded via the Fula File API\n\nIf you are not adding files directly to IPFS as  mentioned in the previous steps (eg/ using the Fotos mobile app), you will need to find the CID for the file that was added through the Fula File API.  You can use the IPFS Cluster proxy for this.\n\n```\n$ docker-compose logs -f cluster |  grep 'new pin added:'\n```\n\nThe output should look something like:\n\n```\ncluster         | 2022-07-29T21:12:21.934Z      INFO    crdt    crdt/consensus.go:231   new pin added: QmfW6ii1KRmr2iei5cpxu3ekojFP5zbtPB8BavcV5SF7MK\ncluster         | 2022-07-29T21:12:21.968Z      INFO    crdt    crdt/consensus.go:231   new pin added: QmYjqgWSaJLJ2iF2CshVTFfBM3da7mtsZymyo69fZepzYo\n```\n\nWhere in this case the last uploaded file would correspond with a CID of `QmYjqgWSaJLJ2iF2CshVTFfBM3da7mtsZymyo69fZepzYo`.\n\n### Ensure the file you added is part of IPFS MFS\n\nIn order for the proof engine to verify your file is being stored by  IPFS it must be part of the IPFS mutable file system.\n\n```\n$ docker exec ipfs ipfs files cp /ipfs/QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf /\n```\n\nWhere `QmcwQBzZcFVa7gyEQazd9WryzXKVMK2TvwBweruBZhy3pf` is the CID you captured in the previous step.\n\n\n\n## Useful docker-compose commands\n\n```bash\n# Update latest tagged images\n$ docker-compose pull\n# Stop the images\n$ docker-compose down\n# Remove any persistent storage\n$ sudo rm -r data/ ipfs/\n```\n\n## Running IPFS outside of docker-compose (Optional)\n\nBy default, the IPFS WebUI is disabled on private swarm networks since it fetches the app from the public network. There is a workaround by installing IPFS Desktop.\n\n- Install and Start [IPFS Desktop](https://docs.ipfs.io/install/ipfs-desktop)\n\n- Disconnect from the public network: \n\n```\nipfs bootstrap rm --all\n```\n\n- Copy the `swarm.key` from the `fula-testnet repository` to your IPFS Folder. The folder can be opened by clicking `IFPS tray icon \u003e Advanced \u003e Open Repository Directory`.\n\n- Add the private swarm node: `ipfs bootstrap add /dns4/ipfs.testnet.fx.land/tcp/4001/ipfs/12D3KooWBNonCBdf689W94wbBhvm39LGeoP5FZDNNh8j8qwy5M3B`\n\n- Restart IPFS Desktop by clicking `IPFS tray icon \u003e Restart`\n\n- Comment the `ipfs` service secion in the `docker-compose.yaml` file.\n\n- Start the services after excluding IPFS.\n\n```\ndocker-compose up -d\n```\n\n\n## Getting Fula API Server multiaddress / Peer ID\n\nDepending on the client you are using you may need to supply either the Fula API server's Peer ID or the Fula API server's multiaddress.\n\n\n### Generate the logs\n\nRun the following commands in this directory.\n\n```\n \u003e docker-compose logs -f box\n```\n\nThe log should contain something like this:\n\n```\nbox0      | 2022-07-14T15:31:09.133Z box:info Box peerID 12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.134Z box:info Box Listen On /dns4/wrtc-star1.par.dwebops.pub/tcp/443/wss/p2p-webrtc-star/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /dns4/wrtc-star2.sjc.dwebops.pub/tcp/443/wss/p2p-webrtc-star/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/127.0.0.1/tcp/4002/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/192.168.65.3/tcp/4002/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/192.168.65.4/tcp/4002/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/172.19.0.1/tcp/4002/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/127.0.0.1/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/192.168.65.3/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/192.168.65.4/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\nbox0      | 2022-07-14T15:31:09.135Z box:info Box Listen On /ip4/172.19.0.1/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\n```\n\nIn this example, the Peer ID is `12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH` and the multiaddress is the one reachable from your client on the same network.\n\nDepending on the client support you can use either the TCP or the websockets transport multiaddresses:\n\n```\n/ip4/192.168.65.4/tcp/4002/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\n/ip4/192.168.65.4/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\n```\n\n### Modify the multiaddress so that it is reachable from your client\n\nBecause the Fula API server is running inside Docker, the network interface that the container sees is a different subnet than your host machine and is therefore probably not reachable from outside the container.  \n\nAs a result, the multiaddress that the Fula API server reports is also not reachable.\n\nTo work around this, change the IP portion of the multiaddress to the IP address of your host machine.\n\nFor example, on macOS do the following to obtain your ipv4 address: \n\nClick the 'network' icon -\u003e network preferences and your wifi or ethernet connection should list your network IP address. (eg/ 192.168.4.42)\n\nNext update the multiaddress in the Fula API server log from the previous step.\n\nChange:\n\n```\n/ip4/127.0.0.1/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\n```\n\nTo:\n\n```\n/ip4/192.168.4.42/tcp/4003/ws/p2p/12D3KooWMNV3ANQq5NE94ArVJDRd6rCk53hUTbVuhqQfrNGF54HH\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunctionland%2Ffula-testnet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffunctionland%2Ffula-testnet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffunctionland%2Ffula-testnet/lists"}