Compare commits

...
271 Commits
Author SHA1 Message Date
Chris Troutner 9b8db2adaf Merge pull request #50 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream ipfs-service-provider
2021-12-31 12:15:50 -08:00
Chris Troutner c8539372ae Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-12-31 12:14:24 -08:00
Chris Troutner e8a3234dcd Merge pull request #64 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): updating to v6.8.2
2021-12-31 12:13:13 -08:00
Chris Troutner fc717e0dcd fix(ipfs-coord): updating to v6.8.2 2021-12-31 12:11:47 -08:00
Chris Troutner 02512a8183 Automatically restarting wallet service 2021-12-30 07:52:22 -08:00
Chris Troutner 09a58a78ef Merge pull request #49 from Permissionless-Software-Foundation/ct-unstable
Synced with upstream ipfs-servicer-provider
2021-12-29 20:06:42 -08:00
Chris Troutner f4708d9a49 Synced with upstream ipfs-servicer-provider 2021-12-29 19:53:53 -08:00
Chris Troutner 18cec75f41 Merge pull request #63 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.8.1
2021-12-29 19:33:54 -08:00
Chris Troutner 7621842952 fix(ipfs-coord): Updating to v6.8.1 2021-12-29 19:32:39 -08:00
Chris Troutner 01da1b44da minor tweeks to docker files 2021-12-29 18:31:01 -08:00
Chris Troutner b8f262b01b feat(ipfs-service-provider): Syncing with upstream. Production uses go-ipfs 2021-12-29 18:17:35 -08:00
Chris Troutner 0e9a57a1da Merge pull request #62 from Permissionless-Software-Foundation/ct-unstable
Kicking off v2.0.0
2021-12-29 18:04:29 -08:00
Chris Troutner e374522725 fix(version): Bumping to v2.0.0 2021-12-29 18:03:09 -08:00
Chris Troutner e402f33132 Adding more properties to docker-compose 2021-12-29 18:00:17 -08:00
Chris Troutner e85655c0ec Adding data/ directory to gitignore 2021-12-29 17:46:52 -08:00
Chris Troutner 227ffbc4bc Removing data directory 2021-12-29 17:46:28 -08:00
Chris Troutner b41f819783 fix(startup): Exiting if server can't stop 2021-12-29 17:46:05 -08:00
Chris Troutner d6c3635c6a fix(ipfs): Got running with external IPFS node 2021-12-29 17:28:35 -08:00
Chris Troutner 37e98e4248 fix(ipfs): Switching from @chris.troutner/ipfs to ipfs v0.60.0 2021-12-29 16:59:32 -08:00
Chris Troutner d2f4369f8d Merge pull request #48 from Permissionless-Software-Foundation/ct-unstable
syncing upstream ipfs-service-provider
2021-12-24 17:16:17 -08:00
Chris Troutner bd33314c4f Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-12-24 17:14:26 -08:00
Chris Troutner e6941f7f7f Merge pull request #61 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-cood): Updating to v6.7.6
2021-12-24 17:10:49 -08:00
Chris Troutner 4fdf35a55f fix(ipfs-cood): Updating to v6.7.6 2021-12-24 17:07:54 -08:00
Chris Troutner e6441a9c8c Merge pull request #47 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream ipfs-service-provider
2021-12-24 15:43:23 -08:00
Chris Troutner 8a3265bff2 Merge branch 'master' into ct-unstable 2021-12-24 15:34:30 -08:00
Chris Troutner d871d8b392 Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-12-24 15:33:01 -08:00
Chris Troutner f1fbe34b58 Merge pull request #60 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.7.5
2021-12-24 15:26:04 -08:00
Chris Troutner d232b6404d fix(ipfs-coord): Updating to v6.7.5 2021-12-24 15:24:38 -08:00
Chris Troutner ea724f7ed8 Merge pull request #46 from Permissionless-Software-Foundation/samrock5000-patch-1
🚧 fix typo and add cd into scripts folder
2021-12-15 08:17:02 -08:00
Samuel Nevarez 2b04bae260 🚧 fix typo and add cd into scripts folder 2021-12-14 21:25:00 -07:00
Chris Troutner 84f1e25648 Adding example script for running locally 2021-12-10 15:30:42 -08:00
Chris Troutner ef8c6fbcec fix(errors): Giving more clues when errors happen 2021-12-10 15:20:03 -08:00
Chris Troutner 12d462b89d Merge pull request #45 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream ipfs-service-provider
2021-12-06 12:52:16 -08:00
Chris Troutner 53065d8365 Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-12-06 12:50:38 -08:00
Chris Troutner 1bf8f756e5 Merge pull request #59 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs): Deleting /blocks dir if it prevents app from starting
2021-12-06 12:48:48 -08:00
Chris Troutner 1e513cc133 fix(ipfs): Deleting /blocks dir if it prevents app from starting 2021-12-06 12:46:22 -08:00
Chris Troutner 7ce53439b1 Updating gitignore 2021-12-02 14:11:27 -08:00
Chris Troutner e90d664761 Merge pull request #44 from Permissionless-Software-Foundation/ct-unstable
Minor updates
2021-12-02 13:52:13 -08:00
Chris Troutner fc11e701e4 fix(broadcast): Handling full node errors 2021-12-02 13:51:07 -08:00
Chris Troutner 3c7ebef8a7 fix(bch-js): Updating to v4.20.28 2021-12-01 14:54:56 -08:00
Chris Troutner 5d70c89f2d Merge pull request #43 from Permissionless-Software-Foundation/ct-unstable
fix(garbage collection): Updating IPFS config for more conservative GC
2021-11-27 15:28:06 -08:00
Chris Troutner 7149c0a824 fix(upstream): Syncing with upstream ipfs-service-provider 2021-11-27 15:25:39 -08:00
Chris Troutner 74c6bc5737 Merge pull request #58 from Permissionless-Software-Foundation/ct-unstable
fix(garbage collection): Updating IPFS config for more conservative GC
2021-11-27 15:14:30 -08:00
Chris Troutner bac6c8b1e9 Disabling debug code 2021-11-27 15:13:23 -08:00
Chris Troutner 9e7d955bc4 fix(garbage collection): Updating IPFS config for more conservative GC 2021-11-27 15:12:08 -08:00
Chris Troutner af7c4464bb Merge pull request #42 from Permissionless-Software-Foundation/dh-pubkey
feat(pubkey): Added pubkey route to ipfs-bch-wallet-service
2021-11-25 06:10:16 -08:00
Chris Troutner cfb128f3c8 Updating deps 2021-11-25 06:04:35 -08:00
Daniel Gonzalez 451a828a05 feat(pubkey): Added pubkey route to ipfs-bch-wallet-service 2021-11-23 19:25:01 -04:00
Chris Troutner 678bc7015c Merge pull request #56 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.7.4
2021-11-13 11:36:57 -08:00
Chris Troutner 013aa97143 fix(ipfs-coord): Updating to v6.7.4 2021-11-13 11:33:28 -08:00
Chris Troutner 45b7e480b7 Merge pull request #55 from Permissionless-Software-Foundation/ct-unstable
fix(bch-js, ipfs-coord): Updating npm packages
2021-10-29 15:40:36 -07:00
Chris Troutner 09772bae29 fix(bch-js, ipfs-coord): Updating npm packages 2021-10-29 15:38:20 -07:00
Chris Troutner c01130fcc7 Updating ipfs-coord and bch-js 2021-10-27 14:33:17 -07:00
Chris Troutner 2d4159b4cf Merge pull request #41 from Permissionless-Software-Foundation/ct-unstable
fix(Docker): Increasing memory limit to 1GB
2021-10-12 13:39:37 -07:00
Chris Troutner 6dcd1ce5e7 fix(Docker): Increasing memory limit to 1GB 2021-10-12 13:37:31 -07:00
Chris Troutner 6c913b2c36 Merge pull request #40 from Permissionless-Software-Foundation/ct-unstable
fix(dependencies): Using exact versions
2021-10-12 13:34:51 -07:00
Chris Troutner c453705a80 fix(dependencies): Using exact versions 2021-10-12 13:22:16 -07:00
Chris Troutner bb9a2a2408 Merge pull request #54 from Permissionless-Software-Foundation/ct-unstable
fix(dependencies): Using exact versions
2021-10-12 12:46:51 -07:00
Chris Troutner 54709a8c70 fix(dependencies): Using exact versions 2021-10-12 09:56:52 -07:00
Chris Troutner 64135b55a7 fix(tests): Fixing broken unit test 2021-10-11 14:45:09 -07:00
Chris Troutner 1ff4ba440d fixing merge conflicts with upstream 2021-10-11 14:40:22 -07:00
Chris Troutner 72da6203a1 Merge pull request #53 from Permissionless-Software-Foundation/ct-unstable
fix(Dockerfile): Switching to more basic stuff
2021-10-11 14:34:03 -07:00
Chris Troutner e2bc560c7d fix(Dockerfile): Switching to more basic stuff 2021-10-11 13:48:20 -07:00
Chris Troutner e40241bac8 Fixing typo in docker-compose 2021-10-11 09:05:57 -07:00
Chris Troutner 01c8c5c194 Merge pull request #52 from Permissionless-Software-Foundation/ct-unstable
Additional test coverage
2021-10-01 14:11:44 -07:00
Chris Troutner 5eb5ef204e fix(json rpc): Increasing to 100% test coverage 2021-10-01 14:01:08 -07:00
Chris Troutner ee90bc0730 fix(ipfs): Got adapter back to 100% unit test coverage 2021-09-30 15:20:51 -07:00
Chris Troutner 5af068e0d6 fix(ipfs-coord): Got adapter back to 100% test coverage 2021-09-30 15:12:47 -07:00
Chris Troutner 7e228b729e fix(ipfs adapter): Adding unit tests for lock-file error handling 2021-09-30 14:47:17 -07:00
Chris Troutner ec4c61f38e Merge pull request #39 from Permissionless-Software-Foundation/ct-unstable
Syncing upstream: Improvements to Docker container
2021-09-29 07:20:47 -07:00
Chris Troutner 9ed610e3a4 fix(upstream): Synced with upstream ipfs-service-provider 2021-09-29 07:05:52 -07:00
Chris Troutner a9e7fc616e Merge pull request #51 from Permissionless-Software-Foundation/ct-unstable
fix(docker): disabling circuit relays by default
2021-09-28 20:30:45 -07:00
Chris Troutner 9d5ffbe26e fix(docker): disabling circuit relays by default 2021-09-28 20:11:25 -07:00
Chris Troutner 3829e90844 Merge pull request #50 from Permissionless-Software-Foundation/ct-unstable
fix(docker): Matching ports to dev env
2021-09-28 19:55:58 -07:00
Chris Troutner f181d8b095 fix(docker): Matching ports to dev env 2021-09-28 19:52:10 -07:00
Chris Troutner a2270e70af Merge pull request #49 from Permissionless-Software-Foundation/ct-unstable
fix(Docker): Dropping RAM to 500MB
2021-09-28 18:18:26 -07:00
Chris Troutner 34604d53b0 fix(Docker): Dropping RAM to 500MB 2021-09-28 18:16:56 -07:00
Chris Troutner 6257b96bc3 fix(Docker): Forcing memory limit of 1GB 2021-09-28 18:14:18 -07:00
Chris Troutner 1d8912f60d Slight update to docker container 2021-09-28 18:04:52 -07:00
Chris Troutner 3c9b63d009 Merge pull request #48 from Permissionless-Software-Foundation/ct-unstable
fix(circuit relay): Auto-discover IP4 addr when CR enabled
2021-09-28 17:53:29 -07:00
Chris Troutner e6f9f64b4a fix(circuit relay): Auto-discover IP4 addr when CR enabled 2021-09-28 17:51:19 -07:00
Chris Troutner a8ad4149e0 fix(shell-scripts): Added shell-script dir with example scripts 2021-09-28 16:58:57 -07:00
Chris Troutner 3924812985 Merge pull request #47 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs): HOP setting is controlled by config.isCircuitRelay
2021-09-28 15:48:44 -07:00
Chris Troutner fef0f3a987 fix(ipfs): HOP setting is controlled by config.isCircuitRelay 2021-09-28 15:44:06 -07:00
Chris Troutner 1c012322fd Merge pull request #46 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Bumping to v6.7.0
2021-09-28 06:56:26 -07:00
Chris Troutner 545e8aa670 fix(ipfs-coord): Bumping to v6.7.0 2021-09-28 06:54:12 -07:00
Chris Troutner 449bd500c2 Merge pull request #38 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating bootstrap peers. v6.6.8
2021-09-27 12:52:00 -07:00
Chris Troutner ea295f2f41 linting 2021-09-27 12:47:10 -07:00
Chris Troutner 9175b8abe8 Fixing merge conflicts 2021-09-27 12:44:59 -07:00
Chris Troutner 9d4a61ea99 Merge pull request #45 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating bootstrap peers. v6.6.8
2021-09-27 12:40:53 -07:00
Chris Troutner cb50fdc70d fix(ipfs-coord): Updating bootstrap peers. v6.6.8 2021-09-27 12:39:10 -07:00
Chris Troutner cf488e1440 Merge pull request #37 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.6.7
2021-09-20 10:41:57 -07:00
Chris Troutner 4fc6def1cd Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-09-20 10:34:59 -07:00
Chris Troutner e0b2fd2525 Merge pull request #44 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.6.7
2021-09-20 10:21:12 -07:00
Chris Troutner 8e08201b16 fix(ipfs-coord): Updating to v6.6.7 2021-09-20 10:19:33 -07:00
Chris Troutner c347a2d99a Merge pull request #36 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-service-provider): Syncing with upstream repo
2021-09-18 11:37:16 -07:00
Chris Troutner 5b7d8d4db4 fix(ipfs-service-provider): Syncing with upstream repo 2021-09-18 11:34:23 -07:00
Chris Troutner dd0692e91f Merge pull request #43 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Bumping to v6.6.6
2021-09-18 11:23:26 -07:00
Chris Troutner 576da66194 fix(ipfs-coord): Bumping to v6.6.6 2021-09-18 11:20:11 -07:00
Chris Troutner f4851d6771 Merge pull request #42 from Permissionless-Software-Foundation/ct-unstable
Minor tweeks
2021-09-17 17:43:33 -07:00
Chris Troutner 96abb0d56e fix(ipfs-coord): Updating to v6.6.5 2021-09-17 17:41:08 -07:00
Chris Troutner fdf3141c91 fix(reset): Restarting app after 4 hours, not 8 2021-09-17 16:23:47 -07:00
Chris Troutner 6692d234da Adding link to video in readme 2021-09-17 16:23:04 -07:00
Chris Troutner b8655e31ca Fixing typo in shell script 2021-09-17 12:22:05 -07:00
Chris Troutner e118fe4d6e Merge pull request #41 from Permissionless-Software-Foundation/ct-unstable
fix(startup script): Added startup script
2021-09-17 11:20:39 -07:00
Chris Troutner 86283195c5 slight tweek to README 2021-09-17 11:18:26 -07:00
Chris Troutner a037646aca fix(startup script): Added startup script 2021-09-17 11:17:10 -07:00
Chris Troutner ae6bdcdd5f Merge pull request #35 from Permissionless-Software-Foundation/ct-unstable
fix(bch-js): Selecting custom server when not using JWT token
2021-09-08 14:02:25 -07:00
Chris Troutner 9fe822024c fix(bch-js): Selecting custom server when not using JWT token 2021-09-08 14:00:00 -07:00
Chris Troutner fc94041d17 Merge pull request #34 from Permissionless-Software-Foundation/ct-unstable
fix(docker): Using Ubuntu base container
2021-09-08 13:05:58 -07:00
Chris Troutner a3f780b1f5 fix(docker): Using Ubuntu base container 2021-09-08 13:02:23 -07:00
Chris Troutner 9487f19233 Merge pull request #33 from Permissionless-Software-Foundation/ct-unstable
fix(JWT): Added env var to enable/disable JWT retrieval at startup
2021-09-08 12:38:05 -07:00
Chris Troutner 2988374769 linting 2021-09-08 12:35:26 -07:00
Chris Troutner 22ab7260f4 fix(startup): Fixing startup issues caused by code mixup with upstream 2021-09-08 12:35:00 -07:00
Chris Troutner 27f6f62f8c fix(gitignore): Adding run-dev.sh to gitignore 2021-09-08 12:03:46 -07:00
Chris Troutner 33ab787a95 Integrating JWT env var in production 2021-09-08 12:02:57 -07:00
Chris Troutner 4f2cde2599 Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-09-08 12:00:41 -07:00
Chris Troutner d419084216 Merge pull request #40 from Permissionless-Software-Foundation/ct-unstable
fix(JWT): Added env var to enable/disable JWT retrieval at startup
2021-09-08 11:59:55 -07:00
Chris Troutner 553e0081fa fix(JWT): Added env var to enable/disable JWT retrieval at startup 2021-09-08 11:58:18 -07:00
Chris Troutner 0716922b7c Merge pull request #32 from Permissionless-Software-Foundation/ct-unstable
fix(memory-leak): Resetting app after 8 hours
2021-09-07 21:05:20 -07:00
Chris Troutner 7e227d994b Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-09-07 21:01:46 -07:00
Chris Troutner dd1b702966 Merge pull request #39 from Permissionless-Software-Foundation/ct-unstable
fix(memory-leak): Resetting app after 8 hours
2021-09-07 20:59:56 -07:00
Chris Troutner 0963f89049 fix(memory-leak): Resetting app after 8 hours 2021-09-07 20:58:23 -07:00
Chris Troutner cda3f1c0a7 Merge pull request #31 from Permissionless-Software-Foundation/ct-unstable
fix(JSON RPC): Adding filters and logging to JSON RPC router
2021-09-05 09:40:16 -07:00
Chris Troutner 1247bcb8c0 fix(upstream): Syncing with upstream ipfs-service-provider 2021-09-05 09:35:53 -07:00
Chris Troutner 36476b32ab Noting GitHub Issue 2021-09-05 09:23:38 -07:00
Chris Troutner 630135ac1c Merge pull request #37 from Permissionless-Software-Foundation/ct-unstable
fix(JSON RPC): Adding filters and logging to JSON RPC router
2021-09-05 08:45:51 -07:00
Chris Troutner 0a86c7dc92 fix(JSON RPC): Adding filters and logging to JSON RPC router 2021-09-05 08:31:06 -07:00
Chris Troutner a8a08f8978 Merge pull request #30 from Permissionless-Software-Foundation/ct-unstable
fix(JSON RPC): Prevening processing of duplicate entries
2021-09-04 18:18:23 -07:00
Chris Troutner 8b8d35573d fix(upstream): Syncing with upstream ipfs-service-provider 2021-09-04 18:07:28 -07:00
Chris Troutner 36ed80212d Merge pull request #36 from Permissionless-Software-Foundation/ct-unstable
fix(JSON RPC): Prevening processing of duplicate entries
2021-09-04 18:01:24 -07:00
Chris Troutner 131e6e1460 Updating ipfs-coord to v6.6.4 2021-09-04 17:59:53 -07:00
Chris Troutner 5c799a8197 fix(JSON RPC): Prevening processing of duplicate entries 2021-09-04 17:53:45 -07:00
Chris Troutner 488c5d3c22 fix(app): Exiting app if IPFS lock file is being held 2021-09-04 17:51:27 -07:00
Chris Troutner e93ffc4c77 Bumping version to 1.11.12 2021-09-04 15:25:52 -07:00
Chris Troutner e4c4e324b8 Merge pull request #29 from Permissionless-Software-Foundation/ct-unstable
fix(debug): Removing debug log spam
2021-09-04 09:20:09 -07:00
Chris Troutner e5e012a700 Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-09-04 09:12:25 -07:00
Chris Troutner 9bddcf1c8e Merge pull request #35 from Permissionless-Software-Foundation/ct-unstable
fix(debug): Removing debug log spam
2021-09-04 09:09:26 -07:00
Chris Troutner ba2fdbc836 fix(debug): Removing debug log spam 2021-09-04 09:05:30 -07:00
Chris Troutner 3f809d38fb Merge pull request #28 from Permissionless-Software-Foundation/ct-unstable
fix(upstream): Syncing with upstream ipfs-service-provider
2021-09-04 08:46:39 -07:00
Chris Troutner d66d80bb0c fix(upstream): Syncing with upstream ipfs-service-provider 2021-09-04 08:43:41 -07:00
Chris Troutner 4c707cf5b9 Merge pull request #34 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.6.3
2021-09-04 08:39:37 -07:00
Chris Troutner 8670bdb588 fix(ipfs-coord): Updating to v6.6.3 2021-09-04 08:37:12 -07:00
Chris Troutner 4c5bdd089e Debugging relay metrics 2021-09-03 21:01:53 -07:00
Chris Troutner c3eb1b1ad3 Merge pull request #27 from Permissionless-Software-Foundation/ct-unstable
fix(docker): Specifying max size for log files
2021-09-03 12:08:46 -07:00
Chris Troutner 1e1e1558b4 Adding data/ directory to gitignore 2021-09-03 12:07:00 -07:00
Chris Troutner d4abd693de fix(upstream): Syncing with upstream ipfs-service-provider 2021-09-03 12:01:45 -07:00
Chris Troutner d38718dcdf Merge pull request #33 from Permissionless-Software-Foundation/ct-unstable
fix(docker): Specifying max size for log files
2021-09-03 11:29:37 -07:00
Chris Troutner 3a3376c303 fix(docker): Specifying max size for log files 2021-09-03 11:27:27 -07:00
Chris Troutner 05043ac74d fix(ipfs-coord): Upgrading to v6.6.0 2021-09-03 11:05:52 -07:00
Chris Troutner 5f89bfcbd8 Merge pull request #26 from Permissionless-Software-Foundation/ct-unstable
fix(sync): Synced with upstream ipfs-service-provider
2021-09-02 17:15:13 -07:00
Chris Troutner d7d56d9ebf fix(sync): Synced with upstream ipfs-service-provider 2021-09-02 17:12:11 -07:00
Chris Troutner 1592eadd8c fix(sync): Syncing with upstream ipfs-service-provider 2021-09-02 17:09:32 -07:00
Chris Troutner be1a4c750a Merge pull request #32 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updated to v6.5.6
2021-09-02 16:54:32 -07:00
Chris Troutner 4572ce3d6b fix(ipfs-coord): Updated to v6.5.6 2021-09-02 16:52:39 -07:00
Chris Troutner fb7d4e6074 Merge pull request #31 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs): Updating IPFS nad ipfs-coord
2021-09-02 09:06:27 -07:00
Chris Troutner 5467c991de Merge branch 'master' into ct-unstable 2021-09-02 09:04:25 -07:00
Chris Troutner ba93c6cc46 fix(ipfs): Updating IPFS nad ipfs-coord 2021-09-02 09:03:16 -07:00
Chris Troutner 60b37e4f72 Merge pull request #25 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.5.2
2021-08-30 08:02:58 -07:00
Chris Troutner 02a543323c Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-08-30 08:00:24 -07:00
Chris Troutner c28bc22084 Merge pull request #30 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.5.2
2021-08-30 07:56:29 -07:00
Chris Troutner f796dd6076 fix(ipfs-coord): Updating to v6.5.2 2021-08-30 07:51:44 -07:00
Chris Troutner 5d624f5c23 Merge pull request #24 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.5.1
2021-08-29 20:47:02 -07:00
Chris Troutner 3eacfb27a6 Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-08-29 20:45:05 -07:00
Chris Troutner 29b3d32743 Slight modification to Docker container 2021-08-29 20:44:45 -07:00
Chris Troutner a58e237122 Merge pull request #29 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.5.1
2021-08-29 20:39:48 -07:00
Chris Troutner c237b33677 fix(ipfs-coord): Updating to v6.5.1 2021-08-29 20:37:11 -07:00
Chris Troutner b48b618d4c Merge pull request #23 from Permissionless-Software-Foundation/ct-unstable
fix(upstream): Synced with upstream ipfs-service-provider
2021-08-29 16:48:00 -07:00
Chris Troutner 252834d727 Updating package-lock.json 2021-08-29 16:45:17 -07:00
Chris Troutner 04bcd9fd3a fix(upstream): Synced with upstream ipfs-service-provider 2021-08-29 16:34:03 -07:00
Chris Troutner cc5aba7896 Merge pull request #28 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v6.5.0
2021-08-29 16:24:04 -07:00
Chris Troutner 50bc5c2d02 fix(ipfs-coord): Updating to v6.5.0 2021-08-29 16:16:45 -07:00
Chris Troutner 3251b0dc58 fix(production): changing directories for permission issues 2021-08-28 17:45:28 -07:00
Chris Troutner 090f524b9d Merge pull request #27 from Permissionless-Software-Foundation/ct-unstable
fix(docker-compose): Opening up IPFS ports
2021-08-28 17:31:40 -07:00
Chris Troutner 1846b5da64 fix(docker-compose): Opening up IPFS ports 2021-08-28 17:29:21 -07:00
Chris Troutner 643dfd8fc0 Merge pull request #22 from Permissionless-Software-Foundation/ct-unstable
fix(upstream): Synced with upstream ipfs-service-provider
2021-08-28 07:56:40 -07:00
Chris Troutner 944d721296 fix(e2e): Fixed manual consumer test 2021-08-28 07:38:44 -07:00
Chris Troutner 96e4afd6c8 fix(upstream): Synced with upstream ipfs-service-provider 2021-08-27 16:21:17 -07:00
Chris Troutner 002e6657ff Merge pull request #26 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updated to v6.4.0
2021-08-27 15:43:16 -07:00
Chris Troutner fb215b11b7 fix(production): Tweeking production Docker container slightly 2021-08-27 15:41:33 -07:00
Chris Troutner 1618289078 fix(ipfs-coord): Updated to v6.4.0 2021-08-27 15:04:09 -07:00
Chris Troutner 2ebe42d5f4 Merge pull request #25 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Upgrading to v6.3.0
2021-08-26 21:27:13 -07:00
Chris Troutner 326271f703 Updating Dockerfile 2021-08-26 21:24:27 -07:00
Chris Troutner 0480f54287 fix(ipfs-coord): Upgrading to v6.3.0 2021-08-26 21:23:37 -07:00
Chris Troutner f9df8c7fab fix(production): Running Docker as root 2021-08-26 10:53:53 -07:00
Chris Troutner 2ae550c027 Merge pull request #24 from Permissionless-Software-Foundation/ct-unstable
fix(production): Updating Docker container
2021-08-26 10:29:01 -07:00
Chris Troutner eca131fefc minor comments to startup script 2021-08-26 10:27:22 -07:00
Chris Troutner 596645ad6b Bumping to ipfs-coord v6.1.8 2021-08-26 10:17:11 -07:00
Chris Troutner 2a2d940e7c fix(startup): Adding startup and env var settings 2021-08-26 09:21:08 -07:00
Chris Troutner 46b0c595f9 fix(production): Updating Docker container 2021-08-26 08:54:33 -07:00
Chris Troutner eab7a30926 Merge pull request #21 from Permissionless-Software-Foundation/ct-unstable
fix(psf-bch-wallet): Got working with psf-bch-wallet and ipfs-coord v6
2021-08-24 16:05:04 -07:00
Chris Troutner 85a8efb5bf fix(psf-bch-wallet): Got working with psf-bch-wallet and ipfs-coord v6 2021-08-24 16:03:17 -07:00
Chris Troutner e33ee49879 Merge pull request #20 from Permissionless-Software-Foundation/ct-unstable
fix(upstream): Synced with upstream repo ipfs-service-provider
2021-08-24 11:01:09 -07:00
Chris Troutner 9c53204a91 fix(upstream): Synced with upstream repo ipfs-service-provider 2021-08-24 10:59:39 -07:00
Chris Troutner 6faf1ccf86 Merge branch 'master' into ct-unstable 2021-08-24 10:58:21 -07:00
Chris Troutner 8fafe96e01 Merge pull request #23 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Bumping to v6.1.4
2021-08-24 10:53:32 -07:00
Chris Troutner d06c995174 fix(ipfs-coord): Bumping to v6.1.4 2021-08-24 10:51:58 -07:00
Chris Troutner 2d02904ed1 fix(ipfs-coord): Bumped to v6.1.3 2021-08-24 10:44:25 -07:00
Chris Troutner 51d7ddb362 Merge pull request #22 from Permissionless-Software-Foundation/ct-unstable
fix(node-fetch): Adding node-fetch as dependency, which was preventin…
2021-08-24 10:28:51 -07:00
Chris Troutner ee1fbad02a Fixing broken test 2021-08-24 10:26:46 -07:00
Chris Troutner f5ae98cb9c fix(node-fetch): Adding node-fetch as dependency, which was preventing install on some machines 2021-08-24 10:23:19 -07:00
Chris Troutner e416478522 Explicitly adding node-pre-gyp 2021-08-24 07:54:04 -07:00
Chris Troutner ce85dffc97 Adding node-fetch as a dep 2021-08-24 07:31:52 -07:00
Chris Troutner c9f7a43339 fix(Docker): integrating changes into production Docker container 2021-08-24 07:27:10 -07:00
Chris Troutner a885fb7edf Merge pull request #19 from Permissionless-Software-Foundation/ct-unstable
fix(version): Bumping to v1.11.0 for wallet consumer
2021-08-23 17:16:23 -07:00
Chris Troutner 93d1542522 fix(version): Bumping to v1.11.0 for wallet consumer 2021-08-23 17:12:49 -07:00
Chris Troutner 62fadbb394 Merge pull request #18 from Permissionless-Software-Foundation/ct-unstable
feat(upstream): Synced with upstream ipfs-service-provider
2021-08-23 17:08:35 -07:00
Chris Troutner ae37b6533b fix(upstream): Synced with upstream ipfs-service-provider 2021-08-23 17:06:20 -07:00
Chris Troutner c711fd0ce1 Merge pull request #21 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-cood): Bumping to v6.1.2
2021-08-23 16:38:06 -07:00
Chris Troutner 05af23b87c Merge branch 'master' into ct-unstable 2021-08-23 16:16:48 -07:00
Chris Troutner 54b505449b fix(ipfs-cood): Bumping to v6.1.2 2021-08-23 16:13:05 -07:00
Chris Troutner 8e5f5f2dbd debugging 2021-08-23 15:51:10 -07:00
Chris Troutner c06a9ec874 debugging 2021-08-23 15:36:33 -07:00
Chris Troutner 8639a3d363 Removing if statement 2021-08-23 15:32:31 -07:00
Chris Troutner a9ef1ebd66 using new code for responding to JSON RPC commands 2021-08-23 15:30:13 -07:00
Chris Troutner 1053191835 fix(orbit): Repairing router for handling orbitdb private message 2021-08-23 15:25:56 -07:00
Chris Troutner 7d0b536f73 fix(test): Removing test that broke with new version of ipfs-coord 2021-08-23 15:17:12 -07:00
Chris Troutner cf45a1fc7e fix(ipfs-coord): Bumped to v6.1.1 2021-08-23 15:14:25 -07:00
Chris Troutner cc2ada5169 Merge pull request #17 from Permissionless-Software-Foundation/dh-manual-tests
feat(tests): Added manual e2e tests
2021-08-20 07:12:33 -07:00
Chris Troutner cf4029ff00 Merge pull request #20 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs ports): Adding configurable ports use env vars
2021-08-19 08:04:24 -07:00
Chris Troutner 76e4feb1ac fix(ipfs ports): Adding configurable ports use env vars 2021-08-19 08:01:23 -07:00
Chris Troutner 4a5103d760 Adding note to README to fix install bug 2021-08-19 07:56:55 -07:00
Daniel Gonzalez 0b72895102 feat(tests): Added manual e2e tests 2021-08-18 01:10:03 -04:00
Chris Troutner f41cac9fc7 Merge pull request #16 from Permissionless-Software-Foundation/ct-unstable
fix(broadcast): Fixing bug in broadcast JSON RPC
2021-08-15 09:07:09 -07:00
Chris Troutner 8ad1400d3c fix(error reporting): Adding JSON RPC error reporting 2021-08-15 08:32:39 -07:00
Chris Troutner e48a9213c5 fix(broadcast): Fixing bug in broadcast JSON RPC 2021-08-13 16:15:44 -07:00
Chris Troutner 60e6a8b24f Merge pull request #19 from Permissionless-Software-Foundation/ct-unstable
Heavy refactoring and relocation of directories.
2021-08-08 11:19:24 -07:00
Chris Troutner 85af08b1aa Ran npm audit fix. Zero vulns 2021-08-08 11:14:00 -07:00
Chris Troutner 2d4bbd9ab0 Updated to ipfs-coord v5 2021-08-08 11:12:25 -07:00
Chris Troutner 06631a81ad perf(directories): Moving IPFS and OribitDB data to a .ipfsdata directory 2021-08-08 10:48:26 -07:00
Chris Troutner 24684ac25a feat(server): Converter top-level server library into a class 2021-08-08 09:58:24 -07:00
Chris Troutner 758de6b088 Got unit tests passing again 2021-08-08 08:09:48 -07:00
Chris Troutner 0346898501 feat(adapters): Refactored the adapters into a class 2021-08-08 07:38:47 -07:00
Chris Troutner 2e2d092b18 Merge pull request #15 from Permissionless-Software-Foundation/ct-unstable
fix(protocol): Adding protocol field to announceJsonLd
2021-08-05 17:18:31 -07:00
Chris Troutner c8aefae0cc fix(protocol): Adding protocol property to announceJsonLd 2021-08-05 17:16:37 -07:00
Chris Troutner 17e465b3ab Merge branch 'master' of https://github.com/Permissionless-Software-Foundation/ipfs-service-provider into ct-unstable 2021-08-05 17:14:40 -07:00
Chris Troutner 40bb75bf33 Merge pull request #18 from Permissionless-Software-Foundation/ct-unstable
fix(protocol): Adding protocol field to announceJsonLd
2021-08-05 17:11:00 -07:00
Chris Troutner 02201afc59 fix(protocol): Adding protocol field to announceJsonLd 2021-08-05 17:08:56 -07:00
Chris Troutner bae98bba28 Merge pull request #14 from Permissionless-Software-Foundation/ct-unstable
feat(about): Adding npm version to JSON RPC About endpoint output
2021-08-03 13:13:25 -07:00
Chris Troutner 0eb7aeaed1 feat(version): Adding npm version to ipfs-coord announce payload 2021-08-03 13:12:02 -07:00
Chris Troutner dbd5022c4c Merge pull request #17 from Permissionless-Software-Foundation/ct-unstable
feat(about): Adding npm version to JSON RPC About endpoint output
2021-08-03 13:07:57 -07:00
Chris Troutner 72ac73c410 feat(about): Adding npm version to JSON RPC About endpoint output 2021-08-03 13:05:45 -07:00
Chris Troutner 9b52c81b25 Adding startup script to gitignore 2021-08-03 12:53:35 -07:00
Chris Troutner 7cc13b9ba9 Adding todo in comments 2021-07-31 16:07:47 -07:00
Chris Troutner 3ba866d2d6 Merge pull request #13 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream ipfs-service-provider
2021-07-31 15:57:18 -07:00
Chris Troutner 3d058d9164 fix(ipfs-service-provider): Synced with upstream 2021-07-31 15:55:47 -07:00
Chris Troutner fde8b16fef Merge pull request #16 from Permissionless-Software-Foundation/dh-required
fix(users): Using the users entity in the use cases
2021-07-31 15:41:25 -07:00
Daniel Gonzalez c5a1eb6f81 fix(users): Using the users entity in the use cases 2021-07-31 15:00:38 -04:00
Chris Troutner 74f8b60472 Adding link to API documentation 2021-07-28 13:28:53 -07:00
Chris Troutner 53846762f0 Merge pull request #12 from Permissionless-Software-Foundation/dh-improve-documentation
feat(documentation): Improved ipfs-bch-wallet-service documentation
2021-07-28 13:25:13 -07:00
Daniel Gonzalez 788d5ba4ee feat(documentation): Improved ipfs-bch-wallet-service documentation 2021-07-26 21:00:24 -04:00
Chris Troutner d57085949c Merge pull request #15 from Permissionless-Software-Foundation/ct-unstable
Removing comments
2021-07-25 17:31:48 -07:00
Chris Troutner 9dc40a417a Removing comments 2021-07-25 17:30:15 -07:00
Chris Troutner 81e5592b81 Merge pull request #14 from Permissionless-Software-Foundation/ct-unstable
Converting wlogger and Controller libraries to classes
2021-07-25 16:51:30 -07:00
Chris Troutner 44867f0173 fix(controllers): Made Controllers library a class 2021-07-25 16:49:01 -07:00
Chris Troutner c46f7357c3 fix(wlogger): Refactored into Class for better unit test control 2021-07-25 16:34:56 -07:00
Chris Troutner 47b8dce966 Adding link to YouTube video in README. 2021-07-21 15:10:05 -07:00
Chris Troutner 63b08d1acb Merge pull request #11 from Permissionless-Software-Foundation/ct-unstable
feat(test): Added e2e test simulating a consumer of JSON RPC
2021-07-18 15:51:22 -07:00
Chris Troutner fa05fcf3d4 feat(test): Added e2e test simulating a consumer of JSON RPC 2021-07-18 15:46:32 -07:00
Chris Troutner f9846e95fd Created client scheme for JSON RPC 2021-07-18 08:09:27 -07:00
Chris Troutner def4f9003c Got simulated client to send a JSON RPC command 2021-07-17 19:51:56 -07:00
Chris Troutner 06cdc03287 Got client to connect to service 2021-07-17 19:14:11 -07:00
Chris Troutner c3bfbbb6e1 Merge pull request #10 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Setting name with an env var
2021-07-17 16:22:51 -07:00
Chris Troutner c7ed9eb3fd fix(ipfs-coord): Setting name with an env var 2021-07-17 16:19:03 -07:00
Chris Troutner a023202703 Adding debug log for mongodb connection string 2021-07-17 11:33:17 -07:00
Chris Troutner e31dceb07f Merge pull request #9 from Permissionless-Software-Foundation/ct-unstable
fix(production): Adjusting production settings
2021-07-17 11:25:38 -07:00
Chris Troutner af0e727ba8 fix(production): Fixed merge conflicts 2021-07-17 11:24:00 -07:00
Chris Troutner 6f64fc4652 fix(production): Adjusting production settings 2 2021-07-17 11:16:57 -07:00
Chris Troutner e91dd7f834 feat(production): Adjusting production settings 2021-07-17 20:16:19 +02:00
Chris Troutner e717124fc7 Merge pull request #8 from Permissionless-Software-Foundation/ct-unstable
fix(production): Updated Docker container
2021-07-17 10:55:48 -07:00
Chris Troutner 3c8d2cfdd3 fix(production): Updated Docker container 2021-07-17 10:54:00 -07:00
54 changed files with 25353 additions and 25956 deletions
+5
View File
@@ -7,6 +7,7 @@
#logs
logs/*.json
*.log
*.log.*
npm-debug.log*
# Runtime data
@@ -64,6 +65,10 @@ database/
system-user-*.json
orbitdb
ipfsdata
.ipfsdata
ipfs-service-provider.sh
start-bch-wallet-service.sh
data/
run-dev.sh
!README.md
+28 -1
View File
@@ -4,6 +4,9 @@
This is a censorship-resistant, IPFS-based microservice that provides access for wallets to access the Bitcoin Cash (BCH) blockchain. It leverages [bch-js](https://github.com/Permissionless-Software-Foundation/bch-js).
- [Decentralized Blockchain Service Providers](https://youtu.be/m_33rRXEats) YouTube video demos this software.
- [JSON RPC and REST API Documentation](https://ipfs-bch-wallet-service.fullstack.cash/)
## About This Repository
This repository is forked from the [ipfs-service-provider](https://github.com/Permissionless-Software-Foundation/ipfs-service-provider) repository. That code has been customized to provide BCH blockchain access for wallets. This server-side node.js app provides both REST API over HTTP and JSON RPC over IPFS endpoints for wallets to access the blockchain through.
@@ -26,13 +29,35 @@ This repository is one step in a longer path. Here are the major milestones of t
## Installation
### Development Environment
A development environment will allow you modify the code on-the-fly and contribute to the code base of this repository. [PM2](https://www.npmjs.com/package/pm2) is recommended for running this code base as an IPFS Circuit Relay.
- [Video: Installing ipfs-service-provider](https://youtu.be/Z0NsboIVN44)
- [Step-by-step installation instructions](https://gist.github.com/christroutner/3304a71d4c12a3a3e1664a438f64d9d0)
```bash
git clone https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service
cd ipfs-bch-wallet-service
./install-mongo.sh
npm install
npm start
cd shell-scripts
./ipfs-bch-wallet-service.sh
```
### Production Environment
The [docker](./production/docker) directory contains a Dockerfile for building a production deployment. However, there is currently [a bug](https://github.com/Permissionless-Software-Foundation/ipfs-service-provider/issues/38) preventing the Docker container from being used as a Circuit Relay.
```
docker-compose build --no-cache
docker-compose up -d
```
### Operation Notes
- There is a memory leak in the version of js-ipfs. The app is currently configured to shut down every 8 hours to flush memory. It relies on a process manager like pm2, Docker, or systemd to restart the app after it shuts down, in order to ensure continuous operation.
## Structure
The file layout of this repository differs from the koa-api-boilerplate. Instead, it follows the file layout of [Clean Architecture](troutsblog.com/blog/clean-architecture).
@@ -74,3 +99,5 @@ Snapshots pinned to IPFS will be listed here.
## License
[MIT](./LICENSE.md)
a
+105 -67
View File
@@ -1,3 +1,12 @@
/*
This Koa server has two interfaces:
- REST API over HTTP
- JSON RPC over IPFS
The architecture of the code follows the Clean Architecture pattern:
https://troutsblog.com/blog/clean-architecture
*/
// npm libraries
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
@@ -12,78 +21,107 @@ const cors = require('kcors')
// Local libraries
const config = require('../config') // this first.
// const IPFSLib = require('../src/lib/ipfs')
const AdminLib = require('../src/adapters/admin')
const adminLib = new AdminLib()
// const JSONRPC = require('../src/rpc')
// const rpc = new JSONRPC()
const errorMiddleware = require('../src/controllers/rest-api/middleware/error')
const { wlogger } = require('../src/adapters/wlogger')
async function startServer () {
// Create a Koa instance.
const app = new Koa()
app.keys = [config.session]
// Connect to the Mongo Database.
mongoose.Promise = global.Promise
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
await mongoose.connect(config.database, {
useUnifiedTopology: true,
useNewUrlParser: true
})
// MIDDLEWARE START
app.use(convert(logger()))
app.use(bodyParser())
app.use(session())
app.use(errorMiddleware())
// Used to generate the docs.
app.use(mount('/', serve(`${process.cwd()}/docs`)))
// Mount the page for displaying logs.
app.use(mount('/logs', serve(`${process.cwd()}/config/logs`)))
// User Authentication
require('../config/passport')
app.use(passport.initialize())
app.use(passport.session())
// Attach REST API and JSON RPC controllers to the app.
const controllers = require('../src/controllers')
await controllers.attachControllers(app)
// Enable CORS for testing
// THIS IS A SECURITY RISK. COMMENT OUT FOR PRODUCTION
app.use(cors({ origin: '*' }))
// MIDDLEWARE END
console.log(`Running server in environment: ${config.env}`)
wlogger.info(`Running server in environment: ${config.env}`)
await app.listen(config.port)
console.log(`Server started on ${config.port}`)
// Create the system admin user.
try {
const success = await adminLib.createSystemUser()
if (success) console.log('System admin user created.')
} catch (err) {
console.warn(
'Error trying to create system admin. Perhaps one already exists?'
)
class Server {
constructor () {
this.adminLib = new AdminLib()
}
return app
}
// startServer()
async startServer () {
try {
// Create a Koa instance.
const app = new Koa()
app.keys = [config.session]
// export default app
// module.exports = app
module.exports = {
startServer
// Connect to the Mongo Database.
mongoose.Promise = global.Promise
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
console.log(
`Connecting to MongoDB with this connection string: ${config.database}`
)
await mongoose.connect(config.database, {
useUnifiedTopology: true,
useNewUrlParser: true
})
console.log(`Starting environment: ${config.env}`)
console.log(`Debug level: ${config.debugLevel}`)
// MIDDLEWARE START
app.use(convert(logger()))
app.use(bodyParser())
app.use(session())
app.use(errorMiddleware())
// Used to generate the docs.
app.use(mount('/', serve(`${process.cwd()}/docs`)))
// Mount the page for displaying logs.
app.use(mount('/logs', serve(`${process.cwd()}/config/logs`)))
// User Authentication
require('../config/passport')
app.use(passport.initialize())
app.use(passport.session())
// Attach REST API and JSON RPC controllers to the app.
const Controllers = require('../src/controllers')
const controllers = new Controllers()
await controllers.attachRESTControllers(app)
app.controllers = controllers
// Enable CORS for testing
// THIS IS A SECURITY RISK. COMMENT OUT FOR PRODUCTION
app.use(cors({ origin: '*' }))
// MIDDLEWARE END
console.log(`Running server in environment: ${config.env}`)
wlogger.info(`Running server in environment: ${config.env}`)
await app.listen(config.port)
console.log(`Server started on ${config.port}`)
// Create the system admin user.
try {
const success = await this.adminLib.createSystemUser()
if (success) console.log('System admin user created.')
} catch (err) {
console.warn(
'Error trying to create system admin. Perhaps one already exists?'
)
}
// Attach the other IPFS controllers
await controllers.attachControllers(app)
// ipfs-coord has a memory leak. This app shuts down after 4 hours. It
// expects to be run by Docker or pm2, which can automatically restart
// the app.
setTimeout(function () {
process.exit(0)
}, 60000 * 60 * 2) // 2 hours
return app
} catch (err) {
console.error('Could not start server. Error: ', err)
console.log(
'Exiting after 5 seconds. Depending on process manager to restart.'
)
await sleep(5000)
process.exit(1)
}
}
}
function sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
module.exports = Server
-15
View File
@@ -1,15 +0,0 @@
/*
This file should be customized for your app. The string in this file is
displayed when a user makes the 'about' JSON RPC call.
*/
module.exports = `
This is the about string for the ipfs-service-provider repository:
https://github.com/Permissionless-Software-Foundation/ipfs-service-provider
Brought to you by the Permissionless Software Foundation:
https://PSFoundation.cash
Documentation:
https://ipfs-service-provider.fullstack.cash/
`
+42 -7
View File
@@ -5,6 +5,16 @@
/* eslint no-unneeded-ternary:0 */
// Get the version from the package.json file.
const pkgInfo = require('../../package.json')
const version = pkgInfo.version
const ipfsCoordName = process.env.COORD_NAME
? process.env.COORD_NAME
: 'ipfs-bch-wallet-service'
console.log('GET_JWT_AT_STARTUP: ', process.env.GET_JWT_AT_STARTUP)
module.exports = {
// Configure TCP port.
port: process.env.PORT || 5001,
@@ -24,28 +34,37 @@ module.exports = {
: 'emailpassword',
// FullStack.cash account information, used for automatic JWT handling.
AUTHSERVER: process.env.AUTHSERVER
getJwtAtStartup: process.env.GET_JWT_AT_STARTUP ? true : false,
authServer: process.env.AUTHSERVER
? process.env.AUTHSERVER
: 'https://auth.fullstack.cash',
APISERVER: process.env.APISERVER
apiServer: process.env.APISERVER
? process.env.APISERVER
: 'https://api.fullstack.cash/v5/',
FULLSTACKLOGIN: process.env.FULLSTACKLOGIN
fullstackLogin: process.env.FULLSTACKLOGIN
? process.env.FULLSTACKLOGIN
: 'demo@demo.com',
FULLSTACKPASS: process.env.FULLSTACKPASS ? process.env.FULLSTACKPASS : 'demo',
fullstackPassword: process.env.FULLSTACKPASS
? process.env.FULLSTACKPASS
: 'demo',
// IPFS settings.
isCircuitRelay: process.env.ENABLE_CIRCUIT_RELAY ? true : false,
// SSL domain used for websocket connection via browsers.
crDomain: process.env.CR_DOMAIN ? process.env.CR_DOMAIN : '',
// Information passed to other IPFS peers about this node.
apiInfo: 'https://ipfs-service-provider.fullstack.cash/',
apiInfo: 'https://ipfs-bch-wallet-service.fullstack.cash/',
ipfsCoordName: ipfsCoordName,
// JSON-LD and Schema.org schema with info about this app.
announceJsonLd: {
'@context': 'https://schema.org/',
'@type': 'WebAPI',
name: 'ipfs-bch-wallet-service',
name: ipfsCoordName,
version,
protocol: 'bch-wallet',
description:
'IPFS service providing BCH blockchain access needed by a wallet.',
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
@@ -54,5 +73,21 @@ module.exports = {
name: 'Permissionless Software Foundation',
url: 'https://PSFoundation.cash'
}
}
},
// IPFS Ports
ipfsTcpPort: process.env.IPFS_TCP_PORT ? process.env.IPFS_TCP_PORT : 5668,
ipfsWsPort: process.env.IPFS_WS_PORT ? process.env.IPFS_WS_PORT : 5669,
// BCH Mnemonic for generating encryption keys and payment address
mnemonic: process.env.MNEMONIC ? process.env.MNEMONIC : '',
debugLevel: process.env.DEBUG_LEVEL ? parseInt(process.env.DEBUG_LEVEL) : 2,
// Settings for production, using external go-ipfs node.
isProduction: process.env.SVC_ENV === 'production' ? true : false,
ipfsHost: process.env.IPFS_HOST ? process.env.IPFS_HOST : 'localhost',
ipfsApiPort: process.env.IPFS_API_PORT
? parseInt(process.env.IPFS_API_PORT)
: 5001
}
+1 -1
View File
@@ -7,6 +7,6 @@
module.exports = {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
database: 'mongodb://localhost:27017/ipfs-service-dev',
database: 'mongodb://localhost:27017/bch-service-dev',
env: 'dev'
}
+3 -1
View File
@@ -10,6 +10,8 @@
module.exports = {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
database: 'mongodb://172.17.0.1:5555/ipfs-service-prod',
database: process.env.DBURL
? process.env.DBURL
: 'mongodb://172.17.0.1:5555/bch-service-prod',
env: 'prod'
}
+1 -1
View File
@@ -7,6 +7,6 @@
module.exports = {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
database: 'mongodb://localhost:27017/ipfs-service-test',
database: 'mongodb://localhost:27017/bch-service-test',
env: 'test'
}
-1
View File
@@ -1 +0,0 @@
This is where the mongodb docker container stores its db files.
-25
View File
@@ -1,25 +0,0 @@
# Start the testnet server with the command 'docker-compose up -d'
koa-mongodb:
image: mongo
container_name: mongo-koa
ports:
- "5555:27017" # <host port>:<container port>
volumes:
- ./database:/data/db
command: mongod --smallfiles --logpath=/dev/null # -- quiet
restart: always
koa:
build: ./production/
dockerfile: Dockerfile
container_name: koa
links:
- koa-mongodb
ports:
- "5001:5001" # <host port>:<container port>
volumes:
# - ./logs:/home/coinjoin/consolidating-coinjoin/logs
- ./keys:/home/safeuser/keys
restart: always
+2 -1
View File
@@ -1,3 +1,4 @@
const server = require('./bin/server.js')
const Server = require('./bin/server.js')
const server = new Server()
server.startServer()
+23128 -25509
View File
File diff suppressed because it is too large Load Diff
+45 -42
View File
@@ -1,6 +1,6 @@
{
"name": "ipfs-bch-wallet-service",
"version": "1.0.0",
"version": "1.11.12",
"description": "IPFS and REST service providing blockchain access needed by a wallet. ",
"main": "index.js",
"scripts": {
@@ -23,50 +23,53 @@
},
"repository": "Permissionless-Software-Foundation/ipfs-bch-wallet-service",
"dependencies": {
"@psf/bch-js": "^4.20.2",
"axios": "^0.21.1",
"bcryptjs": "^2.4.3",
"glob": "^7.1.6",
"ipfs": "^0.54.4",
"ipfs-coord": "^4.0.1",
"jsonrpc-lite": "^2.2.0",
"jsonwebtoken": "^8.5.1",
"jwt-bch-lib": "^1.3.0",
"kcors": "^2.2.2",
"koa": "^2.13.1",
"koa-bodyparser": "^4.3.0",
"koa-convert": "^2.0.0",
"koa-generic-session": "^2.1.1",
"koa-logger": "^3.2.1",
"koa-mount": "^4.0.0",
"koa-passport": "^4.1.3",
"koa-router": "^10.0.0",
"koa-static": "^5.0.0",
"koa2-ratelimit": "^0.9.0",
"line-reader": "^0.4.0",
"mongoose": "^5.11.15",
"nodemailer": "^6.4.17",
"passport-local": "^1.0.0",
"winston": "^3.3.3",
"winston-daily-rotate-file": "^4.5.0"
"@psf/bch-js": "4.20.28",
"axios": "0.21.1",
"bcryptjs": "2.4.3",
"glob": "7.1.6",
"ipfs": "0.60.0",
"ipfs-coord": "6.8.2",
"ipfs-http-client": "55.0.0",
"jsonrpc-lite": "2.2.0",
"jsonwebtoken": "8.5.1",
"jwt-bch-lib": "1.3.0",
"kcors": "2.2.2",
"koa": "2.13.1",
"koa-bodyparser": "4.3.0",
"koa-convert": "2.0.0",
"koa-generic-session": "2.1.1",
"koa-logger": "3.2.1",
"koa-mount": "4.0.0",
"koa-passport": "4.1.3",
"koa-router": "10.0.0",
"koa-static": "5.0.0",
"koa2-ratelimit": "0.9.1",
"line-reader": "0.4.0",
"mongoose": "5.11.15",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.4.17",
"passport-local": "1.0.0",
"public-ip": "4.0.4",
"winston": "3.3.3",
"winston-daily-rotate-file": "4.5.0"
},
"devDependencies": {
"apidoc": "^0.26.0",
"chai": "^4.3.0",
"coveralls": "^3.1.0",
"apidoc": "0.26.0",
"chai": "4.3.0",
"coveralls": "3.1.0",
"eslint": "7.19.0",
"eslint-config-prettier": "^7.2.0",
"eslint-config-standard": "^16.0.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-standard": "^4.0.0",
"husky": "^4.3.8",
"mocha": "^8.2.1",
"nyc": "^15.1.0",
"semantic-release": "^17.4.4",
"sinon": "^9.2.4",
"standard": "^16.0.3",
"uuid": "^8.3.2"
"eslint-config-prettier": "7.2.0",
"eslint-config-standard": "16.0.2",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-prettier": "3.3.1",
"eslint-plugin-standard": "4.0.0",
"husky": "4.3.8",
"mocha": "8.2.1",
"nyc": "15.1.0",
"semantic-release": "17.4.4",
"sinon": "9.2.4",
"standard": "16.0.3",
"uuid": "8.3.2"
},
"release": {
"publish": [
-58
View File
@@ -1,58 +0,0 @@
# Create a Dockerized API server
#
#IMAGE BUILD COMMANDS
# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS
FROM christroutner/ct-base-ubuntu
MAINTAINER Chris Troutner <chris.troutner@gmail.com>
#Create the user 'safeuser' and add them to the sudo group.
#RUN useradd -ms /bin/bash safeuser
#RUN adduser safeuser sudo
#Set password to 'password' change value below if you want a different password
#RUN echo safeuser:password | chpasswd
#Set the working directory to be the home directory
WORKDIR /home/safeuser
#Setup NPM for non-root global install
#RUN mkdir /home/safeuser/.npm-global
#RUN chown -R safeuser .npm-global
#RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile
#RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'"
# Switch to user account.
USER safeuser
# Prep 'sudo' commands.
RUN echo 'abcd8765' | sudo -S pwd
# Clone the rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/christroutner/koa-api-boilerplate
RUN mv koa-api-boilerplate koa
RUN mkdir keys
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/koa
# For development: switch to unstable branch
# RUN git checkout unstable
# Install dependencies
RUN npm install
# Generate the API docs
RUN npm run docs
VOLUME /home/safeuser/keys
# Expose the port the API will be served on.
EXPOSE 5001
# Start the application.
COPY start-production start-production
CMD ["./start-production"]
#CMD ["npm", "start"]
+79
View File
@@ -0,0 +1,79 @@
# Create a Dockerized API server
#
#IMAGE BUILD COMMANDS
FROM ubuntu:20.04
MAINTAINER Chris Troutner <chris.troutner@gmail.com>
#Update the OS and install any OS packages needed.
RUN apt-get update
RUN apt-get install -y sudo git curl nano gnupg wget
#Install Node and NPM
RUN curl -sL https://deb.nodesource.com/setup_14.x -o nodesource_setup.sh
RUN bash nodesource_setup.sh
RUN apt-get install -y nodejs build-essential
#Create the user 'safeuser' and add them to the sudo group.
RUN useradd -ms /bin/bash safeuser
RUN adduser safeuser sudo
#Set password to 'password' change value below if you want a different password
RUN echo safeuser:password | chpasswd
#Set the working directory to be the home directory
WORKDIR /home/safeuser
#Setup NPM for non-root global install
RUN mkdir /home/safeuser/.npm-global
RUN chown -R safeuser .npm-global
RUN echo "export PATH=~/.npm-global/bin:$PATH" >> /home/safeuser/.profile
RUN runuser -l safeuser -c "npm config set prefix '~/.npm-global'"
# Update to the latest version of npm.
# Working with npm@7.21.1
RUN npm install -g npm
# Update to the latest version of npm.
#RUN npm install -g npm@7.23.0
RUN npm install -g npm
# npm mirror to prevent direct dependency on npm.
RUN npm set registry http://94.130.170.209:4873/
# Switch to user account.
#USER safeuser
# Prep 'sudo' commands.
#RUN echo 'abcd8765' | sudo -S pwd
# Clone the repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-bch-wallet-service
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/ipfs-bch-wallet-service
# For development: switch to unstable branch
RUN git checkout ct-unstable
# Install dependencies
#RUN npm install -g @mapbox/node-pre-gyp
RUN npm install
# Generate the API docs
RUN npm run docs
# Calling out the directorys that should be mounted as external volumes.
RUN mkdir /home/safeuser/.ipfsdata
#RUN mkdir /home/safeuser/orbitdb
#VOLUME /home/safeuser/ipfsdata
#VOLUME /home/safeuser/orbitdb
EXPOSE 5010
# Start the application.
COPY start-production.sh start-production.sh
CMD ["./start-production.sh"]
#CMD ["npm", "start"]
+5
View File
@@ -0,0 +1,5 @@
#!/bin/bash
# Remove all untagged docker images.
docker rmi $(docker images | grep "^<none>" | awk '{print $3}')
+61
View File
@@ -0,0 +1,61 @@
# Start the service with the command 'docker-compose up -d'
version: '3.9'
services:
mongo-bch-service:
image: mongo
container_name: mongo-bch-service
ports:
- '5555:27017' # <host port>:<container port>
volumes:
- ../data/mongodb:/data/db
command: mongod --logpath=/dev/null # -- quiet
restart: always
ipfs-bch-wallet:
image: ipfs/go-ipfs:latest
container_name: ipfs-bch-wallet
environment:
MY_ENV_VAR: 'placeholder'
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 2000mb
ports:
- 4001:4001
- 5001:5001
- 8080:8080
volumes:
- ../data/go-ipfs/data:/data/ipfs
- ../data/go-ipfs/export:/export
# https://docs.docker.com/compose/compose-file/compose-file-v3/#command
# https://github.com/ipfs/go-ipfs/blob/91c52657166bcf86f2476926e4fe56694dc26562/Dockerfile#L115
command:
[
'daemon',
'--migrate=true',
'--agent-version-suffix=docker',
'--enable-pubsub-experiment'
]
restart: always
bch-wallet-service:
build: ./
container_name: bch-wallet-service
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1000mb
links:
- mongo-bch-service
- ipfs-bch-wallet
ports:
- '5010:5010' # <host port>:<container port>
volumes:
- ../data/ipfsdata:/home/safeuser/ipfs-bch-wallet-service/.ipfsdata
restart: always
+48
View File
@@ -0,0 +1,48 @@
#!/bin/bash
# BEGIN: Optional configuration settings
# This mnemonic is used to set up persistent public key for e2ee
# Replace this with your own 12-word mnemonic.
# You can get one at https://wallet.fullstack.cash.
export MNEMONIC="olive two muscle bottom coral ancient wait legend bronze useful process session"
# The human readable name this IPFS node identifies as.
export COORD_NAME=bch-wallet-service-generic
# Allow this node to function as a circuit relay. It must not be behind a firewall.
#export ENABLE_CIRCUIT_RELAY=1
# For browsers to use your circuit realy, you must set up a domain, SSL certificate,
# and you must forward that subdomain to the IPFS_WS_PORT.
#export CR_DOMAIN=subdomain.yourdomain.com
# Debug level. 0 = minimal info. 2 = max info.
export DEBUG_LEVEL=1
# END: Optional configuration settings
# Production database connection string.
export DBURL=mongodb://172.17.0.1:5555/ipfs-service-prod
# Customize these environment variables for your own installation.
export GET_JWT_AT_STARTUP=1
export AUTHSERVER=https://auth.fullstack.cash
export APISERVER=https://api.fullstack.cash/v5/
export FULLSTACKLOGIN=demo@demo.com
export FULLSTACKPASS=demo
# Configure IPFS ports
#export IPFS_TCP_PORT=5268
#export IPFS_WS_PORT=5269
# Configure REST API port
export PORT=5010
# Production settings using external go-ipfs node.
export SVC_ENV=production
export IPFS_HOST=172.17.0.1
export IPFS_API_PORT=5001
npm start
-3
View File
@@ -1,3 +0,0 @@
#!/bin/bash
export KOA_ENV=production
npm start
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
# This script is an example for running a generic ipfs-service-provider instance
# using a local installation of bch-api.
# Ports
export PORT=5002 # REST API port
export IPFS_TCP_PORT=5268
export IPFS_WS_PORT=5269
# The human-readible name that is used when displaying data about this node.
export COORD_NAME=ipfs-service-provider-generic
# This is used for end-to-end encryption (e2ee).
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
# 0 = less verbose. 3 = most verbose
export DEBUG_LEVEL=1
# MongoDB connection string.
#export DBURL=mongodb://localhost:27017/bch-service-dev
# Customize these environment variables for your own installation.
export GET_JWT_AT_STARTUP=0
export APISERVER=http://localhost:3000/v5/
npm start
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# This script is an example for running a generic ipfs-service-provider instance.
# Ports
export PORT=5002 # REST API port
export IPFS_TCP_PORT=5268
export IPFS_WS_PORT=5269
# The human-readible name that is used when displaying data about this node.
export COORD_NAME=ipfs-service-provider-generic
# This is used for end-to-end encryption (e2ee).
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
# 0 = less verbose. 3 = most verbose
export DEBUG_LEVEL=1
# MongoDB connection string.
#export DBURL=mongodb://localhost:27017/bch-service-dev
npm start
+22
View File
@@ -0,0 +1,22 @@
#!/bin/bash
# This script is an example for running a generic ipfs-service-provider instance.
# Ports
export PORT=5001 # REST API port
export IPFS_TCP_PORT=5268
export IPFS_WS_PORT=5269
# The human-readible name that is used when displaying data about this node.
export COORD_NAME=ipfs-service-provider-generic
# This is used for end-to-end encryption (e2ee).
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
# 0 = less verbose. 3 = most verbose
export DEBUG_LEVEL=1
# MongoDB connection string.
#export DBURL=mongodb://localhost:27017/bch-service-dev
npm start
+31
View File
@@ -0,0 +1,31 @@
#!/bin/bash
# This script is an example for running a ipfs-service-provider as a Circuit Relay.
# Circuit Relays are help other nodes on the network communicate. They are
# critical for reliable functioning of the network, and for circumventing
# censorship.
# Ports
export PORT=5001 # REST API port
export IPFS_TCP_PORT=5268
export IPFS_WS_PORT=5269
# The human-readible name that is used when displaying data about this node.
export COORD_NAME=ipfs-service-provider-generic
# This is used for end-to-end encryption (e2ee).
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
# 0 = less verbose. 3 = most verbose
export DEBUG_LEVEL=1
# MongoDB connection string.
#export DBURL=mongodb://localhost:27017/bch-service-dev
# Comment to disable circuit relay functionality. Or set to 1 to enable.
export ENABLE_CIRCUIT_RELAY=1
# For browsers to use your circuit realy, you must set up a domain, SSL certificate,
# and you must forward that subdomain to the IPFS_WS_PORT.
#export CR_DOMAIN=subdomain.yourdomain.com
npm start
+28
View File
@@ -0,0 +1,28 @@
#!/bin/bash
# This script is an example for running a production environment, which is
# defined by running an external go-ipfs node.
# Ports
export PORT=5010 # REST API port
# The human-readible name that is used when displaying data about this node.
export COORD_NAME=ipfs-service-provider-generic
# This is used for end-to-end encryption (e2ee).
export MNEMONIC="churn aisle shield silver ladder swear hunt slim pen demand spoil veteran"
# 0 = less verbose. 3 = most verbose
export DEBUG_LEVEL=1
# Production settings that use external IPFS node.
# https://github.com/christroutner/docker-ipfs
export SVC_ENV=production
#export IPFS_HOST=localhost
export IPFS_HOST=172.17.0.1
export IPFS_API_PORT=5001
# MongoDB connection string.
export DBURL=mongodb://localhost:27017/ipfs-service-dev
npm start
+4 -4
View File
@@ -23,13 +23,13 @@ class FullStackJWT {
'Must pass a url for the API server when instantiating FullStackJWT class.'
)
}
this.login = localConfig.login
this.login = localConfig.fullstackLogin
if (!this.login || typeof this.login !== 'string') {
throw new Error(
'Must pass a FullStack.cash login (email) instantiating FullStackJWT class.'
)
}
this.password = localConfig.password
this.password = localConfig.fullstackPassword
if (!this.password || typeof this.password !== 'string') {
throw new Error(
'Must pass a FullStack.cash account password when instantiating FullStackJWT class.'
@@ -39,7 +39,7 @@ class FullStackJWT {
// Encapsulate dependencies
this.jwtLib = new JwtLib({
// Overwrite default values with the values in the config file.
server: this.server,
server: this.authServer,
login: this.login,
password: this.password
})
@@ -53,7 +53,7 @@ class FullStackJWT {
async getJWT () {
try {
// Skip connecting FullStack.cash auth server to the network if this is an E2E test.
if (process.env.E2ETEST) {
if (process.env.TEST_TYPE === 'e2e') {
this.apiToken = 'faketoken'
return this.apiToken
}
+40 -28
View File
@@ -4,8 +4,8 @@
https://troutsblog.com/blog/clean-architecture
*/
// Load the config file
const config = require('../../config')
// Public NPM libraries
const BCHJS = require('@psf/bch-js')
// Load individual adapter libraries.
const IPFSAdapter = require('./ipfs')
@@ -13,35 +13,47 @@ const LocalDB = require('./localdb')
const LogsAPI = require('./logapi')
const Passport = require('./passport')
const Nodemailer = require('./nodemailer')
const { wlogger } = require('./wlogger')
// const { wlogger } = require('./wlogger')
const JSONFiles = require('./json-files')
const FullStackJWT = require('./fullstack-jwt')
// Instantiate adapter libraries.
const ipfs = new IPFSAdapter()
const localdb = new LocalDB()
const logapi = new LogsAPI()
const passport = new Passport()
const nodemailer = new Nodemailer()
const jsonFiles = new JSONFiles()
const config = require('../../config')
// Get a valid JWT API key and instance bch-js.
const fullStackJwt = new FullStackJWT({
authServer: config.AUTHSERVER,
apiServer: config.APISERVER,
login: config.FULLSTACKLOGIN,
password: config.FULLSTACKPASS
})
const bchjs = {} // Placeholder.
class Adapters {
constructor (localConfig = {}) {
// Encapsulate dependencies
this.ipfs = new IPFSAdapter()
this.localdb = new LocalDB()
this.logapi = new LogsAPI()
this.passport = new Passport()
this.nodemailer = new Nodemailer()
this.jsonFiles = new JSONFiles()
this.bchjs = new BCHJS()
this.config = config
module.exports = {
ipfs,
localdb,
logapi,
passport,
nodemailer,
wlogger,
jsonFiles,
fullStackJwt,
bchjs
// Get a valid JWT API key and instance bch-js.
this.fullStackJwt = new FullStackJWT(config)
}
async start () {
try {
if (this.config.getJwtAtStartup) {
// Get a JWT token and instantiate bch-js with it. Then pass that instance
// to all the rest of the apps controllers and adapters.
await this.fullStackJwt.getJWT()
// Instantiate bch-js with the JWT token, and overwrite the placeholder for bch-js.
this.bchjs = await this.fullStackJwt.instanceBchjs()
} else {
this.bchjs = new BCHJS({ restURL: this.config.apiServer })
}
// Start the IPFS node.
await this.ipfs.start({ bchjs: this.bchjs })
} catch (err) {
console.error('Error in adapters/index.js/start()')
throw err
}
}
}
module.exports = Adapters
+9
View File
@@ -10,6 +10,7 @@ class IPFS {
// Encapsulate dependencies
this.ipfsAdapter = new IpfsAdapter()
this.IpfsCoordAdapter = IpfsCoordAdapter
this.process = process
this.ipfsCoordAdapter = {} // placeholder
@@ -46,6 +47,14 @@ class IPFS {
return true
} catch (err) {
console.error('Error in adapters/ipfs/index.js/start()')
// If error is due to a lock file issue. Kill the process, so that
// Docker or pm2 has a chance to restart the service.
if (err.message.includes('Lock already being held')) {
console.log('lock being held. Exiting.')
this.process.exit(1)
}
throw err
}
}
+36 -10
View File
@@ -7,6 +7,7 @@
// Global npm libraries
const IpfsCoord = require('ipfs-coord')
// const BCHJS = require('@psf/bch-js')
const publicIp = require('public-ip')
// Local libraries
const config = require('../../../config')
@@ -35,6 +36,7 @@ class IpfsCoordAdapter {
this.ipfsCoord = {}
// this.rpc = new JSONRPC()
this.config = config
this.publicIp = publicIp
// Properties of this class instance.
this.isReady = false
@@ -43,24 +45,48 @@ class IpfsCoordAdapter {
}
async start (localConfig = {}) {
this.ipfsCoord = new this.IpfsCoord({
const circuitRelayInfo = {}
// If configured as a Circuit Relay, get the public IP addresses for this node.
if (this.config.isCircuitRelay) {
try {
const ip4 = await this.publicIp.v4()
// const ip6 = await publicIp.v6()
circuitRelayInfo.ip4 = ip4
circuitRelayInfo.tcpPort = this.config.ipfsTcpPort
// Domain used by browser-based secure websocket connections.
circuitRelayInfo.crDomain = this.config.crDomain
} catch (err) {
/* exit quietly */
}
}
const ipfsCoordOptions = {
ipfs: this.ipfs,
type: 'node.js',
// type: 'browser',
bchjs: this.bchjs,
privateLog: console.log, // Default to console.log
isCircuitRelay: this.config.isCircuitRelay,
circuitRelayInfo,
apiInfo: this.config.apiInfo,
announceJsonLd: this.config.announceJsonLd
})
// Skip connecting ipfs-coord to the network if this is an E2E test.
if (!process.env.E2ETEST) {
// Wait for the ipfs-coord library to signal that it is ready.
await this.ipfsCoord.ipfs.start()
await this.ipfsCoord.isReady()
announceJsonLd: this.config.announceJsonLd,
mnemonic: this.config.mnemonic,
debugLevel: this.config.debugLevel
}
// Production env uses external go-ipfs node.
if (this.config.isProduction) {
ipfsCoordOptions.nodeType = 'external'
}
this.ipfsCoord = new this.IpfsCoord(ipfsCoordOptions)
// Wait for the ipfs-coord library to signal that it is ready.
await this.ipfsCoord.start({ type: 'node.js' })
// Signal that this adapter is ready.
this.isReady = true
@@ -72,7 +98,7 @@ class IpfsCoordAdapter {
attachRPCRouter (router) {
try {
_this.ipfsCoord.privateLog = router
_this.ipfsCoord.ipfs.orbitdb.privateLog = router
_this.ipfsCoord.adapters.orbit.privateLog = router
} catch (err) {
console.error('Error in attachRPCRouter()')
throw err
+74 -16
View File
@@ -2,36 +2,53 @@
Clean Architecture Adapter for IPFS.
This library deals with IPFS so that the apps business logic doesn't need
to have any specific knowledge of the js-ipfs library.
TODO: Add the external IP address to the list of multiaddrs advertised by
this node. See this GitHub Issue for details:
https://github.com/Permissionless-Software-Foundation/ipfs-service-provider/issues/38
*/
// Global npm libraries
const IPFS = require('ipfs')
// const IPFS = require('ipfs')
// const IPFS = require('@chris.troutner/ipfs')
const IPFSembedded = require('ipfs')
const IPFSexternal = require('ipfs-http-client')
const fs = require('fs')
// Local libraries
const config = require('../../../config')
const IPFS_DIR = './.ipfsdata/ipfs'
class IpfsAdapter {
constructor (localConfig) {
// Encapsulate dependencies
this.IPFS = IPFS
this.config = config
// Choose the IPFS constructor based on the config settings.
this.IPFS = IPFSembedded // default
if (this.config.isProduction) {
this.IPFS = IPFSexternal
}
// Properties of this class instance.
this.isReady = false
this.config = config
this.fs = fs
}
// Start an IPFS node.
async start () {
try {
// Ipfs Options
const ipfsOptions = {
repo: './ipfsdata',
const ipfsOptionsEmbedded = {
repo: IPFS_DIR,
start: true,
config: {
relay: {
enabled: true, // enable circuit relay dialer and listener
hop: {
enabled: true // enable circuit relay HOP (make this node a relay)
enabled: config.isCircuitRelay // enable circuit relay HOP (make this node a relay)
}
},
pubsub: true, // enable pubsub
@@ -46,26 +63,34 @@ class IpfsAdapter {
`/ip4/0.0.0.0/tcp/${this.config.ipfsTcpPort}`,
`/ip4/0.0.0.0/tcp/${this.config.ipfsWsPort}/ws`
]
},
Datastore: {
StorageMax: '2GB',
StorageGCWatermark: 50,
GCPeriod: '15m'
}
}
}
const ipfsOptionsExternal = {
host: this.config.ipfsHost,
port: this.config.ipfsApiPort
}
let ipfsOptions = ipfsOptionsEmbedded
if (this.config.isProduction) {
ipfsOptions = ipfsOptionsExternal
}
// Create a new IPFS node.
this.ipfs = await this.IPFS.create(ipfsOptions)
// Set the 'server' profile so the node does not scan private networks.
await this.ipfs.config.profiles.apply('server')
// const nodeConfig = await this.ipfs.config.getAll()
// console.log(
// `IPFS node configuration: ${JSON.stringify(nodeConfig, null, 2)}`
// )
// Stop the IPFS node if we're running tests.
if (this.config.env === 'test') {
console.log('Stopping IPFS for tests.')
await this.ipfs.stop()
}
// Debugging: Display IPFS config settings.
// const configSettings = await this.ipfs.config.getAll()
// console.log(`configSettings: ${JSON.stringify(configSettings, null, 2)}`)
// Signal that this adapter is ready.
this.isReady = true
@@ -73,6 +98,39 @@ class IpfsAdapter {
return this.ipfs
} catch (err) {
console.error('Error in ipfs.js/start()')
// If IPFS crashes because the /blocks directory is full, wipe the directory.
if (err.message.includes('No space left on device')) {
console.log('No space left in /blocks folder. Deleting blocks folder.')
this.rmBlocksDir()
}
throw err
}
}
async stop () {
await this.ipfs.stop()
return true
}
// Remove the '/blocks' directory that is used to store IPFS data.
// Dev Note: It's assumed this node is not pinning any data and that
// everything in this directory is transient. This folder will regularly
// fill up and prevent IPFS from starting.
rmBlocksDir () {
try {
const dir = `${IPFS_DIR}/blocks`
console.log(`Deleting ${dir} directory...`)
this.fs.rmdirSync(dir, { recursive: true })
console.log(`${dir} directory is deleted!`)
return true // Signal successful execution.
} catch (err) {
console.log('Error in rmBlocksDir()')
throw err
}
}
+54 -44
View File
@@ -11,52 +11,62 @@ require('winston-daily-rotate-file')
const config = require('../../config')
// Configure daily-rotation transport.
const transport = new winston.transports.DailyRotateFile({
filename: `${__dirname.toString()}/../../logs/koa-${config.env}-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: false,
maxSize: '1m', // 1 megabyte
maxFiles: '5d', // 5 days
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
)
})
class Wlogger {
constructor (localConfig = {}) {
this.config = config
transport.on('rotate', notifyRotation)
function notifyRotation (oldFilename, newFilename) {
wlogger.info('Rotating log files')
}
// This controls what goes into the log FILES
const wlogger = winston.createLogger({
level: 'verbose',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
// new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
// new winston.transports.File({ filename: 'logs/combined.log' })
transport
]
})
function outputToConsole () {
wlogger.add(
new winston.transports.Console({
format: winston.format.simple(),
level: 'info'
// Configure daily-rotation transport.
this.transport = new winston.transports.DailyRotateFile({
filename: `${__dirname.toString()}/../../logs/koa-${
this.config.env
}-%DATE%.log`,
datePattern: 'YYYY-MM-DD',
zippedArchive: false,
maxSize: '1m', // 1 megabyte
maxFiles: '5d', // 5 days
format: winston.format.combine(
winston.format.timestamp(),
winston.format.json()
)
})
)
this.transport.on('rotate', this.notifyRotation)
// This controls what goes into the log FILES
this.wlogger = winston.createLogger({
level: 'verbose',
format: winston.format.json(),
transports: [
//
// - Write to all logs with level `info` and below to `combined.log`
// - Write all logs error (and below) to `error.log`.
//
// new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
// new winston.transports.File({ filename: 'logs/combined.log' })
this.transport
]
})
}
notifyRotation (oldFilename, newFilename) {
this.wlogger.info('Rotating log files')
}
outputToConsole () {
this.wlogger.add(
new winston.transports.Console({
format: winston.format.simple(),
level: 'info'
})
)
}
}
// This controls the logs to CONSOLE
// if (config.env !== 'test') {
// outputToConsole()
// }
const logger = new Wlogger()
module.exports = { wlogger, notifyRotation, outputToConsole }
// Allow the logger to write to the console.
logger.outputToConsole()
const wlogger = logger.wlogger
module.exports = { wlogger, Wlogger }
+36 -38
View File
@@ -7,57 +7,55 @@
// Public npm libraries.
// Load the Clean Architecture Adapters library
const adapters = require('../adapters')
const Adapters = require('../adapters')
// Load the JSON RPC Controller.
const JSONRPC = require('./json-rpc')
// Load the Clean Architecture Use Case libraries.
const UseCases = require('../use-cases')
const useCases = new UseCases({ adapters })
// const useCases = new UseCases({ adapters })
// Load the REST API Controllers.
const RESTControllers = require('./rest-api')
// Top-level function for this library.
// Start the various Controllers and attach them to the app.
async function attachControllers (app) {
try {
// Get a JWT token and instantiate bch-js with it. Then pass that instance
// to all the rest of the apps controllers and adapters.
await adapters.fullStackJwt.getJWT()
// Instantiate bch-js with the JWT token, and overwrite the placeholder for bch-js.
adapters.bchjs = await adapters.fullStackJwt.instanceBchjs()
class Controllers {
constructor (localConfig = {}) {
this.adapters = new Adapters()
this.useCases = new UseCases({ adapters: this.adapters })
}
// Attach the REST controllers to the Koa app.
attachRESTControllers(app)
async attachControllers (app) {
// Wait for any startup processes to complete for the Adapters libraries.
await this.adapters.start()
// Start IPFS.
await adapters.ipfs.start({ bchjs: adapters.bchjs })
this.attachRPCControllers()
}
attachRPCControllers()
} catch (err) {
console.error('Error in attachControllers()')
throw err
// Top-level function for this library.
// Start the various Controllers and attach them to the app.
attachRESTControllers (app) {
const restControllers = new RESTControllers({
adapters: this.adapters,
useCases: this.useCases
})
// Attach the REST API Controllers associated with the boilerplate code to the Koa app.
restControllers.attachRESTControllers(app)
}
// Add the JSON RPC router to the ipfs-coord adapter.
attachRPCControllers () {
const jsonRpcController = new JSONRPC({
adapters: this.adapters,
useCases: this.useCases
})
// Attach the input of the JSON RPC router to the output of ipfs-coord.
this.adapters.ipfs.ipfsCoordAdapter.attachRPCRouter(
jsonRpcController.router
)
}
}
function attachRESTControllers (app) {
const rESTControllers = new RESTControllers({
adapters,
useCases
})
// Attach the REST API Controllers associated with the boilerplate code to the Koa app.
rESTControllers.attachRESTControllers(app)
}
// Add the JSON RPC router to the ipfs-coord adapter.
function attachRPCControllers () {
const jsonRpcController = new JSONRPC({ adapters, useCases })
// Attach the input of the JSON RPC router to the output of ipfs-coord.
adapters.ipfs.ipfsCoordAdapter.attachRPCRouter(jsonRpcController.router)
}
module.exports = { attachControllers }
module.exports = Controllers
+3 -2
View File
@@ -6,7 +6,7 @@
const jsonrpc = require('jsonrpc-lite')
// Local libraries
const aboutStr = require('../../../../config/about')
const config = require('../../../../config')
class AboutRPC {
constructor (localConfig) {
@@ -36,7 +36,8 @@ class AboutRPC {
return {
success: true,
status: 200,
message: aboutStr,
// message: aboutStr,
message: JSON.stringify(config.announceJsonLd),
endpoint: 'about'
}
}
+354 -8
View File
@@ -68,6 +68,10 @@ class BCHRPC {
case 'transaction':
await this.rateLimit.limiter(rpcData.from)
return await this.transaction(rpcData)
case 'pubkey':
await this.rateLimit.limiter(rpcData.from)
return await this.pubKey(rpcData)
}
} catch (err) {
console.error('Error in BCHRPC/rpcRouter()')
@@ -88,10 +92,49 @@ class BCHRPC {
* @apiName Transactions
* @apiGroup JSON BCH
* @apiDescription This endpoint wraps the bchjs.Electrumx.transactions([]) function.
* Given the 'addresses' property this endpoint returns an object with the following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - method: "" - Method used in the petition
* - receiver: "" - Receiver address
* - value: {} - Final result value of the petition
* - success : - Petition status
* - transactions : [] - Transactions of the provided adresses
* - transactions: [] - Transaction details
* - height : - Reference to the blockchain size
* - tx_hash: "" - Hash of the transaction
* - address : "" - Address asociated to the transactions
* - status: - HTTP Status Code
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "transactions", "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"]}}
*
* @apiSuccessExample {json} Success-Response:
* {
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value":{
* "success":true,
* "transactions":[
* {
* "transactions":[
* {
* "height":631219,
* "tx_hash":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f"
* }
* ],
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"
* }
* ],
* "status":200
* }
* }
* }
*/
async transactions (rpcData) {
try {
@@ -107,7 +150,7 @@ class BCHRPC {
return retObj
} catch (err) {
// console.error('Error in createUser()')
console.error('Error in JSON RPC BCH transactions()')
// throw err
// Return an error response
@@ -127,9 +170,48 @@ class BCHRPC {
* @apiGroup JSON BCH
* @apiDescription This endpoint wraps the bchjs.Electrumx.balance([]) function.
*
* Given the 'addresses' property it returns an object
* with the following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - method: "" - Method used in the petition
* - receiver: "" - Receiver address
* - value: {} - Final result value of the petition
* - success : - Petition status
* - balances : [] - Balance of the provided addresses
* - balance : {} - Object with the balance types of an address
* - confirmed : - Confirmed balance
* - unconfirmed : - Unconfirmed balance
* - address : "" - Address related to the balance
* - status: - HTTP Status Code
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "balance", "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"]}}
*
* @apiSuccessExample {json} Success-Response:
* {
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value":{
* "success":true,
* "balances":[
* {
* "balance":{
* "confirmed":1000,
* "unconfirmed":0
* },
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"
* }
* ],
* "status":200
* }
* }
* }
*/
async balance (rpcData) {
try {
@@ -145,7 +227,7 @@ class BCHRPC {
return retObj
} catch (err) {
// console.error('Error in createUser()')
console.error('Error in JSON RPC BCH balance()')
// throw err
// Return an error response
@@ -167,15 +249,89 @@ class BCHRPC {
* endpoint returns UTXOs held at an address, hydrated
* with token information.
*
* Given an address this endpoint will return an object
* with the following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - method: "" - Method used in the petition
* - receiver: "" - Receiver address
* - value: [] - Final result value of the petition
* - address: "" - the address these UTXOs are associated with
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
* not spent, to be safe.
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
* - type1: {}
* - tokens: [] - SLP token Type 1 tokens.
* - mintBatons: [] - SLP token Type 1 mint batons.
* - nft: {}
* - tokens: [] - NFT tokens
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "utxos", "address": "bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"}}
*
* @apiSuccessExample {json} Success-Response:
*
* {
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value":[
* {
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj",
* "bchUtxos":[
* {
* "height":631219,
* "tx_hash":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
* "tx_pos":0,
* "value":1000,
* "txid":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
* "vout":0,
* "isValid":false
* }
* ],
* "nullUtxos":[
*
* ],
* "slpUtxos":{
* "type1":{
* "mintBatons":[
*
* ],
* "tokens":[
*
* ]
* },
* "nft":{
* "groupMintBatons":[
*
* ],
* "groupTokens":[
*
* ],
* "tokens":[
*
* ]
* }
* }
* }
* ]
* }
* }
*
*/
async utxos (rpcData) {
try {
// console.log('createUser rpcData: ', rpcData)
const addr = rpcData.payload.params.address
console.log('addr: ', addr)
const data = await this.bchjs.Utxo.get(addr)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
@@ -185,7 +341,8 @@ class BCHRPC {
return retObj
} catch (err) {
// console.error('Error in createUser()')
console.error('Error in JSON RPC BCH utxos()')
console.error('Error in JSON RPC utxos(): ', err)
// throw err
// Return an error response
@@ -206,9 +363,27 @@ class BCHRPC {
* @apiDescription Broadcast a transaction to the BCH network.
* The transaction should be encoded as a hexidecimal string.
*
* This endpoint will return an object with the following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - method: "" - Method used in the petition
* - receiver: "" - Receiver address
* - value: "" - Final result value of the petition
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "broadcast", "hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000"}}
*
* @apiSuccessExample {json} Success-Response:
*
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value": "951299775f68a599b95239bfc385423f87a33e11747c299a22ef9dcf3d1557ec"
*
*/
async broadcast (rpcData) {
try {
@@ -219,19 +394,35 @@ class BCHRPC {
const data = await this.bchjs.RawTransactions.sendRawTransaction(hex)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
const retObj = data
retObj.status = 200
const retObj = {
success: true,
status: 200,
endpoint: 'broadcast',
txid: data
}
// retObj.status = 200
return retObj
} catch (err) {
// console.error('Error in createUser()')
console.error('Error in JSON RPC BCH broadcast()')
console.log('error: ', err)
// throw err
// bch-api will sometimes return an error message, not an error object.
let message = ''
if (!err.message && err.error) {
// Full node error
message = err.error
} else {
// Normal error
message = err.message
}
// Return an error response
return {
success: false,
status: 422,
message: err.message,
message,
endpoint: 'broadcast'
}
}
@@ -243,10 +434,93 @@ class BCHRPC {
* @apiName Transaction
* @apiGroup JSON BCH
* @apiDescription Get data about a specific transaction.
* Given a transaction the endpoint will return an object with the
* following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - method: "" - Method used in the petition
* - receiver: "" - Receiver address
* - value: {} - Final result value of the petition
* - txid: "" - Transaction ID
* - hash: "" - Transaction hash
* - version: - Version number
* - size: - Transaction size
* - locktime: -
* - vin: [] - Transaction inputs
* - vout: [] - Transaction outputs
* - hex: "" - hexadecimal script
* - blockhash: "" - Reference to the block register
* - confirmations : "" - Transaction confirmations
* - time: - Execution time
* - blocktime: - Execution time
* - isValidSLPTx: - Determines if the transaction was under SLP
* - status: - HTTP Status Code
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "transaction", "txid": "01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b"}}
*
* @apiSuccessExample {json} Success-Response:
* {
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value":{
* "txid":"01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b",
* "hash":"01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b",
* "version":1,
* "size":272,
* "locktime":0,
* "vin":[
* {
* "txid":"4deef6de4b973706cd6e8fc8105a41a84be349e4e9717225ee5e7c63538e95e8",
* "vout":1,
* "scriptSig":{
* "asm":"3045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f2496[ALL|FORKID] 0467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3",
* "hex":"483045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f249641410467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3"
* },
* "sequence":4294967295,
* "address":"bitcoincash:qqrxa0h9jqnc7v4wmj9ysetsp3y7w9l36u8gnnjulq",
* "value":0.00001824
* }
* ],
* "vout":[
* {
* "value":0,
* "n":0,
* "scriptPubKey":{
* "asm":"OP_RETURN -385055325 46226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a",
* "hex":"6a045d7af3962046226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a",
* "type":"nulldata"
* }
* },
* {
* "value":0.0000155,
* "n":1,
* "scriptPubKey":{
* "asm":"OP_DUP OP_HASH160 066ebee590278f32aedc8a4865700c49e717f1d7 OP_EQUALVERIFY OP_CHECKSIG",
* "hex":"76a914066ebee590278f32aedc8a4865700c49e717f1d788ac",
* "reqSigs":1,
* "type":"pubkeyhash",
* "addresses":[
* "bitcoincash:qqrxa0h9jqnc7v4wmj9ysetsp3y7w9l36u8gnnjulq"
* ]
* }
* }
* ],
* "hex":"0100000001e8958e53637c5eee257271e9e449e34ba8415a10c88f6ecd0637974bdef6ee4d010000008b483045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f249641410467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3ffffffff020000000000000000276a045d7af3962046226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a0e060000000000001976a914066ebee590278f32aedc8a4865700c49e717f1d788ac00000000",
* "blockhash":"0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536",
* "confirmations":98000,
* "time":1568338904,
* "blocktime":1568338904,
* "isValidSLPTx":false,
* "status":200
* }
* }
* }
*/
async transaction (rpcData) {
try {
@@ -262,7 +536,7 @@ class BCHRPC {
return retObj
} catch (err) {
// console.error('Error in createUser()')
console.error('Error in JSON RPC BCH transaction()')
// throw err
// Return an error response
@@ -274,6 +548,78 @@ class BCHRPC {
}
}
}
/**
* @api {JSON} /bch PubKey
* @apiPermission public
* @apiName PubKey
* @apiGroup JSON BCH
* @apiDescription Get the public key from an address.
* Given an address the endpoint will return an object with the
* following properties
*
* - jsonrpc: "" - jsonrpc version
* - id: "" - jsonrpc id
* - result: {} - Result of the petition with the RPC information
* - success: - Request status
* - publickey: - Address public key
*
* @apiExample Example usage:
* {"jsonrpc":"2.0","id":"555","method":"bch","params":{ "endpoint": "pubkey", "address": "bitcoincash:qpnty9t0w93fez04h7yzevujpv8pun204qv6yfuahk"}}
*
* @apiSuccessExample {json} Success-Response:
* {
* "jsonrpc":"2.0",
* "id":"555",
* "result":{
* "method":"bch",
* "reciever":"QmU86vLVbUY1UhziKB6rak7GPKRA2QHWvzNm2AjEvXNsT6",
* "value":{
* "success": true,
* "status": 200,
* "endpoint": "pubkey",
* "pubkey": {
* "success": true,
* "publicKey": "033f267fec0f7eb2b27f8c2e3052b3d03b09d36b47de4082ffb638ffb334ef0eee"
* }
*
* }
*/
async pubKey (rpcData) {
try {
// console.log('createUser rpcData: ', rpcData)
const address = rpcData.payload.params.address
const data = await this.bchjs.encryption.getPubKey(address)
// console.log(`data: ${JSON.stringify(data, null, 2)}`)
const retObj = {
success: true,
status: 200,
endpoint: 'pubkey',
pubkey: data
}
// retObj.status = 200
return retObj
} catch (err) {
console.error('Error in JSON RPC BCH pubKey()')
// throw err
let error = err
if (err.error && typeof err.error === 'string') {
error = new Error(err.error)
}
// Return an error response
return {
success: false,
status: 422,
message: error.message,
endpoint: 'pubkey'
}
}
}
}
module.exports = BCHRPC
+79 -9
View File
@@ -38,6 +38,11 @@ class JSONRPC {
this.aboutController = new AboutController()
this.bchController = new BCHController(localConfig)
// Cache to store IDs of processed JSON RPC commands. Used to prevent
// duplicate processing.
this.msgCache = []
this.MSG_CACHE_SIZE = 30
_this = this
}
@@ -46,23 +51,47 @@ class JSONRPC {
async router (str, from) {
try {
// console.log('router str: ', str)
// console.log('router from: ', from)
console.log('JSON RPC router recieved data from: ', from)
// Exit quietly if 'from' is not specified.
if (!from || typeof from !== 'string') {
// console.warn(
// 'Warning: Can not send JSON RPC response. Can not determine which peer this message came from.'
// )
return
wlogger.info(
'Warning: Can not send JSON RPC response. Can not determine which peer this message came from.'
)
return false
}
// Attempt to parse the incoming data as a JSON RPC string.
const parsedData = _this.jsonrpc.parse(str)
// console.log('parsedData: ', parsedData)
// wlogger.debug(`parsedData: ${JSON.stringify(parsedData, null, 2)}`)
// Exit quietly if the incoming string is an invalid JSON RPC string.
if (parsedData.type === 'invalid') {
return
wlogger.info('Rejecting invalid JSON RPC command.')
return false
}
// Check for duplicate entries with same 'id' value.
const alreadyProcessed = _this._checkIfAlreadyProcessed(parsedData)
if (alreadyProcessed) {
return false
} else {
// console.log(`parsedData: ${JSON.stringify(parsedData, null, 2)}`)
// This node will regularly ping known circuit relays with an /about
// JSON RPC call. These will be handled by ipfs-coord, but will percolate
// up to this library. Ignore these messages.
if (
parsedData.type.includes('success') &&
parsedData.payload.method === undefined
) {
return false
}
// Log the incoming JSON RPC command.
wlogger.info(
`JSON RPC received from ${from}, ID: ${parsedData.payload.id}, type: ${parsedData.type}, method: ${parsedData.payload.method}`
)
}
// Added the property "from" to the parsedData object;
@@ -100,8 +129,19 @@ class JSONRPC {
// Encrypt and publish the response to the originators private OrbitDB,
// if ipfs-coord has been initialized and the peers ID is registered.
if (_this.ipfsCoord.ipfs) {
await _this.ipfsCoord.ipfs.orbitdb.sendToDb(from, retStr)
// console.log('responding to JSON RPC command')
const thisNode = _this.ipfsCoord.thisNode
// console.log('thisNode: ', thisNode)
try {
await _this.ipfsCoord.useCases.peer.sendPrivateMessage(
from,
retStr,
thisNode
)
} catch (err) {
console.log('sendPrivateMessage() err: ', err)
}
// Return the response and originator. Useful for testing.
@@ -113,6 +153,36 @@ class JSONRPC {
}
}
// Checks the ID of the JSON RPC call, to see if the message has already been
// processed. Returns true if the ID exists in the cache of processed messages.
// If the ID is new, the function adds it to the cache and return false.
_checkIfAlreadyProcessed (data) {
try {
// console.log('data: ', data)
const id = data.payload.id
// Check if the hash is in the array of already processed message.
const alreadyProcessed = this.msgCache.includes(id)
// Update the msgCache if this is a new message.
if (!alreadyProcessed) {
// Add the hash to the array.
this.msgCache.push(id)
// If the array is at its max size, then remove the oldest element.
if (this.msgCache.length > this.MSG_CACHE_SIZE) {
this.msgCache.shift()
}
}
return alreadyProcessed
} catch (err) {
console.error('Error in _checkIfAlreadyProcessed: ', err)
return true
}
}
// The default JSON RPC response if the incoming command could not be routed.
defaultResponse () {
const errorObj = {
+228 -20
View File
@@ -29,20 +29,42 @@ class BCHRESTController {
}
/**
*
* @api {post} /bch/transactions Transactions
* @apiName Transactions
* @apiGroup REST BCH
* @apiDescription This endpoint wraps the bchjs.Electrumx.transactions([]) function.
*
* Given the 'addresses' property returns an array of objects
* with the following properties
*
* - success : - Petition status
* - transactions : [] - Transaction of the provided address
* - transactions: [] - Transaction details
* - height : - Reference to the blockchain size
* - tx_hash: "" - Transaction hash
* - address : "" - Address associated to the transactions
*
* Note: For a single address pass the 'addresses' of string type
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"] }' localhost:5001/bch/transactions
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
*
* success:true,
* data: <data>
* "success":true,
* "transactions":[
* {
* "transactions":[
* {
* "height":631219,
* "tx_hash":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f"
* }
* ],
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"
* }
* ]
* }
*
* @apiError UnprocessableEntity Missing required parameters
@@ -54,6 +76,7 @@ class BCHRESTController {
* "error": "Unprocessable Entity"
* }
*/
async transactions (ctx) {
try {
const addrs = ctx.request.body.addresses
@@ -71,7 +94,19 @@ class BCHRESTController {
* @api {post} /bch/balance Balance
* @apiName Balance
* @apiGroup REST BCH
* @apiDescription This endpoint returns the balance in BCH for an address.
* @apiDescription Returns the balance of an address or an array of addresses.
*
* Given the 'addresses' property returns an array of objects
* with the following properties
*
* - success : - Petition status
* - balances : [] - Balance of the provided addresses
* - balance : {} - Object with the balance types of an address
* - confirmed : - Confirmed balance
* - unconfirmed : - Unconfirmed Balance
* - address : "" - Address related to the balance
*
* Note: For a single address pass the 'addresses' of string type
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "addresses": ["bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"] }' localhost:5001/bch/balance
@@ -79,8 +114,16 @@ class BCHRESTController {
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* success:true,
* data: <data>
* "success":true,
* "balances":[
* {
* "balance":{
* "confirmed":1000,
* "unconfirmed":0
* },
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj"
* }
* ]
* }
*
* @apiError UnprocessableEntity Missing required parameters
@@ -110,17 +153,70 @@ class BCHRESTController {
* @apiName UTXOs
* @apiGroup REST BCH
* @apiDescription This endpoint returns UTXOs held at an address, hydrated
* with token information.
* with token information.
*
* Given an address, this endpoint will return an object with thre following
* properties:
*
* - address: "" - the address these UTXOs are associated with
* - bchUtxos: [] - UTXOs confirmed to be spendable as normal BCH
* - nullUtxo: [] - UTXOs that did not pass SLP validation. Should be ignored and
* not spent, to be safe.
* - slpUtxos: {} - UTXOs confirmed to be colored as valid SLP tokens
* - type1: {}
* - tokens: [] - SLP token Type 1 tokens.
* - mintBatons: [] - SLP token Type 1 mint batons.
* - nft: {}
* - tokens: [] - NFT tokens
* - groupTokens: [] - NFT Group tokens, used to create NFT tokens.
* - groupMintBatons: [] - Minting baton to create more NFT Group tokens.
*
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "address": "bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj" }' localhost:5001/bch/utxos
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* success:true,
* data: <data>
* }
* [
* {
* "address":"bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj",
* "bchUtxos":[
* {
* "height":631219,
* "tx_hash":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
* "tx_pos":0,
* "value":1000,
* "txid":"ae2daa01c8172545b5edd205ea438706bcb74e63d4084a26b9ff2a46d46dc97f",
* "vout":0,
* "isValid":false
* }
* ],
* "nullUtxos":[
*
* ],
* "slpUtxos":{
* "type1":{
* "mintBatons":[
*
* ],
* "tokens":[
*
* ]
* },
* "nft":{
* "groupMintBatons":[
*
* ],
* "groupTokens":[
*
* ],
* "tokens":[
*
* ]
* }
* }
* }
* ]
*
* @apiError UnprocessableEntity Missing required parameters
*
@@ -151,15 +247,14 @@ class BCHRESTController {
* @apiDescription Broadcast a transaction to the BCH network.
* The transaction should be encoded as a hexidecimal string.
*
* This endpoint will return a transaction id
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff0704ffff001d0104ffffffff0100f2052a0100000043410496b538e853519c726a2c91e61ec11600ae1390813a627c66fb8be7947be63c52da7589379515d4e0a604f8141781e62294721166bf621e73a82cbf2342c858eeac00000000" }' localhost:5001/bch/broadcast
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* success:true,
* data: <data>
* }
* "951299775f68a599b95239bfc385423f87a33e11747c299a22ef9dcf3d1557ec"
*
* @apiError UnprocessableEntity Missing required parameters
*
@@ -175,7 +270,7 @@ class BCHRESTController {
const hex = ctx.request.body.hex
const txid = await _this.bchjs.RawTransactions.sendRawTransaction(hex)
// console.log(`utxos: ${JSON.stringify(utxos, null, 2)}`)
// console.log(`txid: ${JSON.stringify(txid, null, 2)}`)
ctx.body = txid
} catch (err) {
@@ -188,16 +283,78 @@ class BCHRESTController {
* @apiName Transaction
* @apiGroup REST BCH
* @apiDescription Get data about a specific transaction.
* Given a transaction id this endpoint will return an object
* with the following properties
*
* - txid: "" - Transaction ID
* - hash: "" - Transaction hash
* - version: - Version number
* - size: - Transaction size
* - locktime: -
* - vin: [] - Transaction inputs
* - vout: [] - Transaction outputs
* - hex: "" - hexadecimal script
* - blockhash: "" - Reference to the block register
* - confirmations : "" - Transaction confirmations
* - time: - Execution time
* - blocktime: - Execution time
* - isValidSLPTx: - Determines if the transaction was under SLP
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "txid": "01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b" }' localhost:5001/bch/transaction
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* success:true,
* data: <data>
* }
* {
* "txid":"01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b",
* "hash":"01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b",
* "version":1,
* "size":272,
* "locktime":0,
* "vin":[
* {
* "txid":"4deef6de4b973706cd6e8fc8105a41a84be349e4e9717225ee5e7c63538e95e8",
* "vout":1,
* "scriptSig":{
* "asm":"3045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f2496[ALL|FORKID] 0467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3",
* "hex":"483045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f249641410467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3"
* },
* "sequence":4294967295,
* "address":"bitcoincash:qqrxa0h9jqnc7v4wmj9ysetsp3y7w9l36u8gnnjulq",
* "value":0.00001824
* }
* ],
* "vout":[
* {
* "value":0,
* "n":0,
* "scriptPubKey":{
* "asm":"OP_RETURN -385055325 46226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a",
* "hex":"6a045d7af3962046226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a",
* "type":"nulldata"
* }
* },
* {
* "value":0.0000155,
* "n":1,
* "scriptPubKey":{
* "asm":"OP_DUP OP_HASH160 066ebee590278f32aedc8a4865700c49e717f1d7 OP_EQUALVERIFY OP_CHECKSIG",
* "hex":"76a914066ebee590278f32aedc8a4865700c49e717f1d788ac",
* "reqSigs":1,
* "type":"pubkeyhash",
* "addresses":[
* "bitcoincash:qqrxa0h9jqnc7v4wmj9ysetsp3y7w9l36u8gnnjulq"
* ]
* }
* }
* ],
* "hex":"0100000001e8958e53637c5eee257271e9e449e34ba8415a10c88f6ecd0637974bdef6ee4d010000008b483045022100fce6ef975fa7ec66e0ce0c51d839fd8f56510897252c0b238e7265974bc7c07202200d1d1429154e6775eecdc2829965650bc3ca714a86088d705bd58f8c034f249641410467ff2df20f28bc62ad188525868f41d461f7dab3c1e500314cdb5218e5637bfd0f9c02eb5b3f383f698d28ff13547eaf05dd9216130861dd0216824e9d7337e3ffffffff020000000000000000276a045d7af3962046226800369048b83cea897639bb39273c8e4b883bd8c2a435bbe7a237cc433a0e060000000000001976a914066ebee590278f32aedc8a4865700c49e717f1d788ac00000000",
* "blockhash":"0000000000000000008e8d83cba6d45a9314bc2ef4538d4e0577c6bed8593536",
* "confirmations":97988,
* "time":1568338904,
* "blocktime":1568338904,
* "isValidSLPTx":false
* }
*
* @apiError UnprocessableEntity Missing required parameters
*
@@ -221,6 +378,57 @@ class BCHRESTController {
}
}
/**
* @api {post} /bch/pubkey PubKey
* @apiName PubKey
* @apiGroup REST BCH
* @apiDescription Get the public key from an address
*
* Given the 'address' param returns an object
* with the following properties
*
* - success : - Request status
* - publicKey : '' - Public key of the provided address
*
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X GET localhost:5001/bch/pubkey/bitcoincash:qpnty9t0w93fez04h7yzevujpv8pun204qv6yfuahk
*
* @apiSuccessExample {json} Success-Response:
* HTTP/1.1 200 OK
* {
* "success":true,
* "publicKey": '033f267fec0f7eb2b27f8c2e3052b3d03b09d36b47de4082ffb638ffb334ef0eee'
* }
*
* @apiError UnprocessableEntity Missing required parameters
*
* @apiErrorExample {json} Error-Response:
* HTTP/1.1 422 Unprocessable Entity
* {
* "status": 422,
* "error": "Unprocessable Entity"
* }
*/
async pubKey (ctx) {
try {
const address = ctx.params.address
console.log(`pubKey address: ${address}`)
const pubkey = await _this.bchjs.encryption.getPubKey(address)
// console.log(`pubkey: ${JSON.stringify(pubkey, null, 2)}`)
ctx.body = pubkey
} catch (err) {
console.log(err)
let error = err
if (err.error && typeof err.error === 'string') {
error = new Error(err.error)
}
_this.handleError(ctx, error)
}
}
// DRY error handler
handleError (ctx, err) {
// If an HTTP status is specified by the buisiness logic, use that.
+1
View File
@@ -50,6 +50,7 @@ class BCHRouter {
this.router.post('/utxos', this.bchRESTController.utxos)
this.router.post('/broadcast', this.bchRESTController.broadcast)
this.router.post('/transaction', this.bchRESTController.transaction)
this.router.get('/pubkey/:address', this.bchRESTController.pubKey)
// Attach the Controller routes to the Koa app.
app.use(this.router.routes())
+4 -11
View File
@@ -3,7 +3,7 @@
functions are called by the /user REST API endpoints.
*/
// const UserModel = require('../adapters/localdb/models/users')
const UserEntity = require('../entities/user')
const { wlogger } = require('../adapters/wlogger')
class UserLib {
@@ -17,6 +17,7 @@ class UserLib {
}
// Encapsulate dependencies
this.UserEntity = new UserEntity()
this.UserModel = this.adapters.localdb.Users
}
@@ -24,17 +25,9 @@ class UserLib {
async createUser (userObj) {
try {
// Input Validation
if (!userObj.email || typeof userObj.email !== 'string') {
throw new Error("Property 'email' must be a string!")
}
if (!userObj.password || typeof userObj.password !== 'string') {
throw new Error("Property 'password' must be a string!")
}
if (!userObj.name || typeof userObj.name !== 'string') {
throw new Error("Property 'name' must be a string!")
}
const user = new this.UserModel(userObj)
const userEntity = this.UserEntity.validate(userObj)
const user = new this.UserModel(userEntity)
// Enforce default value of 'user'
user.type = 'user'
+5 -2
View File
@@ -10,7 +10,7 @@ const axios = require('axios').default
// Local support libraries
const config = require('../../../config')
const app = require('../../../bin/server')
const Server = require('../../../bin/server')
const testUtils = require('../../utils/test-utils')
const AdminLib = require('../../../src/adapters/admin')
const adminLib = new AdminLib()
@@ -23,11 +23,14 @@ const LOCALHOST = `http://localhost:${config.port}`
describe('Auth', () => {
before(async () => {
try {
process.env.E2ETEST = 'true'
const app = new Server()
// This should be the first instruction. It starts the REST API server.
await app.startServer()
// Stop the IPFS node for the rest of the e2e tests.
// await app.controllers.adapters.ipfs.stop()
// Delete all previous users in the database.
await testUtils.deleteAllUsers()
+2 -1
View File
@@ -12,7 +12,8 @@ const LOCALHOST = `http://localhost:${config.port}`
const context = {}
const UserController = require('../../../src/controllers/rest-api/users/controller')
const adapters = require('../../../src/adapters')
const Adapters = require('../../../src/adapters')
const adapters = new Adapters()
const UseCases = require('../../../src/use-cases/')
let uut
let sandbox
+11
View File
@@ -0,0 +1,11 @@
# Consumer Simulation E2E Test
The files in this directory simulates a consumer of web services, using JSON RPC over IPFS. It starts a new IPFS node that connects to the ipfs-bch-wallet-service and exercises each JSON RPC endpoint.
## Instructions
Execute these steps in order to run the test:
1. Run your local copy of ipfs-bch-wallet-service service provider.
2. Update the [test-data.json](./test-data.json) file with the IPFS ID of the ipfs-bch-wallet-service.
3. In another terminal, run the client simulation with `node client.e2e.js`
+33
View File
@@ -0,0 +1,33 @@
/*
An end-to-end (e2e) test simulating a client connecting over IPFS and
that exercises each JSON RPC endpoint.
*/
const TestUtils = require('./lib/test-utils')
const testUtils = new TestUtils()
const testData = require('./test-data.json')
async function startTest () {
try {
console.log('E2E TEST: Starting consumer E2E tests...')
await testUtils.startIpfs()
await testUtils.connectToUut(testData.uutAddr, testData.uutId)
await testUtils.testBalance(testData.uutId)
await testUtils.testTransaction(testData.uutId)
await testUtils.testTransactions(testData.uutId)
await testUtils.testUtxos(testData.uutId)
console.log('E2E TEST: Tests completed successfully!')
process.exit()
} catch (err) {
console.error('Error in startTest(): ', err)
}
}
startTest()
+295
View File
@@ -0,0 +1,295 @@
/*
A class library of test utility functions.
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
const IpfsCoord = require('ipfs-coord')
const IPFS = require('@chris.troutner/ipfs')
const EventEmitter = require('events')
const { v4: uid } = require('uuid')
const jsonrpc = require('jsonrpc-lite')
let _this
class TestUtils {
constructor (localConfig = {}) {
// Encapsulate dependencies.
this.bchjs = new BCHJS()
this.eventEmitter = new EventEmitter()
this.uid = uid
this.jsonrpc = jsonrpc
_this = this
}
// This handler function recieves data from other ipfs-coord peers, like
// the ipfs-bch-wallet-service that we're testing.
// It emits the data as an 'rpcData' event. The tests will listen for this
// event.
rpcHandler (inData) {
try {
// console.log('Data recieved by rpcHandler: ', inData)
const jsonData = JSON.parse(inData)
_this.eventEmitter.emit('rpcData', jsonData)
} catch (err) {
console.error('Error in rpcHandler: ', err)
// Do not throw an error. This is a top-level function.
}
}
// Send the RPC command to the service, wait a period of time for a response.
// Timeout if a response is not recieved.
async sendRPC (ipfsId, cmdStr) {
try {
// Send the RPC command to the server/service.
// await this.ipfsCoord.ipfs.orbitdb.sendToDb(ipfsId, cmdStr)
await this.ipfsCoord.useCases.peer.sendPrivateMessage(
ipfsId,
cmdStr,
this.ipfsCoord.thisNode
)
let retData
// This event is triggered when the response comes back.
this.eventEmitter.on('rpcData', (inData) => {
retData = inData
})
// Used for calculating the timeout.
const start = new Date()
let now = start
let timeDiff = 0
// Wait for the response from the server. Exit once the response is
// recieved, or a timeout occurs.
do {
await this.bchjs.Util.sleep(1000)
now = new Date()
timeDiff = now.getTime() - start.getTime()
// console.log('timeDiff: ', timeDiff)
} while (
// Exit once the RPC data comes back, or if a period of time passes.
!retData || // eslint-disable-line no-unmodified-loop-condition
timeDiff > 10000
)
return retData
} catch (err) {
console.error('Error in sendRPC')
throw err
}
}
async startIpfs () {
try {
// Start the IPFS node.
this.ipfs = await IPFS.create()
await this.ipfs.config.profiles.apply('server')
// Start ipfs-coord.
this.ipfsCoord = new IpfsCoord({
ipfs: this.ipfs,
type: 'node.js',
// type: 'browser',
bchjs: this.bchjs,
privateLog: this.rpcHandler, // Default to console.log
isCircuitRelay: false,
apiInfo: 'none',
announceJsonLd: announceJsonLd
})
await this.ipfsCoord.start()
// Wait to let ipfs-coord connect to subnet peers.
await this.bchjs.Util.sleep(30000)
} catch (err) {
console.error('Error in startIpfs().')
throw err
}
}
// Connect to the unit under test (uut)
async connectToUut (addr, ipfsId) {
try {
try {
await this.ipfs.swarm.connect(addr)
console.log(`E2E TEST: Connected to IPFS node ${addr}`)
} catch (err) {
throw new Error('Could not connect to UUT IPFS node.')
}
// console.log(
// 'ipfs-coord peer info: ',
// this.ipfsCoord.ipfs.peers.state.peers[ipfsId]
// )
const peers = this.ipfsCoord.thisNode.peerList
// console.log('peers: ', peers)
// console.log('Target peer in peerList? ', peers.includes(ipfsId))
// if (!this.ipfsCoord.ipfs.peers.state.peers[ipfsId]) {
if (!peers.includes(ipfsId)) {
throw new Error('Could not find UUT in ipfs-coord list of peers.')
}
} catch (err) {
console.log(err)
console.error('Error in connectToUut()')
console.log(
'Is the service running? Did you update the test-data.json file?'
)
process.exit()
}
}
// Get the balance for a BCH address over JSON RPC.
async testBalance (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'balance',
addresses: ['bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj']
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Balance command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result: ', result)
if (result.result.value.success && result.result.value.balances) {
console.log('E2E TEST: balance test passed.')
return true
} else {
console.log('E2E TEST: balance test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testBalance()')
throw err
}
}
// Get the info a on transaction over JSON RPC.
async testTransaction (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'transaction',
txid: '01517ff1587fa5ffe6f5eb91c99cf3f2d22330cd7ee847e928ce90ca95bf781b'
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Transaction command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result: ', result)
if (result.result.value.status && result.result.value.confirmations) {
console.log('E2E TEST: transaction test passed.')
return true
} else {
console.log('E2E TEST: transaction test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testTransaction()')
throw err
}
}
// Get the info a on transaction over JSON RPC.
async testTransactions (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'transactions',
addresses: ['bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj']
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Transactions command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result: ', result)
if (
result.result.value.status &&
Array.isArray(result.result.value.transactions)
) {
console.log('E2E TEST: transactions test passed.')
return true
} else {
console.log('E2E TEST: transactions test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testTransactions()')
throw err
}
}
// Get the utxos for a BCH address over JSON RPC.
async testUtxos (ipfsId) {
try {
// Generate the JSON RPC command
const id = uid()
const cmd = jsonrpc.request(id, 'bch', {
endpoint: 'utxos',
address: 'bitcoincash:qrl2nlsaayk6ekxn80pq0ks32dya8xfclyktem2mqj'
})
const cmdStr = JSON.stringify(cmd)
// console.log(`Publishing message to ${ipfsId}`)
console.log('E2E TEST: Sending Utxos command...')
const result = await this.sendRPC(ipfsId, cmdStr)
// console.log('result', result.result.value)
const bchUtxos = result.result.value[0].bchUtxos
const slpUtxos = result.result.value[0].slpUtxos
if (result.result.value && bchUtxos && slpUtxos) {
console.log('E2E TEST: utxos test passed.')
return true
} else {
console.log('E2E TEST: utxos test failed.')
this.failTest()
}
} catch (err) {
console.error('Error in testUtxos()')
throw err
}
}
failTest () {
console.log('Exiting test program.')
process.exit()
}
}
const announceJsonLd = {
'@context': 'https://schema.org/',
'@type': 'WebAPI',
name: 'e2e-test-client',
description: 'A test client runing e2e tests on ipfs-bch-wallet-service.',
documentation: 'https://ipfs-bch-wallet-service.fullstack.cash/',
provider: {
'@type': 'Organization',
name: 'Permissionless Software Foundation',
url: 'https://PSFoundation.cash'
}
}
module.exports = TestUtils
+4
View File
@@ -0,0 +1,4 @@
{
"uutAddr": "/ip4/127.0.0.1/tcp/5268/p2p/QmdBGB8S6sEr19gaAxJYjhRbz5ZmMiH5a1JyyMmaxcRKnY",
"uutId": "QmdBGB8S6sEr19gaAxJYjhRbz5ZmMiH5a1JyyMmaxcRKnY"
}
@@ -18,8 +18,8 @@ describe('#FullStackJWT', () => {
const localConfig = {
authServer: 'someserver',
apiServer: 'someserver',
login: 'somelogin',
password: 'somepassword'
fullstackLogin: 'somelogin',
fullstackPassword: 'somepassword'
}
uut = new FullStackJWT(localConfig)
})
@@ -81,7 +81,7 @@ describe('#FullStackJWT', () => {
const localConfig = {
authServer: 'someserver',
apiServer: 'someserver',
login: 'somelogin'
fullstackLogin: 'somelogin'
}
uut = new FullStackJWT(localConfig)
+24 -2
View File
@@ -62,10 +62,24 @@ describe('#IPFS', () => {
assert.equal(result, true)
})
it('should get the public IP address if this node is a Circuit Relay', async () => {
// Mock dependencies.
uut.IpfsCoord = IPFSCoordMock
sandbox.stub(uut.publicIp, 'v4').returns('123')
// Force Circuit Relay
uut.config.isCircuitRelay = true
const result = await uut.start()
// console.log('result: ', result)
assert.equal(result, true)
})
})
describe('#attachRPCRouter', () => {
it('should attached a router output', async () => {
it('should attach a router output', async () => {
// Mock dependencies
uut.ipfsCoord = {
privateLog: {},
@@ -73,6 +87,11 @@ describe('#IPFS', () => {
orbitdb: {
privateLog: {}
}
},
adapters: {
orbit: {
privateLog: () => {}
}
}
}
@@ -81,8 +100,11 @@ describe('#IPFS', () => {
uut.attachRPCRouter(router)
})
it('should throw an error if ipfs-coord has not been instantiated', () => {
it('should catch and throw an error', () => {
try {
// Force an error
delete uut.ipfsCoord.adapters
const router = console.log
uut.attachRPCRouter(router)
+22 -1
View File
@@ -4,6 +4,7 @@
const assert = require('chai').assert
const sinon = require('sinon')
const BCHJS = require('@psf/bch-js')
const IPFSLib = require('../../../src/adapters/ipfs')
const IPFSMock = require('../mocks/ipfs-mock')
@@ -12,9 +13,11 @@ const IPFSCoordMock = require('../mocks/ipfs-coord-mock')
describe('#IPFS-adapter-index', () => {
let uut
let sandbox
let bchjs
beforeEach(() => {
uut = new IPFSLib()
bchjs = new BCHJS()
uut = new IPFSLib({ bchjs })
sandbox = sinon.createSandbox()
})
@@ -59,5 +62,23 @@ describe('#IPFS-adapter-index', () => {
assert.include(err.message, 'test error')
}
})
it('should handle lock-file errors', async () => {
try {
// Force an error
sandbox
.stub(uut.ipfsAdapter, 'start')
.rejects(new Error('Lock already being held'))
// Prevent process from exiting
sandbox.stub(uut.process, 'exit').returns()
await uut.start({ bchjs })
assert.fail('Unexpected code path.')
} catch (err) {
assert.include(err.message, 'Lock already being held')
}
})
})
})
+34
View File
@@ -47,4 +47,38 @@ describe('#IPFS-adapter', () => {
}
})
})
describe('#stop', () => {
it('should stop the IPFS node', async () => {
// Mock dependencies
uut.ipfs = {
stop: () => {}
}
const result = await uut.stop()
assert.equal(result, true)
})
})
describe('#rmBlocksDir', () => {
it('should delete the /blocks directory', () => {
const result = uut.rmBlocksDir()
assert.equal(result, true)
})
it('should catch and throw an error', () => {
try {
// Force an error
sandbox.stub(uut.fs, 'rmdirSync').throws(new Error('test error'))
uut.rmBlocksDir()
assert.fail('Unexpected code path')
} catch (err) {
assert.equal(err.message, 'test error')
}
})
})
})
+20 -10
View File
@@ -1,30 +1,40 @@
// const assert = require('chai').assert
const {
notifyRotation,
outputToConsole
} = require('../../../src/adapters/wlogger')
const assert = require('chai').assert
const { Wlogger } = require('../../../src/adapters/wlogger')
const sinon = require('sinon')
// let uut
let uut
let sandbox
describe('#wlogger.js', () => {
describe('#wlogger', () => {
beforeEach(() => {
sandbox = sinon.createSandbox()
})
afterEach(() => sandbox.restore())
afterEach(() => {
sandbox.restore()
uut = new Wlogger()
})
describe('#constructor', () => {
it('should create a new wlogger instance', () => {
uut = new Wlogger()
// console.log('uut: ', uut)
assert.property(uut, 'transport')
})
})
describe('#notifyRotation', () => {
it('should notify of a log rotation', () => {
notifyRotation()
uut.notifyRotation()
})
})
describe('#envronment', () => {
it('should write to console in non-test environment', () => {
outputToConsole()
uut.outputToConsole()
})
})
})
+23 -13
View File
@@ -6,26 +6,30 @@
const assert = require('chai').assert
const sinon = require('sinon')
const adapters = require('../../../src/adapters')
const { attachControllers } = require('../../../src/controllers')
const Controllers = require('../../../src/controllers')
describe('#Controllers', () => {
// let uut
let uut
let sandbox
beforeEach(() => {
sandbox = sinon.createSandbox()
uut = new Controllers()
})
afterEach(() => sandbox.restore())
describe('#attachControllers', () => {
it('should attach the controllers', async () => {
// mock IPFS
sandbox.stub(adapters.ipfs, 'start').resolves({})
sandbox.stub(adapters.fullStackJwt, 'getJWT').resolves({})
sandbox.stub(adapters.fullStackJwt, 'instanceBchjs').resolves({})
adapters.ipfs.ipfsCoordAdapter = {
// mock dependencies
// sandbox.stub(adapters.fullStackJwt, 'getJWT').resolves({})
// sandbox.stub(adapters.fullStackJwt, 'instanceBchjs').resolves({})
// sandbox.stub(adapters.ipfs, 'start').resolves({})
// adapters.ipfs.ipfsCoordAdapter = {
sandbox.stub(uut.adapters, 'start').resolves({})
uut.adapters.ipfs.ipfsCoordAdapter = {
attachRPCRouter: () => {}
}
@@ -33,17 +37,23 @@ describe('#Controllers', () => {
use: () => {}
}
await attachControllers(app)
await uut.attachControllers(app)
assert.isOk(true, 'Not throwing an error is a success')
})
it('should catch and throw errors', async () => {
try {
// Force an error
sandbox
.stub(adapters.fullStackJwt, 'getJWT')
.rejects(new Error('test error'))
sandbox.stub(uut.adapters, 'start').rejects(new Error('test error'))
await attachControllers()
const app = {
use: () => {}
}
await uut.attachControllers(app)
assert.fail('Unexpected code path')
} catch (err) {
// console.log('err.message: ', err.message)
assert.include(err.message, 'test error')
@@ -155,6 +155,24 @@ describe('#BCHRPC', () => {
assert.equal(result, true)
})
it('should route to the pubkey method', async () => {
// Mock dependencies
sandbox.stub(uut, 'pubKey').resolves(true)
// Generate the parsed data that the main router would pass to this
// endpoint.
const id = uid()
const rpcCall = jsonrpc.request(id, 'bch', {
endpoint: 'pubkey'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
rpcData.from = 'Origin request'
const result = await uut.bchRouter(rpcData)
assert.equal(result, true)
})
it('should return 500 status on routing issue', async () => {
// Mock dependencies
@@ -420,4 +438,81 @@ describe('#BCHRPC', () => {
assert.equal(response.endpoint, 'transaction')
})
})
describe('#pubKey', () => {
it('should return data from bchjs', async () => {
// Mock dependencies
const mock = { success: true, publicKey: '033f267fec0f7eb2b27f8c2e3052b3d03b09d36b47de4082ffb638ffb334ef0eee' }
sandbox.stub(uut.bchjs.encryption, 'getPubKey').resolves(mock)
// Generate the parsed data that the main router would pass to this
// endpoint.
const id = uid()
const rpcCall = jsonrpc.request(id, 'bch', {
endpoint: 'pubkey',
address: 'bitcoincash:qpnty9t0w93fez04h7yzevujpv8pun204qv6yfuahk'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.pubKey(rpcData)
assert.equal(response.success, true)
assert.equal(response.status, 200)
assert.property(response, 'pubkey')
const pubKey = response.pubkey
assert.property(pubKey, 'publicKey')
assert.equal(pubKey.publicKey, mock.publicKey)
})
it('should throw an error if public key is not found', async () => {
// Force an error
sandbox
.stub(uut.bchjs.encryption, 'getPubKey')
.rejects({ success: false, error: 'No transaction history.' })
// Generate the parsed data that the main router would pass to this
// endpoint.
const id = uid()
const rpcCall = jsonrpc.request(id, 'bch', {
endpoint: 'pubkey',
address: 'bitcoincash:qrnx7l2e6yejgswehf54gs30ljzumnhqdqgn8yscr2'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.pubKey(rpcData)
// console.log('response: ', response)
assert.equal(response.success, false)
assert.equal(response.status, 422)
assert.equal(response.message, 'No transaction history.')
assert.equal(response.endpoint, 'pubkey')
})
it('should return an error for invalid input', async () => {
// Force an error
sandbox
.stub(uut.bchjs.encryption, 'getPubKey')
.rejects(new Error('Invalid data'))
// Generate the parsed data that the main router would pass to this
// endpoint.
const id = uid()
const rpcCall = jsonrpc.request(id, 'bch', {
endpoint: 'pubkey',
address: 'bitcoincash'
})
const jsonStr = JSON.stringify(rpcCall, null, 2)
const rpcData = jsonrpc.parse(jsonStr)
const response = await uut.pubKey(rpcData)
// console.log('response: ', response)
assert.equal(response.success, false)
assert.equal(response.status, 422)
assert.equal(response.message, 'Invalid data')
assert.equal(response.endpoint, 'pubkey')
})
})
})
@@ -207,5 +207,120 @@ describe('#JSON RPC', () => {
assert.equal(obj.result.method, 'bch')
assert.equal(obj.id, id)
})
it('should exit quietly for duplicate RPC message', async () => {
const id = uid()
const json = jsonrpc.request(id, 'unknownMethod', {})
const str = JSON.stringify(json)
// Call router once.
await uut.router(str, 'peerA')
// Call the router again with the same input.
const result = await uut.router(str, 'peerA')
assert.equal(result, false)
})
it('should ignore metric queries from ipfs-coord', async () => {
const id = uid()
const json = jsonrpc.request(id, 'unknownMethod', {})
const str = JSON.stringify(json)
// Force the RPC type to be 'success', to indicate an RPC that was
// processed internal to ipfs-coord.
sandbox.stub(uut.jsonrpc, 'parse').returns({
payload: {},
type: 'success'
})
// Call the router again with the same input.
const result = await uut.router(str, 'peerA')
assert.equal(result, false)
})
it('should report errors when trying to send messages to peers', async () => {
const id = uid()
const json = jsonrpc.request(id, 'unknownMethod', {})
const str = JSON.stringify(json)
// Force issue with sendPrivateMessage()
sandbox
.stub(uut.ipfsCoord.useCases.peer, 'sendPrivateMessage')
.rejects('test error')
// Call the router again with the same input.
const result = await uut.router(str, 'peerA')
// console.log('result: ', result)
assert.property(result, 'from')
assert.property(result, 'retStr')
})
})
describe('#_checkIfAlreadyProcessed', () => {
it('should return false the first time an RPC command is seen', () => {
const data = {
payload: {
jsonrpc: '2.0',
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
method: 'unknownMethod',
params: {}
},
type: 'request'
}
const result = uut._checkIfAlreadyProcessed(data)
assert.equal(result, false)
})
it('should return true the second time an RPC command is seen', () => {
const data = {
payload: {
jsonrpc: '2.0',
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
method: 'unknownMethod',
params: {}
},
type: 'request'
}
// First call.
uut._checkIfAlreadyProcessed(data)
// Second call.
const result = uut._checkIfAlreadyProcessed(data)
assert.equal(result, true)
})
it('should push out old data from the cache for new data', () => {
const data = {
payload: {
jsonrpc: '2.0',
id: '6c515f3c-cf8a-42ec-870e-e416edd4923f',
method: 'unknownMethod',
params: {}
},
type: 'request'
}
uut.MSG_CACHE_SIZE = 0
const result = uut._checkIfAlreadyProcessed(data)
assert.equal(result, false)
})
it('should return true on error', () => {
const result = uut._checkIfAlreadyProcessed()
assert.equal(result, true)
})
})
})
@@ -233,6 +233,56 @@ describe('#BCH-REST-Router', () => {
})
})
describe('#pubKey', () => {
it('should return data from bchjs', async () => {
// Mock dependencies
const mock = { success: true, publicKey: '033f267fec0f7eb2b27f8c2e3052b3d03b09d36b47de4082ffb638ffb334ef0eee' }
sandbox.stub(uut.bchjs.encryption, 'getPubKey').resolves(mock)
ctx.params = {
address: 'bitcoincash:qpnty9t0w93fez04h7yzevujpv8pun204qv6yfuahk'
}
await uut.pubKey(ctx)
// console.log('ctx.body: ', ctx.body)
assert.equal(ctx.body.success, true)
assert.equal(ctx.body.publicKey, mock.publicKey)
})
it('should throw an error if public key is not found', async () => {
try {
// Force an error
sandbox
.stub(uut.bchjs.encryption, 'getPubKey')
.rejects({ success: false, error: 'No transaction history.' })
ctx.params = {
address: 'bitcoincash:qrnx7l2e6yejgswehf54gs30ljzumnhqdqgn8yscr2'
}
await uut.pubKey(ctx)
} catch (err) {
// console.log('err: ', err)
assert.include(err.message, 'No transaction history')
}
})
it('should catch and throw an error', async () => {
try {
// Force an error
sandbox
.stub(uut.bchjs.encryption, 'getPubKey')
.rejects(new Error('test error'))
ctx.params = {
address: 'bitcoincash:qpnty9t0w93fez04h7yzevujpv8pun204qv6yfuahk'
}
await uut.pubKey(ctx)
} catch (err) {
// console.log('err: ', err)
assert.include(err.message, 'test error')
}
})
})
describe('#handleError', () => {
it('should pass an error message', () => {
try {
+10 -1
View File
@@ -7,7 +7,13 @@ const ipfs = {
ipfs: {}
},
ipfsCoordAdapter: {
ipfsCoord: {}
ipfsCoord: {
useCases: {
peer: {
sendPrivateMessage: () => {}
}
}
}
}
}
@@ -60,6 +66,9 @@ const bchjs = {
},
RawTransactions: {
sendRawTransaction: () => {}
},
encryption: {
getPubKey: () => {}
}
}
+1 -1
View File
@@ -57,7 +57,7 @@ describe('#users-use-case', () => {
} catch (err) {
// console.log(err)
// assert.equal(err.status, 422)
assert.include(err.message, 'Cannot read property')
assert.include(err.message, "Property 'email' must be a string!")
}
})