Compare commits

..
243 Commits
Author SHA1 Message Date
Chris Troutner aaee25389f Merge pull request #51 from Permissionless-Software-Foundation/ct-unstable
fix(docker): Updating docker image. Bumping to v2
2022-10-01 13:12:48 -07:00
Chris Troutner ce83ddcadf fix(docker): Updating docker image. Bumping to v2 2022-10-01 13:10:21 -07:00
Chris Troutner 1b961905e0 Merge pull request #50 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream. Converting from CommonJS to ES6
2022-10-01 13:02:35 -07:00
Chris Troutner e757bd0fe0 Updating p2wdb image 2022-10-01 13:00:22 -07:00
Chris Troutner 3da78ce46b fix(ES6): Synced with upstream, converted from CommonJS to ES6 2022-10-01 12:16:14 -07:00
Chris Troutner c9d1d79e11 linting 2022-10-01 11:40:41 -07:00
Chris Troutner ce118069eb Syncing with upstream. Fixing merge conflicts, converting to ES6 2022-10-01 11:40:26 -07:00
Chris Troutner f8dce21d95 fix(dex-ui): Updating docker image for rpi 2022-09-27 17:56:12 -07:00
Chris Troutner e8104a8a12 Merge pull request #49 from Permissionless-Software-Foundation/ct-unstable
fix(production): Updating docker container
2022-09-19 19:34:35 -07:00
Chris Troutner 2c43793bf2 fix(production): Updating docker container 2022-09-19 19:28:21 -07:00
Chris Troutner c13a5d1593 Merge pull request #101 from Permissionless-Software-Foundation/ct-unstable
Increased test coverage to 100%
2022-09-17 15:24:26 -07:00
Chris Troutner 6d7b3db370 Using latest version of ipfs-coord-esm 2022-09-17 15:19:37 -07:00
Chris Troutner 33d06e99e8 fix(tests): got ipfs-coord lib to 100% test coverage 2022-09-17 14:51:57 -07:00
Chris Troutner 3203e56a4d fix(tests): Added user e2e tests back in 2022-09-17 14:47:17 -07:00
Chris Troutner ff47f1b356 fix(test): Got use cases to 100% test coverage 2022-09-17 14:23:46 -07:00
Chris Troutner d9377ea78b fix(tests): Increased coverage of REST API validators 2022-09-17 14:18:16 -07:00
Chris Troutner d266bcc54b fix(deps): Updating dependencies 2022-09-17 10:10:39 -07:00
Chris Troutner a033fb1042 fix(tests): Replacing nyc with c8, for test coverage of ESM 2022-09-16 08:38:53 -07:00
Chris Troutner b0eda392a6 Merge pull request #48 from Permissionless-Software-Foundation/ct-unstable
Better error handling for tokens without mutable data
2022-09-14 06:29:01 -07:00
Chris Troutner f81d6853fc Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-09-14 06:26:20 -07:00
Chris Troutner 02a889385d fix(offer): Better error handling for tokens without mutable data 2022-09-14 06:26:12 -07:00
Chris Troutner f17b21bee8 fixing typo 2022-09-13 15:37:57 -07:00
Chris Troutner 78b9e4fcb1 fix(rpi-docker): Updating docker images 2022-09-13 15:34:50 -07:00
Chris Troutner eb1bee1b61 fix(docker): Updating docker images 2022-09-13 15:10:03 -07:00
Chris Troutner 611c2d1631 Merge pull request #47 from Permissionless-Software-Foundation/ct-unstable
feat(nsfw): Detecting tokens marked NSFW in the mutable data
2022-09-13 14:17:12 -07:00
Chris Troutner cb9f5af62e feat(nsfw): Detecting tokens marked NSFW in the mutable data 2022-09-13 13:40:01 -07:00
Chris Troutner 2fca908c97 Merge pull request #46 from Permissionless-Software-Foundation/ct-unstable
feat(NSFW): Adding hook for handling NSFW flags from users
2022-09-13 11:53:03 -07:00
Chris Troutner 3aba1e061b feat(NSFW): Adding hook for handling NSFW flags from users 2022-09-13 11:50:14 -07:00
Chris Troutner c398942c95 temp mod to docker-compose.yml 2022-09-12 13:36:24 -07:00
Chris Troutner c2bffd8c4e Merge pull request #45 from Permissionless-Software-Foundation/ct-unstable
feat(pagination): Adding filtering and pagination
2022-09-12 10:40:32 -07:00
Chris Troutner ac97831721 feat(pagination): Adding filtering and pagination 2022-09-12 10:34:45 -07:00
Chris Troutner 02eab8686c Merge pull request #44 from Permissionless-Software-Foundation/ct-unstable
feat(categorizeToken): New field to Offer model, for UI display
2022-09-11 14:45:15 -07:00
Chris Troutner 1c1169dd93 linting 2022-09-11 14:41:56 -07:00
Chris Troutner 0896adffbb feat(categorizeToken): New field to Offer model, for UI display 2022-09-11 14:36:40 -07:00
Chris Troutner 56e0f7e8df fix(p2wdb): Updating p2wdb to v2.2.3 2022-09-11 11:55:07 -07:00
Chris Troutner 34841f53db Merge pull request #43 from Permissionless-Software-Foundation/ct-unstable
fix(offer): Fixing bugs related to making and taking offers
2022-09-11 10:54:53 -07:00
Chris Troutner c27209cceb fix(offer): Fixing bugs related to making and taking offers 2022-09-11 10:51:32 -07:00
Chris Troutner 5a0fc31c7a Merge pull request #42 from Permissionless-Software-Foundation/ct-unstable
Updating depenencies. Fixing issue with garbage collection.
2022-09-11 09:24:28 -07:00
Chris Troutner 4701f245b9 fix(garbage collection): Fixing issue with garbage collection 2022-09-11 09:21:50 -07:00
Chris Troutner daa06a57ed fix(deps): Updated dependencies and updated tests 2022-09-11 07:39:58 -07:00
Chris Troutner b3157a04ed Merge pull request #41 from Permissionless-Software-Foundation/ct-unstable
Updating docker images
2022-09-11 07:06:35 -07:00
Chris Troutner 3753db46f6 fixing merge conflict 2022-09-11 07:02:27 -07:00
Chris Troutner b924449d02 Updating docker images 2022-09-11 06:57:54 -07:00
Chris Troutner 569dcbd576 Merge pull request #100 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to new version to fix bugs
2022-09-08 09:32:01 -07:00
Chris Troutner b0a2d73540 fix(ipfs-coord): Updating to new version to fix bugs 2022-09-08 09:30:21 -07:00
Chris Troutner 0d4c8cd56e Merge pull request #99 from Permissionless-Software-Foundation/ct-unstable
Breaking change: Converted from CommonJS to ESM
2022-09-08 09:00:19 -07:00
Chris Troutner b37dae60d1 fix(ESM): Converted from CommonJS to ESM 2022-09-08 08:59:03 -07:00
Chris Troutner 448b028bb4 fixed linting issue 2022-09-08 08:58:39 -07:00
Chris Troutner dd8d992b8a Merge pull request #40 from Permissionless-Software-Foundation/ct-unstable
fix(garbage collection): Replacing web2 with web3 calls to validate UTXO
2022-09-04 15:49:43 -07:00
Chris Troutner 4ed657ae28 fix(production): Creating new v1.9.6 docker images for amd64 and arm64 2022-09-04 15:35:50 -07:00
Chris Troutner e14633db79 Updating bch-message-lib 2022-09-04 14:38:11 -07:00
Chris Troutner 6a4e749218 fix(garbage collection): Replacing web2 with web3 calls to validate UTXO 2022-09-04 14:27:51 -07:00
Chris Troutner 7a5036e3aa Merge pull request #39 from Permissionless-Software-Foundation/ct-unstable
fix(production): Created new RPi images
2022-08-28 16:20:45 -07:00
Chris Troutner cca10452c0 fix(production): Created new RPi images 2022-08-28 16:17:33 -07:00
Chris Troutner 309ea0774d Merge pull request #38 from Permissionless-Software-Foundation/ct-unstable
New Docker images
2022-08-28 10:15:13 -07:00
Chris Troutner c2b68a0787 fix(production): Using new docker images 2022-08-28 10:12:36 -07:00
Chris Troutner 2bb4cd7cae fix(production): Updating Dockerfiles 2022-08-28 09:23:47 -07:00
Chris Troutner 9ca581e998 Merge pull request #37 from Permissionless-Software-Foundation/ct-unstable
Syncing with upstream ipfs-service-provider
2022-08-27 15:43:49 -07:00
Chris Troutner 02adbd5634 fixing merge conflicts 2022-08-27 15:40:59 -07:00
Chris Troutner da637df44a Merge pull request #98 from Permissionless-Software-Foundation/ct-unstable
Using bandwidth limited IPFS Docker container
2022-08-27 13:43:51 -07:00
Chris Troutner 9315e6f166 fix(production): Updating docker image 2022-08-27 13:39:06 -07:00
Chris Troutner 7e965e8415 Adding comments 2022-08-27 12:59:20 -07:00
Chris Troutner a5916c95f9 fix(production): Using bandwidth limited IPFS Docker container 2022-08-27 12:58:41 -07:00
Chris Troutner 708f97d107 More dependency updates 2022-08-27 12:55:24 -07:00
Chris Troutner 637738bfb9 Updated npm deps 2022-08-27 12:53:43 -07:00
Chris Troutner d8e82c5ad2 fix(ipfs-coord): Updating to v8.0.5 2022-08-27 12:52:16 -07:00
Chris Troutner b23acd3cdc Merge pull request #97 from Permissionless-Software-Foundation/ct-unstable
fix(production): Switching to Docker Image
2022-07-25 19:17:27 -07:00
Chris Troutner c71fda38ff fix(production): Switching to Docker Image 2022-07-25 19:14:44 -07:00
Chris Troutner f99f49d840 Merge pull request #96 from Permissionless-Software-Foundation/ct-unstable
Configuring ports with env vars
2022-07-25 17:58:40 -07:00
Chris Troutner 2edd924c57 fix(production): Adding 4003 websocket port 2022-07-25 17:56:02 -07:00
Chris Troutner 689c8fd8d9 fix(ipfs): Using config to set ports 2022-07-25 17:40:05 -07:00
Chris Troutner ffd6c452c9 Merge pull request #95 from Permissionless-Software-Foundation/ct-unstable
fix(mocks): Another update to IPFS test mocks
2022-07-24 08:15:55 -07:00
Chris Troutner fc8e160874 fix(mocks): Another update to IPFS test mocks 2022-07-24 08:14:27 -07:00
Chris Troutner d2f83307e6 Merge pull request #94 from Permissionless-Software-Foundation/ct-unstable
fix(mocks): Improvement to adapter mocks used in tests
2022-07-24 08:08:13 -07:00
Chris Troutner 1a09fcd26f fix(mocks): Improvement to adapter mocks used in tests 2022-07-24 08:06:32 -07:00
Chris Troutner db54a067f4 Merge pull request #36 from Permissionless-Software-Foundation/ct-unstable
Updating ipfs-coord & docker images
2022-07-08 16:09:45 -07:00
Chris Troutner 9fcee20498 Switching bch-dex app ID for RPi 2022-07-08 16:07:33 -07:00
Chris Troutner 0a04ee61ef Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-07-08 15:45:18 -07:00
Chris Troutner 7cae06dd65 fix(rpi): Updating containers for RPi 2022-07-08 15:44:30 -07:00
Chris Troutner 96064ac9a7 fix(production): New docker image 2022-07-08 12:48:31 -07:00
Chris Troutner 3690b749fe fix(package.json): Synced with upstream 2022-07-08 09:55:22 -07:00
Chris Troutner e2c5821dbe Merge pull request #93 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating bootstrap nodes
2022-07-07 15:56:42 -07:00
Chris Troutner 9967d5145b fix(ipfs-coord): Updating bootstrap nodes 2022-07-07 15:55:33 -07:00
Chris Troutner 9d16291855 Merge pull request #92 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v8
2022-07-07 15:17:09 -07:00
Chris Troutner 1518d1a12b fix(ipfs-coord): Updating to v8 2022-07-07 15:16:03 -07:00
Chris Troutner 6dbf284876 Merge pull request #35 from Permissionless-Software-Foundation/ct-unstable
fix(webhook): Ensuring startup waits for webhook to be established
2022-07-07 13:46:12 -07:00
Chris Troutner d1e96505c8 fix(order): Handling bad order data 2022-07-07 13:45:01 -07:00
Chris Troutner 1e80a3159e fix(webhook): Ensuring startup waits for webhook to be established 2022-07-07 13:37:16 -07:00
Chris Troutner d3df9546a7 fix(tests): Speeding up e2e tests 2022-07-06 20:56:01 -07:00
Chris Troutner 3422f3146e Merge pull request #34 from Permissionless-Software-Foundation/ct-unstable
feat(sweep-nfts.js): Added script to reclaim NFTs
2022-07-06 18:42:00 -07:00
Chris Troutner 5c4dc21d3e Making e2e tests a little faster 2022-07-06 18:39:45 -07:00
Chris Troutner b74f460a9a feat(sweep-nfts.js): Added script to reclaim NFTs 2022-07-06 18:30:33 -07:00
Chris Troutner 6585ceacc7 Merge pull request #33 from Permissionless-Software-Foundation/ct-unstable
fix(offer): Changing stale threshold from 7 days to 8 weeks
2022-07-06 12:24:01 -07:00
Chris Troutner 942dbedd44 fix(offer): Changing stale threshold from 7 days to 8 weeks 2022-07-06 12:22:15 -07:00
Chris Troutner 825ede0760 Minor text chagne 2022-07-02 13:41:25 -07:00
Chris Troutner 5e4540bd84 Updating docker image 2022-06-29 17:37:37 -07:00
Chris Troutner a3b21d7547 Merge pull request #32 from Permissionless-Software-Foundation/ct-unstable
Using P2WDB v3 + synced with ipfs-service-provider
2022-06-29 17:31:36 -07:00
Chris Troutner 87ece9d6bb fix(production): Improvements to docker files 2022-06-29 17:29:23 -07:00
Chris Troutner 125330f5b0 Fixing broken test 2022-06-29 16:56:12 -07:00
Chris Troutner 6b3fc78fc9 fix(p2wdb): Working with v3 P2WDB 2022-06-29 16:50:36 -07:00
Chris Troutner 3d7d4a57d2 Fixing merge conflicts 2022-06-29 16:29:28 -07:00
Chris Troutner abf07005eb fix(deps): Updating dependencies 2022-06-29 16:03:09 -07:00
Chris Troutner b68a143071 Merge pull request #91 from Permissionless-Software-Foundation/ct-unstable
Added hooks for async startup
2022-06-27 11:33:50 -07:00
Chris Troutner 5c25ebeeca Renaming mock log 2022-06-27 11:32:25 -07:00
Chris Troutner 3b17ba8e8b fix(logapi): Fixing issues with unit tests 2022-06-27 11:29:27 -07:00
Chris Troutner 434a4d7bd6 Refactoring failing unit tests 2022-06-27 10:25:19 -07:00
Chris Troutner dd36ebc7a0 Got test coverage back to 100% 2022-06-27 10:15:35 -07:00
Chris Troutner f117fe15df fix(startup): Added hooks for async startup 2022-06-27 10:09:08 -07:00
Chris Troutner 0333f77f5a Fixing broken link in README 2022-06-20 07:30:10 -07:00
Chris Troutner 3c908d1a4d Merge pull request #90 from Permissionless-Software-Foundation/ct-unstable
Increasing test coverage to 100%
2022-06-20 07:22:10 -07:00
Chris Troutner eb46a4c130 fix(tests): Got to 100% test coverage for entire repo 2022-06-20 07:19:36 -07:00
Chris Troutner d0efdcfa07 fix(ipfs-coord): Increased unit test coverage to 100% 2022-06-20 07:01:43 -07:00
Chris Troutner 62a7fcb16d fix(tests): Got bin/server.js unit test coverage to 100% 2022-06-19 20:21:40 -07:00
Chris Troutner d8addd5b27 Trying to build unit tests for bin/server 2022-06-19 20:00:25 -07:00
Chris Troutner bf6f1cf62d Merge pull request #89 from Permissionless-Software-Foundation/ct-unstable
Updating dependencies
2022-06-19 13:25:07 -07:00
Chris Troutner b7df7c47a5 Updated ipfs 2022-06-19 13:23:52 -07:00
Chris Troutner ae260db4af Updated some dependencies 2022-06-19 13:19:31 -07:00
Chris Troutner 778098ca12 fix(ipfs-coord): Updating to v7.1.19 2022-05-28 09:29:31 -07:00
Chris Troutner 0c4bb9c4a1 fix(ipfs-coord): Updating to v7.1.18 2022-05-28 09:09:44 -07:00
Chris Troutner 9cb975656d Merge pull request #88 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v7.1.17
2022-05-28 08:00:57 -07:00
Chris Troutner 4f6564423e fix(ipfs-coord): Updating to v7.1.17 2022-05-28 07:59:47 -07:00
Chris Troutner 54e7e74ae5 Merge pull request #87 from Permissionless-Software-Foundation/ct-unstable
Subscribing to chat channel at startup
2022-05-26 09:14:50 -07:00
Chris Troutner 324c372119 fix(startup): Subscribing to chat pubsub channel at startup 2022-05-26 09:12:15 -07:00
Chris Troutner da62f1bbe3 linting 2022-05-26 08:24:45 -07:00
Chris Troutner 129047fe88 fix(startup): Announcing config settings at startup 2022-05-26 08:24:30 -07:00
Chris Troutner 3f2a12f6ec Merge pull request #31 from Permissionless-Software-Foundation/ct-unstable
fix(rpi): updating UI docker container
2022-05-17 07:10:37 -07:00
Chris Troutner c1b687efd1 fix(rpi): updating UI docker container 2022-05-17 07:07:43 -07:00
Chris Troutner fb182ced58 Merge pull request #86 from Permissionless-Software-Foundation/ct-unstable
Updating docker-compose file
2022-05-16 12:33:03 -07:00
Chris Troutner bec7c11e46 Updating README 2022-05-16 12:31:53 -07:00
Chris Troutner fb10e10226 fix(production): Updating docker images 2022-05-16 12:30:58 -07:00
Chris Troutner 5b37e47747 Merge pull request #85 from Permissionless-Software-Foundation/ct-unstable
fix(bch-js): Updating to v6.4.1
2022-05-16 12:15:47 -07:00
Chris Troutner a3cea782ba fix(bch-js): Updating to v6.4.1 2022-05-16 12:14:20 -07:00
Chris Troutner 14ffdae194 Merge pull request #84 from Permissionless-Software-Foundation/dh-test-coverage
feat(coverage): Got ipfs-coord.js to 100% test coverage
2022-05-16 12:09:18 -07:00
Chris Troutner faf5a83eb6 Merge pull request #30 from Permissionless-Software-Foundation/ct-unstable
Several small tweeks
2022-05-10 10:54:53 -07:00
Chris Troutner 92a35b220f fix(RPi): Updating docker images 2022-05-09 17:38:48 -07:00
Chris Troutner 58e934eeab fix(docker): Uploaded new PC images 2022-05-09 12:04:05 -07:00
Chris Troutner d5de76729d fix(production): Switching p2wdb to debug level 1 2022-05-09 09:35:31 -07:00
Chris Troutner 805cac97d9 fix(startup): Listing web3 server at startup 2022-05-09 09:33:39 -07:00
Chris Troutner 91fa460158 fix(production scripts): Improvement to sweep-wallet.js 2022-05-09 09:26:17 -07:00
Chris Troutner 2d6055b537 Merge pull request #29 from Permissionless-Software-Foundation/ct-unstable
Updating docker images
2022-05-08 16:19:42 -07:00
Chris Troutner 72e6a37ed1 fix(docker): Updating image files 2022-05-08 16:17:20 -07:00
Chris Troutner 9d18a24c7e Restoring 20s time delay on bch-dex startup 2022-05-08 13:45:01 -07:00
Chris Troutner feacf6e571 Merge pull request #28 from Permissionless-Software-Foundation/ct-unstable
feat(NFT): Adding support for NFTs
2022-05-08 13:24:14 -07:00
Chris Troutner c51f7cdf3a feat(NFT): Adding support for NFTs 2022-05-08 10:45:21 -07:00
Chris Troutner 07fbe8c654 Merge pull request #26 from Permissionless-Software-Foundation/ct-unstable
Updating docker images
2022-05-07 13:13:25 -07:00
Chris Troutner a65ec7494f fix(production): Updating docker images of PC 2022-05-07 13:10:18 -07:00
Chris Troutner 59fca7903f Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-05-07 12:12:59 -07:00
Chris Troutner f8948f12fa fix(rpi): Updating to v1.6.7 of bch-dex Docker container 2022-05-07 12:12:30 -07:00
Chris Troutner b79163cdf7 Merge pull request #25 from Permissionless-Software-Foundation/ct-unstable
Improved startup and error handling
2022-05-07 11:41:52 -07:00
Chris Troutner 2d537994ef Increasing startup time to 20 seconds 2022-05-04 17:00:46 -07:00
Chris Troutner 2ae963ee62 fix(removeStaleOrders): handling network errors 2022-05-04 16:07:24 -07:00
Chris Troutner f5cd59eb12 Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-05-04 16:06:35 -07:00
Chris Troutner d4f9e128b3 fix(removeStaleOrders): Handling network errors 2022-05-04 16:05:58 -07:00
Chris Troutner 3c322ecbd0 Merge pull request #24 from Permissionless-Software-Foundation/ct-unstable
Several minor fixes and enhancements
2022-05-04 06:12:49 -07:00
Chris Troutner 56944176fa fix(sweep-wallet): Got sweeping script working better 2022-05-04 06:03:08 -07:00
Chris Troutner 5f9cdc3f2e fix(startup): Adding 5 sec delay to bch-dex startup 2022-05-03 17:09:19 -07:00
Chris Troutner c20938f9f7 Fixing bug 2022-05-03 16:35:17 -07:00
Chris Troutner 5be3c92a29 fix(order): Better error handling in use-case 2022-05-03 15:33:33 -07:00
Chris Troutner 1476500c61 fix(rpi): Updating docker image to v1.6.6 2022-05-03 15:25:37 -07:00
Chris Troutner 519980eb99 Adding extra error handling to removeStaleOffers() 2022-05-03 14:23:13 -07:00
Chris Troutner 1e4b71aacd fix(production): Switching to newly name UI repo 2022-05-03 07:03:13 -07:00
Chris Troutner 2c1c009b64 fix(removeStaleOffers): Better error handling 2022-05-02 13:31:22 -07:00
Chris Troutner 09cbfd00e8 Merge pull request #23 from Permissionless-Software-Foundation/ct-unstable
Fixing bugs. Updating docker images
2022-05-02 10:54:09 -07:00
Chris Troutner 2c21d79740 fix(rpi): Updating docker images 2022-05-02 10:43:47 -07:00
Chris Troutner 15eb871b1f fix(production): Updating to v1.6.4 of docker images 2022-05-02 09:43:39 -07:00
Chris Troutner f4e80017d6 Merge pull request #22 from Permissionless-Software-Foundation/ct-unstable
fix(orders): Fixing bug with creating orders
2022-05-02 08:32:25 -07:00
Chris Troutner e27b9da2ee fix(orders): Fixing bug with creating orders 2022-05-02 08:29:51 -07:00
Chris Troutner adb210cd60 Merge pull request #21 from Permissionless-Software-Foundation/ct-unstable
Using RPi docker images
2022-05-01 14:57:41 -07:00
Chris Troutner ff7697baf6 fix(RPi): using docker images 2022-05-01 14:39:28 -07:00
Chris Troutner d65c3701cd fix(README): Updating README 2022-05-01 13:13:59 -07:00
Chris Troutner 4303efdb43 fix(README): Updating readme 2022-05-01 13:03:31 -07:00
Chris Troutner 87b1b7f9ca fix(rpi): Updating docker files 2022-05-01 12:45:07 -07:00
Chris Troutner 3dddf21986 Merge pull request #20 from Permissionless-Software-Foundation/ct-unstable
Improvements to production containers
2022-05-01 10:30:45 -07:00
Chris Troutner 238bee3d92 fix(production): Mounting swarm.key with IPFS container 2022-05-01 10:27:54 -07:00
Chris Troutner 04f77c883a fix(production): Mounting wallet file instead of including it in Docker image 2022-05-01 09:27:52 -07:00
Chris Troutner cddf141ce4 Merge branch 'ct-unstable' 2022-05-01 06:14:50 -07:00
Chris Troutner 628d8c01f8 Doing force install in rpi docker container 2022-05-01 06:10:31 -07:00
Chris Troutner 0ed4a03314 Merge pull request #19 from Permissionless-Software-Foundation/ct-unstable
Ct unstable
2022-04-30 19:34:42 -07:00
Chris Troutner 5eb8464469 fix(README): Adding link to setup video 2022-04-30 16:49:30 -07:00
Chris Troutner d1dc4dd198 Updating README 2022-04-15 06:42:20 -07:00
Chris Troutner 1ba3633fac Updating README 2022-04-15 06:37:06 -07:00
Chris Troutner 69dd2c2627 Updating README 2022-04-15 06:35:19 -07:00
Chris Troutner 0a838b7fd7 Adding install force 2022-04-14 17:11:54 -07:00
Chris Troutner de9ede9859 fix(ui): Adding new UI to RPi docker 2022-04-12 15:40:22 -07:00
Chris Troutner 8273ae29d0 Switching UI to bch-dex-ui2 2022-04-12 13:24:51 -07:00
Chris Troutner 4d733f0995 Merge pull request #18 from Permissionless-Software-Foundation/ct-unstable
Better Offer UX
2022-04-01 20:39:22 -07:00
Chris Troutner f812580169 fix(production): Added sweep-wallet.js 2022-04-01 20:20:16 -07:00
Chris Troutner ec8dc91d36 feat(offers): Deleting offers older than 7 days 2022-04-01 20:10:38 -07:00
Chris Troutner 03214fd7df feat(offer): Deleting Offer model after broadcasting Counter Offer. 2022-04-01 19:50:33 -07:00
Chris Troutner 9aae6da4a7 feat(offer/list): Returning Offers sorted by newest first 2022-04-01 19:05:31 -07:00
Chris Troutner 6e7ab40dea Merge pull request #17 from Permissionless-Software-Foundation/ct-unstable
fix(webhook): Fixing default webhook URL
2022-03-31 18:51:04 -07:00
Chris Troutner 3b45e3c2c4 fix(domain): Detecting domain for working with back-end 2022-03-31 18:48:05 -07:00
Chris Troutner 756002dd8c fix(webhook): Fixing default webhook URL 2022-03-31 18:04:13 -07:00
Chris Troutner 86da41b6c8 Making instruction steps a numbered list 2022-03-29 11:07:44 -07:00
Chris Troutner c2838b6117 Updating install step 2022-03-29 11:03:11 -07:00
Chris Troutner af33de3f9a Adding links to videos 2022-03-29 09:27:29 -07:00
Chris Troutner 50d7cf137f Merge pull request #16 from Permissionless-Software-Foundation/ct-unstable
fix(createOrder()): Updating wallet UTXOs before checking for funds
2022-03-27 19:42:42 -07:00
Chris Troutner dad9803d69 fix(createOrder()): Updating wallet UTXOs before checking for funds 2022-03-27 19:17:52 -07:00
Chris Troutner a235e57302 Merge pull request #15 from Permissionless-Software-Foundation/ct-unstable
fix(production): Auto-restarting bch-dex Docker container
2022-03-27 13:59:03 -07:00
Chris Troutner bb2f20b322 fix(production): Auto-restarting bch-dex Docker container 2022-03-27 13:47:05 -07:00
Chris Troutner 1f91bb05dd Editing README 2022-03-27 11:49:55 -07:00
Chris Troutner 5e044f3d10 Editing README 2022-03-27 11:42:16 -07:00
Chris Troutner a94f2d32b5 fix(README): Adding installation instructions to README 2022-03-27 11:30:54 -07:00
Chris Troutner 4b66305392 fix(production scripts): Added create-wallet.js to scripts folder 2022-03-27 11:00:29 -07:00
Chris Troutner e23f8c2019 Merge pull request #14 from Permissionless-Software-Foundation/ct-unstable
Got Docker containers working
2022-03-27 10:18:11 -07:00
Chris Troutner f9e76a3dfb fix(createOffer()): Prevening duplicate Offers from being created 2022-03-26 20:31:34 -07:00
Chris Troutner 470fa95b74 temporary commenting out failing test 2022-03-26 19:38:23 -07:00
Chris Troutner f2b8ccaa3a fix(acceptCounterOffer()): Appropriately ignoring Counter Offers 2022-03-26 19:35:15 -07:00
Chris Troutner fa834e9114 Fixing typo in webhook 2022-03-26 19:27:32 -07:00
Chris Troutner c45b512fc6 fix(wallet): Throwing error when wallet file not passed in correctly 2022-03-26 19:20:06 -07:00
Chris Troutner e0d1aa24d4 More wallet debugging 2022-03-26 18:56:18 -07:00
Chris Troutner a4faecf56e debugging wallet file issue 2022-03-26 18:36:49 -07:00
Chris Troutner 95e66efc2f Adding more debugging 2022-03-26 18:07:41 -07:00
Chris Troutner 881a882175 fix(bug): Handling counter offer bug 2022-03-26 15:35:26 -07:00
Chris Troutner 80945039b0 Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-03-26 15:24:20 -07:00
Chris Troutner e470b26771 fix(docker): Updating to node.js v16 in all containers 2022-03-26 15:24:12 -07:00
Chris Troutner eb458f1e9f Merge branch 'ct-unstable' of https://github.com/Permissionless-Software-Foundation/bch-dex into ct-unstable 2022-03-26 15:23:15 -07:00
Chris Troutner 21f4bc2f4c Fixing webhook url 2022-03-26 15:23:11 -07:00
Chris Troutner 7e2e28834a Debugging ensureFunds() 2022-03-26 15:15:08 -07:00
Chris Troutner 07551bb693 fix(production): Minor fixes 2022-03-26 13:32:52 -07:00
Chris Troutner 207f00ba81 Merge pull request #13 from Permissionless-Software-Foundation/ct-rpi
feat(rpi): Created customized docker files for RPi4
2022-03-26 12:11:44 -07:00
Chris Troutner 3ccdf40a9c Merge branch 'master' into ct-rpi 2022-03-26 12:06:58 -07:00
Chris Troutner 0b940c797c feat(rpi): Created customized docker files for RPi4 2022-03-26 12:05:11 -07:00
Chris Troutner 04f6dbee54 Merge pull request #12 from gitter-badger/gitter-badge
Add a Gitter chat badge to README.md
2022-03-26 11:59:57 -07:00
The Gitter Badger 632320960f Add Gitter badge 2022-03-26 16:14:13 +00:00
Chris Troutner b26160b748 Merge pull request #11 from Permissionless-Software-Foundation/ct-unstable
Got production docker containers running
2022-03-26 08:40:50 -07:00
Chris Troutner 04f45eea6a Adding production/script dir 2022-03-26 08:35:16 -07:00
Chris Troutner 9096db1614 Removing old docker containers 2022-03-26 08:27:53 -07:00
Chris Troutner 369415bf8d fix(production): Got docker containers working 2022-03-26 08:25:43 -07:00
Chris Troutner 7cb536d312 Making webhook target an env var 2022-03-26 07:32:00 -07:00
Daniel Gonzalez 7e3ce1564d feat(coverage): Got ipfs-coord.js to 100% test coverage 2022-03-25 22:12:11 -04:00
Chris Troutner 592ea60892 Ported docker containers from avax-dex 2022-03-25 18:45:32 -07:00
Chris Troutner d14270c5b0 Updating package-lock.json 2022-03-25 17:59:56 -07:00
Chris Troutner 8154dd96f9 Merge pull request #83 from Permissionless-Software-Foundation/ct-unstable
fix(deps): Updating bch-js
2022-03-20 07:48:42 -07:00
Chris Troutner e37223cc88 fix(deps): Updating bch-js 2022-03-20 07:46:08 -07:00
Chris Troutner 5002ef2b90 Merge pull request #82 from Permissionless-Software-Foundation/dh-test-coverage-ipfsjs
feat(test): Got ipfs.js to 100% test coverage
2022-03-18 11:27:32 -07:00
Chris Troutner 5d95109ad4 more linting 2022-03-18 11:24:15 -07:00
Chris Troutner 13b3150f62 minor linting 2022-03-18 11:24:04 -07:00
Daniel Gonzalez b3a4a7c1ab feat(test): Got ipfs.js to 100% test coverage 2022-03-15 18:58:55 -04:00
Chris Troutner 733e8fd405 Merge pull request #81 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v7.1.6
2022-03-10 09:29:32 -08:00
Chris Troutner baee72c1c6 fix(ipfs-coord): Updating to v7.1.6 2022-03-10 09:27:13 -08:00
Chris Troutner 11618a796f Merge pull request #80 from Permissionless-Software-Foundation/ct-unstable
fix(ipfs-coord): Updating to v7.1.5
2022-03-10 08:35:21 -08:00
Chris Troutner 025ae20704 fix(ipfs-coord): Updating to v7.1.5 2022-03-10 08:33:53 -08:00
171 changed files with 10324 additions and 20172 deletions
+63 -22
View File
@@ -1,34 +1,75 @@
# bch-dex
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![Join the chat at https://gitter.im/Permissionless-Software-Foundation/psf-dex-dev](https://badges.gitter.im/Permissionless-Software-Foundation/psf-dex-dev.svg)](https://gitter.im/Permissionless-Software-Foundation/psf-dex-dev?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
This is a prototype web service that monitors the [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service) for trading signals, to trade BCH and SLP tokens. It's inspired by the [SWaP Prototype](https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md).
`bch-dex` is a decentralized exchange for permissionless trading of [SLP tokens](https://github.com/simpleledger/slp-specifications/blob/master/slp-token-type-1.md) and [NFTs](https://github.com/simpleledger/slp-specifications/blob/master/slp-nft-1.md). Trading fees are incredibly small, compared to other DEX platforms. The software is based entirely on open protocols and open source software. It's not a '.com' website that you visit, but software you run on your own computer, in the confort of your own home. So long as you have an internet connection and the technical knowledge to run this software, no one can stop you from trading tokens. `bch-dex` software is maintained by the [Permissionless Software Foundation](https://psfoundation.cash/).
This repository was forked from [ipfs-torlist-service](https://github.com/Permissionless-Software-Foundation/ipfs-torlist-service).
- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video)
## Development Notes
This is a prototype web service that monitors the [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service) for trading signals, to trade BCH and SLP tokens. It's inspired by the [SWaP Protocol](https://github.com/vinarmani/swap-protocol/blob/master/swap-protocol-spec.md).
This repository contains the back end code. The user interface is contained in the [bch-dex-ui](https://github.com/Permissionless-Software-Foundation/bch-dex-ui) repository.
**Warning**: This repository is under active development. Things will be constantly changing and breaking.
### Road Map:
## Media
- [High-level Overview of bch-dex](https://youtu.be/LVX8CLi4sHw) (Video)
- [Developer walk-through for installing and hacking on bch-dex](https://youtu.be/T5XI43-SWJo) (Video)
- This video is out of date. Follow the instructions below.
- Phase 1: MVP (single user)
- Move tokens or BCH for sale to temporary address.
- Accept input from user:
- Submit Signal message to P2WDB for new buy/sell order.
- Check UTXO status before submitting Payment message.
- React to webhook when new Offers come in.
- Add and track new Offers in MongoDB.
- Process Payment signals:
- Checking transaction for compatibility
- Broadcast/close trades managed by this app.
- Phase 2: Build single-user web app
- _Make_ buy or sell orders.
- Browse Offers on the market.
- _Take_ buy or sell orders.
- Phase 3: Multi-user
- Configure REST API as an IPFS Service that can offer services to multiple users.
- Update web app to display and select available SWaP services over IPFS.
## Participate
This is an open source project, and we encourage other JavaScript developers to participate in its creation and maintenance. We have two chat rooms for the community:
- [Telegram Channel](https://t.me/psf_dex_dev)
- [Gitter Channel](https://gitter.im/Permissionless-Software-Foundation/psf-dex-dev)
## Installation
Running the DEX requires composition of these different software packages:
- bch-dex - This repository is the back end software that tracks trade data on the network, generates [Offers and Counter Offers](https://github.com/Permissionless-Software-Foundation/bch-dex/tree/ct-unstable/dev-docs#definitions), and finalizes trades by accepting Counter Offers.
- [bch-dex-ui](https://github.com/Permissionless-Software-Foundation/bch-dex-ui) is a [Gatsby](https://www.gatsbyjs.com/) web app and user interface (UI) for bch-dex.
- [P2WDB](https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service) is a censorship-resistant database used to communicate trade data between peers running bch-dex.
- [IPFS](https://ipfs.io/) is a censorship-resistant network for communicating data over the internet.
- [MongoDB](https://www.mongodb.com/) is a database used by both P2WDB and bch-dex to store and manage local data.
The above software is orchestrated using [Docker](https://www.docker.com/) and Docker Compose. The target operating system is Ubuntu 20+, and the target hardware is amd64 (normal desktop PCs) and the arm64 (Raspberry Pi 4). Trying to operate this software on other operating systems or hardware is possible, but not supported.
The Raspberry Pi 4 is the primary hardware target, because this software functions best when it is always running. The Pi 4 makes a great appliance for monitoring trade signals and finalizing trades.
Instructions for setting up Node.js, Docker, and Docker Compose can be found in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd). Walk-through videos can also be found on the [PSF Videos page](https://psfoundation.cash/video/).
Here are the steps involved in setting up bch-dex:
1. Follow the direction in [this Gist](https://gist.github.com/christroutner/a39f656850dc022b60f25c9663dd1cdd) to install Node.js, Docker, and Docker Compose.
1. Clone the repository with `git clone https://github.com/Permissionless-Software-Foundation/bch-dex` and enter it with `cd bch-dex`.
1. Install dependencies by running `npm install`
1. Create a wallet:
- `cd production/scripts`
- `node create-wallet.js`
1. Change directory to the `production/docker` or `production/rpi-docker` folder depending on your hardware target.
1. Pull the Docker images down from Docker Hub: `docker-compose pull`
1. Start the Docker containers with `docker-compose up -d`
1. Wait for the P2WDB to sync and populate bch-dex with trade data. You can monitor it with `docker logs --tail 20 -f p2wdb`.
1. Open a web browser and navigate the `http://localhost:4500`. You'll be able to see new Offers as they come in and are detected by bch-dex.
1. To take the other side of the trade, click the `Take` button in the UI.
1. You can add the 12-word mnemonic from the `wallet.json` file to the the web wallet, which will mirror your wallet in the UI, and allow you to perform basic wallet functions (send and receive BCH and tokens).
## Blockchain Infrastructure
The P2WDB and bch-dex containers requires a 'Global Back End' (as described in [CashStack.info](https://cashstack.info)) in order to connect to the blockchain. By default, the Docker containers connect to [free-bch.fullstack.cash](https://free-bch.fullstack.cash/). Several community-provided Global Back End servers are provided and can be [viewed here](https://gist.github.com/christroutner/63c5513782181f8b8ea3eb89f7cadeb6). The back end can be changed by setting the `CONSUMER_URL` environment variable in the `docker-compose.yml` file.
### Applying Software Updates
As this is an active project, software updates will happen frequently. To apply a software update, perform these steps.
1. Enter the `docker` or `rpi-docker` folder, depending on your hardware target.
1. Bring down the Docker containers with `docker-compose down`.
1. Pull in the software updates with `git pull`
1. Update dependencies with `npm install`
1. Pull new Docker images with `docker-compose pull`
1. Clean up disk space by deleting old Docker images with `./cleanup-images.sh`
1. Start the Docker containers with `docker-compose up -d`
Sometimes it may be necessary to delete the databases before applying a software update. This can be done by stopping the Docker containers and deleting the `production/data` directory. When the Docker containers are restarted, they will recreate that directory. The P2WDB will re-sync and bch-dex will be populated with fresh trade data.
## License
+78 -58
View File
@@ -8,55 +8,59 @@
*/
// npm libraries
const Koa = require('koa')
const bodyParser = require('koa-bodyparser')
const convert = require('koa-convert')
const logger = require('koa-logger')
const mongoose = require('mongoose')
const session = require('koa-generic-session')
const passport = require('koa-passport')
const mount = require('koa-mount')
const serve = require('koa-static')
const cors = require('kcors')
import Koa from 'koa'
import bodyParser from 'koa-bodyparser'
import convert from 'koa-convert'
import logger from 'koa-logger'
import mongoose from 'mongoose'
import session from 'koa-generic-session'
import passport from 'koa-passport'
import mount from 'koa-mount'
import serve from 'koa-static'
import cors from 'kcors'
// Local libraries
const config = require('../config') // this first.
const AdminLib = require('../src/adapters/admin')
// const adminLib = new AdminLib()
import config from '../config/index.js' // this first.
const WebHookLib = require('../src/adapters/webhook')
const webhookLib = new WebHookLib()
// const JSONRPC = require('../src/rpc')
// const rpc = new JSONRPC()
const errorMiddleware = require('../src/controllers/rest-api/middleware/error')
// const { wlogger } = require('../src/adapters/wlogger')
import AdminLib from '../src/adapters/admin.js'
import errorMiddleware from '../src/controllers/rest-api/middleware/error.js'
// import wlogger from '../src/adapters/wlogger.js'
import Controllers from '../src/controllers/index.js'
import { applyPassportMods } from '../config/passport.js'
class Server {
constructor () {
// Encapsulate dependencies
this.adminLib = new AdminLib()
this.controllers = new Controllers()
this.mongoose = mongoose
this.config = config
this.process = process
}
async startServer () {
try {
// Create a Koa instance.
const app = new Koa()
app.keys = [config.session]
app.keys = [this.config.session]
// Connect to the Mongo Database.
mongoose.Promise = global.Promise
mongoose.set('useCreateIndex', true) // Stop deprecation warning.
this.mongoose.Promise = global.Promise
this.mongoose.set('useCreateIndex', true) // Stop deprecation warning.
console.log(
`Connecting to MongoDB with this connection string: ${config.database}`
`Connecting to MongoDB with this connection string: ${this.config.database}`
)
await mongoose.connect(config.database, {
await this.mongoose.connect(this.config.database, {
useUnifiedTopology: true,
useNewUrlParser: true
})
console.log(`Starting environment: ${config.env}`)
console.log(`Debug level: ${config.debugLevel}`)
console.log(`Starting environment: ${this.config.env}`)
console.log(`Debug level: ${this.config.debugLevel}\n`)
console.log(`Using this web3 CashStack service: ${this.config.consumerUrl}`)
console.log('Alternative web services listed here: https://gist.github.com/christroutner/63c5513782181f8b8ea3eb89f7cadeb6')
console.log('This app is built on top of the CashStack. Find out more: https://CashStack.info\n')
// MIDDLEWARE START
@@ -72,7 +76,8 @@ class Server {
app.use(mount('/logs', serve(`${process.cwd()}/config/logs`)))
// User Authentication
require('../config/passport')
// require('../config/passport')
applyPassportMods(passport)
app.use(passport.initialize())
app.use(passport.session())
@@ -81,33 +86,42 @@ class Server {
// Dev Note: This line must come BEFORE controllers.attachRESTControllers()
app.use(cors({ origin: '*' }))
// Attach REST API and JSON RPC controllers to the app.
const Controllers = require('../src/controllers')
const controllers = new Controllers()
await controllers.attachRESTControllers(app)
// Wait for any adapters to initialize.
await this.controllers.initAdapters()
app.controllers = controllers
// Wait for any use-libraries to initialize.
await this.controllers.initUseCases()
// Attach REST API and JSON RPC controllers to the app.
await this.controllers.attachRESTControllers(app)
app.controllers = this.controllers
// MIDDLEWARE END
// 7/7/22 CT: This code paragraph can be deleted
// Delay startup to give the P2WDB time to start first, so that it accepts the webook call
// if (this.config.env !== 'test') {
// await this.sleep(20000)
// }
// Create webhook
try {
try {
// Delete an old webhook if it exists.
await webhookLib.deleteWebhook(`http://localhost:${config.port}/p2wdb`)
} catch (err) {
/* exit quietly */
// console.log('err deleting webhook: ', err)
}
await webhookLib.createWebhook(`http://localhost:${config.port}/p2wdb`)
console.log('Webhook created')
} catch (error) {
console.log('Webhook cant be created')
}
// try {
// try {
// // Delete an old webhook if it exists.
// await webhookLib.deleteWebhook(config.webhookTarget)
// } catch (err) {
// /* exit quietly */
// // console.log('err deleting webhook: ', err)
// }
//
// await webhookLib.createWebhook(config.webhookTarget)
// console.log('Webhook created')
// } catch (error) {
// console.log('Webhook cant be created')
// }
// startServer()
await app.listen(config.port)
this.server = await app.listen(config.port)
console.log(`Server started on ${config.port}`)
// Create the system admin user.
@@ -116,10 +130,16 @@ class Server {
// Attach the other IPFS controllers.
// Skip if this is a test environment.
if (config.env !== 'test') {
await controllers.attachControllers(app)
if (this.config.env !== 'test') {
await this.controllers.attachControllers(app)
}
// Display configuration settings
console.log('\nConfiguration:')
console.log(`Circuit Relay: ${this.config.isCircuitRelay}`)
console.log(`IPFS TCP port: ${this.config.ipfsTcpPort}`)
console.log(`IPFS WS port: ${this.config.ipfsWsPort}\n`)
return app
} catch (err) {
console.error('Could not start server. Error: ', err)
@@ -127,14 +147,14 @@ class Server {
console.log(
'Exiting after 5 seconds. Depending on process manager to restart.'
)
await sleep(5000)
process.exit(1)
await this.sleep(5000)
this.process.exit(1)
}
}
sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
}
function sleep (ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
module.exports = Server
export default Server
+19 -7
View File
@@ -5,15 +5,22 @@
/* eslint no-unneeded-ternary:0 */
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
// Get the version from the package.json file.
const pkgInfo = require('../../package.json')
import { readFileSync } from 'fs'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const pkgInfo = JSON.parse(readFileSync(`${__dirname.toString()}/../../package.json`))
const version = pkgInfo.version
const ipfsCoordName = process.env.COORD_NAME
? process.env.COORD_NAME
: 'ipfs-torlist-service-generic'
module.exports = {
export default {
// Configure TCP port.
port: process.env.PORT || 5700,
@@ -35,8 +42,8 @@ module.exports = {
useFullStackCash: process.env.USE_FULLSTACKCASH ? true : false,
consumerUrl: process.env.CONSUMER_URL
? process.env.CONSUMER_URL
// : 'https://free-bch.fullstack.cash',
: 'https://wa-usa-bch-consumer.fullstackcash.nl',
: 'https://free-bch.fullstack.cash',
// : 'https://wa-usa-bch-consumer.fullstackcash.nl',
// P2WDB URL that will accept API calls from the p2wdb npm library.
p2wdbUrl: process.env.P2WDB_URL ? process.env.P2WDB_URL : 'https://p2wdb.fullstack.cash',
@@ -85,7 +92,10 @@ module.exports = {
webhookService: process.env.WEBHOOKSERVICE
? process.env.WEBHOOKSERVICE
: 'http://localhost:5010/webhook', // P2WDB.
p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-test556',
p2wdbAppId: process.env.APP_ID ? process.env.APP_ID : 'bch-dex-001',
webhookTarget: process.env.WEBHOOKTARGET
? process.env.WEBHOOKTARGET
: 'http://localhost:5700/p2wdb',
// IPFS Ports
ipfsTcpPort: process.env.IPFS_TCP_PORT ? process.env.IPFS_TCP_PORT : 4001,
@@ -94,12 +104,14 @@ module.exports = {
// 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,
debugLevel: process.env.DEBUG_LEVEL ? parseInt(process.env.DEBUG_LEVEL) : 1,
// 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
: 5001,
chatPubSubChan: 'psf-ipfs-chat-001'
}
+1 -1
View File
@@ -4,7 +4,7 @@
specified.
*/
module.exports = {
export default {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
database: 'mongodb://localhost:27017/bch-swap-service-dev',
+1 -1
View File
@@ -7,7 +7,7 @@
so as not to conflict with the default host port of 27017 for MongoDB.
*/
module.exports = {
export default {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
// database: 'mongodb://172.17.0.1:5555/ipfs-service-prod',
+1 -1
View File
@@ -4,7 +4,7 @@
This is the environment run by the test suite.
*/
module.exports = {
export default {
session: 'secret-boilerplate-token',
token: 'secret-jwt-token',
database: 'mongodb://localhost:27017/bch-swap-service-test',
+19 -4
View File
@@ -1,6 +1,21 @@
const common = require('./env/common')
import common from './env/common.js'
const env = process.env.BCH_ENV || 'development'
const config = require(`./env/${env}`)
import development from './env/development.js'
import production from './env/production.js'
import test from './env/test.js'
module.exports = Object.assign({}, common, config)
const env = process.env.BCH_DEX || 'development'
console.log(`Loading config for this environment: ${env}`)
let config = development
if (env === 'test') {
config = test
} else if (env === 'prod') {
config = production
}
// const importStr = `./env/${env}.js`
// console.log('importStr: ', importStr)
// import config from importStr
export default Object.assign({}, common, config)
+34 -28
View File
@@ -1,30 +1,6 @@
const passport = require('koa-passport')
const User = require('../src/adapters/localdb/models/users')
const Strategy = require('passport-local')
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id, '-password')
done(null, user)
} catch (err) {
done(err)
}
})
passport.use(
'local',
new Strategy(
{
usernameField: 'email',
passwordField: 'password'
},
passportCallback
)
)
// import passport from 'koa-passport';
import User from '../src/adapters/localdb/models/users.js'
import Strategy from 'passport-local'
async function passportCallback (email, password, done) {
try {
@@ -49,5 +25,35 @@ async function passportCallback (email, password, done) {
}
}
function applyPassportMods (passport) {
passport.serializeUser((user, done) => {
done(null, user.id)
})
passport.deserializeUser(async (id, done) => {
try {
const user = await User.findById(id, '-password')
done(null, user)
} catch (err) {
done(err)
}
})
passport.use(
'local',
new Strategy(
{
usernameField: 'email',
passwordField: 'password'
},
passportCallback
)
)
return true
}
// For testing
module.exports = { passport, passportCallback }
// export default { passport, passportCallback };
// export default applyPassportMods
export { applyPassportMods, passportCallback }
+1 -1
View File
@@ -1,4 +1,4 @@
const Server = require('./bin/server.js')
import Server from './bin/server.js'
const server = new Server()
server.startServer()
+6728 -19047
View File
File diff suppressed because it is too large Load Diff
+19 -27
View File
@@ -1,20 +1,21 @@
{
"name": "bch-dex",
"version": "1.0.0",
"version": "2.0.0",
"description": "A DEX on BCH for trading SLP tokens.",
"main": "index.js",
"type": "module",
"scripts": {
"start": "node index.js",
"test": "npm run test:all",
"test:all": "export BCH_DEX=test && nyc --reporter=text mocha --exit --timeout 30000 --recursive test/unit test/e2e/automated/",
"test:all": "export BCH_DEX=test && c8 --reporter=text mocha --exit --timeout 15000 --recursive test/unit test/e2e/automated/",
"test:unit": "export BCH_DEX=test && mocha --exit --timeout 15000 --recursive test/unit/",
"test:e2e:auto": "export BCH_DEX=test && mocha --exit --timeout 30000 test/e2e/automated/",
"test:integration": "export BCH_DEX=test && mocha --exit --timeout 45000 --recursive test/integration",
"test:temp": "export BCH_DEX=test && mocha --exit --timeout 15000 -g '#rate-limit' test/unit/json-rpc/",
"lint": "standard --env mocha --fix",
"docs": "./node_modules/.bin/apidoc -i src/ -o docs",
"coverage": "nyc report --reporter=text-lcov | coveralls",
"coverage:report": "export BCH_DEX=test && nyc --reporter=html mocha --exit --timeout 15000 --recursive test/unit/ test/e2e/automated/"
"coverage": "c8 report --reporter=text-lcov | coveralls",
"coverage:report": "export BCH_DEX=test && c8 --reporter=html mocha --exit --timeout 15000 --recursive test/unit/ test/e2e/automated/"
},
"author": "Chris Troutner <chris.troutner@gmail.com>",
"contributors": [
@@ -27,15 +28,13 @@
},
"repository": "Permissionless-Software-Foundation/bch-dex",
"dependencies": {
"@psf/bch-js": "6.2.1",
"axios": "0.21.1",
"bch-message-lib": "2.1.4",
"axios": "0.27.2",
"bch-message-lib": "2.2.1",
"bcryptjs": "2.4.3",
"bitcoincashjs-lib": "3.3.3",
"glob": "7.1.6",
"ipfs": "0.60.0",
"ipfs-coord": "7.1.6",
"ipfs-http-client": "55.0.0",
"ipfs-coord-esm": "9.1.3",
"ipfs-http-client": "58.0.0",
"jsonrpc-lite": "2.2.0",
"jsonwebtoken": "8.5.1",
"jwt-bch-lib": "1.3.0",
@@ -52,34 +51,27 @@
"koa2-ratelimit": "0.9.1",
"libp2p": "^0.36.2",
"line-reader": "0.4.0",
"minimal-slp-wallet": "4.4.5",
"mongoose": "5.13.13",
"minimal-slp-wallet": "5.1.0",
"mongoose": "5.13.14",
"node-fetch": "npm:@achingbrain/node-fetch@2.6.7",
"nodemailer": "6.4.17",
"p2wdb": "1.3.1",
"nodemailer": "6.7.5",
"p2wdb": "2.2.3",
"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",
"bch-token-sweep": "1.5.16",
"apidoc": "0.51.1",
"bch-token-sweep": "2.1.2",
"c8": "7.12.0",
"chai": "4.3.0",
"coveralls": "2.11.4",
"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-promise": "^4.3.1",
"eslint-plugin-standard": "4.0.0",
"husky": "4.3.8",
"mocha": "8.4.0",
"nyc": "15.1.0",
"semantic-release": "17.4.4",
"mocha": "10.0.0",
"semantic-release": "19.0.3",
"sinon": "9.2.4",
"standard": "16.0.4",
"standard": "17.0.0",
"uuid": "8.3.2"
},
"release": {
-61
View File
@@ -1,61 +0,0 @@
# Docker Containers
The 'production' environment is assumed to be a set of Docker containers orchestrated with Docker Compose. The files in this directory will stand up three Docker containers:
1 An instance of go-ipfs.
2 An instance of MongoDB.
3 The JavaScript software in this repository.
The software in this repository depends on the first two containers, so if they aren't running correctly, the application won't run correctly either.
## IPFS
IPFS can be a little tricky to set up. By default, the container uses the following ports:
- 4001 for TCP connections, exposed publicly.
- 5001 for control by the application, exposed privately.
- 8080 for an IPFS gateway, consumed by the application, exposed privately.
If you already have an IPFS node running on a the computer, you will need to change the ports to avaid a conflict. To change the ports from the default, you'll need to perform a series of steps, and the order of the steps matter.
1. Edit the `docker-compose.yml` file and change the ports. Then save the file. Here is an example:
```
ports:
- 4101:4101
- 172.17.0.1:5101:5101
- 172.17.0.1:8180:8180
```
2. Bring the Docker containers up, and then back down. This will allow the IPFS container to create the config file that you'll need to edit.
- `docker-compose up -d`
- Wait a few seconds.
- `docker-compose down`
3. Update the generated config file at `../data/go-ipfs/data/config`, to update the ports in the config file, like this:
```
"Addresses": {
"API": "/ip4/0.0.0.0/tcp/5101",
"Announce": [],
"AppendAnnounce": [],
"Gateway": "/ip4/0.0.0.0/tcp/8180",
"NoAnnounce": [],
"Swarm": [
"/ip4/0.0.0.0/tcp/4101",
"/ip6/::/tcp/4101",
"/ip4/0.0.0.0/udp/4101/quic",
"/ip6/::/udp/4101/quic"
]
},
```
4. Update the port changes in the `start-production.sh` shell script. This tells the application which ports to use, in order to control the IPFS node, are are used when signaling other nodes.
5. Quickly rebuild the containers, to add the modified `start-production.sh` shell script to the application Docker container:
- `docker-compose build`
6. Now start the containers, and the port changes to IPFS should be complete.
+73
View File
@@ -0,0 +1,73 @@
# Create a Dockerized API server
#
#IMAGE BUILD COMMANDS
# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS
#FROM christroutner/ct-base-ubuntu
FROM ubuntu:20.04 as builder
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_16.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.
#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 rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v2
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/bch-dex-ui-v2
# For development: switch to unstable branch
RUN git checkout ct-unstable
# Install dependencies
#RUN mkdir .ipfsdata
#RUN npm install -g @mapbox/node-pre-gyp
RUN npm install
# Build the site
RUN CI=true npm run build
# Load the NGINX image.
FROM nginx
EXPOSE 80
# Copy the files built in the first container to the new NGINX container.
COPY --from=builder /home/safeuser/bch-dex-ui-v2/build /usr/share/nginx/html
#USER safeuser
@@ -12,7 +12,7 @@ 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 curl -sL https://deb.nodesource.com/setup_16.x -o nodesource_setup.sh
RUN bash nodesource_setup.sh
RUN apt-get install -y nodejs build-essential
@@ -46,11 +46,11 @@ RUN npm set registry http://94.130.170.209:4873/
# Clone the rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-service-provider
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/ipfs-service-provider
WORKDIR /home/safeuser/bch-dex
# For development: switch to unstable branch
RUN git checkout ct-unstable
@@ -63,13 +63,16 @@ RUN npm install
# Generate the API docs
RUN npm run docs
VOLUME /home/safeuser/keys
# Copy the wallet files
#COPY wallet.json wallet.json
#VOLUME /home/safeuser/keys
# Expose the port the API will be served on.
EXPOSE 5010
#EXPOSE 5010
# Start the application.
COPY start-production.sh start-production.sh
#COPY start-production.sh start-production.sh
CMD ["./start-production.sh"]
#CMD ["npm", "start"]
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
# BEGIN: Optional configuration settings
# The human readable name this IPFS node identifies as.
export COORD_NAME=bch-dex-generic
# Allow this node to function as a circuit relay. It must not be behind a firewall.
#export ENABLE_CIRCUIT_RELAY=true
# 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:5666/bch-swap-service-prod
# Configure REST API port
export PORT=5700
# bch-dex specific env vars
export BCH_DEX=production
export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook
export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb
export APP_ID=bch-dex-001
npm start
+80 -25
View File
@@ -3,21 +3,27 @@
version: '3.9'
services:
mongo-ipfs-service:
image: mongo
container_name: mongo-ipfs-service
mongo-p2wdb-service:
image: mongo:4.2.0
container_name: mongo-p2wdb-service
ports:
- '5555:27017' # <host port>:<container port>
- '5666:27017' # <host port>:<container port>
volumes:
- ../data/database:/data/db
command: mongod --logpath=/dev/null # -- quiet
restart: always
ipfs:
image: ipfs/go-ipfs:v0.11.0
# https://github.com/christroutner/trickle-ipfs
image: christroutner/trickle-ipfs:v1.0.1
#build:
# context: ./
# dockerfile: Dockerfile
container_name: ipfs
environment:
MY_ENV_VAR: 'placeholder'
IPFS_DAEMON_ARGUMENTS: '--enable-pubsub-experiment --migrate=true --agent-version-suffix=docker --routing=dhtclient'
UPLOAD_KBPS: '1000'
DOWNLOAD_KBPS: '1000'
logging:
driver: 'json-file'
options:
@@ -26,25 +32,75 @@ services:
mem_limit: 2000mb
ports:
- 4001:4001
- 4003:4003
- 172.17.0.1:5001:5001
- 172.17.0.1:8080:8080
command: [
'./start-ipfs.sh'
]
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'
]
- ../data/go-ipfs/data:/root/.ipfs
restart: always
ipfs-service:
build: .
container_name: ipfs-service
p2wdb:
#build:
# context: ./p2wdb/
# dockerfile: Dockerfile
image: christroutner/p2wdb:v3.1.8
container_name: p2wdb
environment:
CONSUMER_URL: 'https://free-bch.fullstack.cash'
DEBUG_LEVEL: 1
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1gb
links:
- mongo-p2wdb-service
ports:
# <host port>:<container port>
- 5667:5667 # REST API
#- 5668:5668 # IPFS TCP port
#- 5669:5669 # IPFS WS Port
volumes:
- ../data/ipfsdata/p2wdb:/home/safeuser/ipfs-p2wdb-service/.ipfsdata/p2wdb
- ./p2wdb/start-production.sh:/home/safeuser/ipfs-p2wdb-service/start-production.sh
restart: always
bch-dex:
#build:
# context: ./bch-dex/
# dockerfile: Dockerfile
image: christroutner/bch-dex:v2.0.0
container_name: bch-dex
environment:
CONSUMER_URL: 'https://free-bch.fullstack.cash'
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1000mb
links:
- mongo-p2wdb-service
- p2wdb
ports:
- '5700:5700' # <host port>:<container port>
volumes:
- ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json
- ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh
restart: always
dex-ui:
#build:
# context: ./bch-dex-ui/
# dockerfile: Dockerfile
image: christroutner/bch-dex-ui:v1.12.0
container_name: dex-ui
environment:
SERVER: 'http://192.168.2.3'
logging:
driver: 'json-file'
options:
@@ -52,10 +108,9 @@ services:
max-file: '10'
mem_limit: 500mb
links:
- mongo-ipfs-service
- ipfs
- bch-dex
ports:
- '5010:5010' # <host port>:<container port>
volumes:
- ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata
- '4500:80' # <host port>:<container port>
# volumes:
# - ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata
restart: always
+71
View File
@@ -0,0 +1,71 @@
# Create a Docker container for the P2WDB
#
#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_16.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 'abcd8765' change value below if you want a different password
RUN echo safeuser:abcd8765 | chpasswd
#Set the working directory to be the users home directory
WORKDIR /home/safeuser
#Setup NPM for non-root global install (like on a mac)
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.
#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 rest.bitcoin.com repository
RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service
WORKDIR /home/safeuser/ipfs-p2wdb-service
RUN mkdir .ipfsdata
RUN git checkout ct-unstable
#RUN npm install fsevents
# Install dependencies
#RUN mkdir .ipfsdata
RUN npm install
# Generate the API docs
RUN npm run docs
# Expose the port the API will be served on.
#EXPOSE 5010
# Start the application.
#COPY start-production.sh start-production.sh
CMD ["./start-production.sh"]
#CMD ["npm", "start"]
# Used for debugging
#COPY dummyapp.js dummyapp.js
#CMD ["node", "dummyapp.js"]
+4
View File
@@ -0,0 +1,4 @@
setInterval(function () {
const now = new Date()
console.log(`ping ${now.toLocaleString()}`)
}, 10000)
@@ -4,11 +4,10 @@
# 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"
export MNEMONIC="mass response fiscal world message exact series swallow forward confirm canoe festival"
# The human readable name this IPFS node identifies as.
export COORD_NAME=ipfs-service-provider-generic
export COORD_NAME=generic-p2wdb-production
# Allow this node to function as a circuit relay. It must not be behind a firewall.
#export ENABLE_CIRCUIT_RELAY=true
@@ -17,22 +16,32 @@ export COORD_NAME=ipfs-service-provider-generic
#export CR_DOMAIN=subdomain.yourdomain.com
# Debug level. 0 = minimal info. 2 = max info.
export DEBUG_LEVEL=2
# This value set by docker-compose.yml
#export DEBUG_LEVEL=1
# Log-in information for retrieving a JWT token from FullStack.cash.
export FULLSTACKLOGIN=demo@demo.com
export FULLSTACKPASS=demo
# END: Optional configuration settings
# Production database connection string.
export DBURL=mongodb://172.17.0.1:5555/ipfs-service-prod
export DBURL=mongodb://172.17.0.1:5666/p2wdb-service-dev
# Configure IPFS ports
#export IPFS_TCP_PORT=5668
#export IPFS_WS_PORT=5669
# Configure REST API port
export PORT=5010
export PORT=5667
# Production settings using external go-ipfs node.
export SVC_ENV=production
export P2W_ENV=production
export IPFS_HOST=172.17.0.1
export IPFS_API_PORT=5001
export IPFS_TCP_PORT=4001
#export IPFS_WS_PORT=5269
# P2WDB specific env vars
#export ORBITDB_NAME=/orbitdb/zdpuAm4fPafpjs5mgbBUJV8Az7kd8Xj1ttD6M1JaAxF8RMRrw/psf-bch-p2wdb-keyvalue-v1.0.0-0004
npm start
@@ -0,0 +1,73 @@
# Create a Dockerized API server
#
#IMAGE BUILD COMMANDS
# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS
#FROM christroutner/ct-base-ubuntu
FROM ubuntu:20.04 as builder
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_16.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.
#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 rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex-ui-v2
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/bch-dex-ui-v2
# For development: switch to unstable branch
RUN git checkout ct-unstable
# Install dependencies
#RUN mkdir .ipfsdata
#RUN npm install -g @mapbox/node-pre-gyp
RUN npm install
# Build the site
RUN CI=true npm run build
# Load the NGINX image.
FROM nginx
EXPOSE 80
# Copy the files built in the first container to the new NGINX container.
COPY --from=builder /home/safeuser/bch-dex-ui-v2/build /usr/share/nginx/html
#USER safeuser
+78
View File
@@ -0,0 +1,78 @@
# Create a Dockerized API server
#
#IMAGE BUILD COMMANDS
# ct-base-ubuntu = ubuntu 18.04 + nodejs v10 LTS
#FROM christroutner/ct-base-ubuntu
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_16.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.
#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 rest.bitcoin.com repository
WORKDIR /home/safeuser
RUN git clone https://github.com/Permissionless-Software-Foundation/bch-dex
# Switch to the desired branch. `master` is usually stable,
# and `stage` has the most up-to-date changes.
WORKDIR /home/safeuser/bch-dex
# For development: switch to unstable branch
RUN git checkout ct-unstable
# Install dependencies
#RUN mkdir .ipfsdata
#RUN npm install -g @mapbox/node-pre-gyp
RUN npm install
# Generate the API docs
RUN npm run docs
# Copy the wallet files
#COPY wallet.json wallet.json
#VOLUME /home/safeuser/keys
# Expose the port the API will be served on.
#EXPOSE 5010
# Start the application.
#COPY start-production.sh start-production.sh
CMD ["./start-production.sh"]
#CMD ["npm", "start"]
+32
View File
@@ -0,0 +1,32 @@
#!/bin/bash
# BEGIN: Optional configuration settings
# The human readable name this IPFS node identifies as.
export COORD_NAME=bch-dex-generic
# Allow this node to function as a circuit relay. It must not be behind a firewall.
#export ENABLE_CIRCUIT_RELAY=true
# 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:5666/bch-swap-service-prod
# Configure REST API port
export PORT=5700
# bch-dex specific env vars
export BCH_DEX=production
export WEBHOOKSERVICE=http://172.17.0.1:5667/webhook
export WEBHOOKTARGET=http://172.17.0.1:5700/p2wdb
export APP_ID=bch-dex-001
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}')
+112
View File
@@ -0,0 +1,112 @@
# Start the service with the command 'docker-compose up -d'
version: '3.9'
services:
mongo-bch-dex:
image: mongo:4.2.0
container_name: mongo-bch-dex
ports:
- '5666:27017' # <host port>:<container port>
volumes:
- ../data/database:/data/db
command: mongod --logpath=/dev/null # -- quiet
restart: always
ipfs:
image: christroutner/trickle-ipfs-rpi:v1.0.1
#image: odanado/go-ipfs:v0.11.0
container_name: ipfs
environment:
IPFS_DAEMON_ARGUMENTS: '--enable-pubsub-experiment --migrate=true --agent-version-suffix=docker --routing=dhtclient'
UPLOAD_KBPS: '25'
DOWNLOAD_KBPS: '25'
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1000mb
ports:
- 4001:4001
- 4003:4003
- 172.17.0.1:5001:5001
- 172.17.0.1:8080:8080
volumes:
- ./data/go-ipfs:/root/.ipfs
command: [
'./start-ipfs.sh'
]
restart: always
p2wdb:
#build:
# context: ./p2wdb/
# dockerfile: Dockerfile
image: christroutner/p2wdb-rpi:v3.1.5
container_name: p2wdb
environment:
CONSUMER_URL: 'https://wa-usa-bch-consumer.fullstackcash.nl'
DEBUG_LEVEL: 1
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1gb
links:
- mongo-bch-dex
ports:
# <host port>:<container port>
- 5667:5667 # REST API
#- 5668:5668 # IPFS TCP port
#- 5669:5669 # IPFS WS Port
volumes:
- ../data/ipfsdata/p2wdb:/home/safeuser/ipfs-p2wdb-service/.ipfsdata/p2wdb
- ./p2wdb/start-production.sh:/home/safeuser/ipfs-p2wdb-service/start-production.sh
restart: always
bch-dex:
#build:
# context: ./bch-dex/
# dockerfile: Dockerfile
image: christroutner/bch-dex-rpi:v1.13.0
container_name: bch-dex
environment:
#CONSUMER_URL: 'https://free-bch.fullstack.cash'
CONSUMER_URL: 'https://wa-usa-bch-consumer.fullstackcash.nl'
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 1000mb
links:
- mongo-bch-dex
- p2wdb
ports:
- '5700:5700' # <host port>:<container port>
volumes:
- ../scripts/wallet.json:/home/safeuser/bch-dex/wallet.json
- ./bch-dex/start-production.sh:/home/safeuser/bch-dex/start-production.sh
restart: always
dex-ui:
#build:
# context: ./bch-dex-ui/
# dockerfile: Dockerfile
image: christroutner/bch-dex-ui-rpi:v1.2.2
container_name: dex-ui
logging:
driver: 'json-file'
options:
max-size: '10m'
max-file: '10'
mem_limit: 500mb
links:
- bch-dex
ports:
- '4500:80' # <host port>:<container port>
# volumes:
# - ../data/ipfsdata:/home/safeuser/ipfs-service-provider/.ipfsdata
restart: always
+71
View File
@@ -0,0 +1,71 @@
# Create a Docker container for the P2WDB
#
#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_16.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 'abcd8765' change value below if you want a different password
RUN echo safeuser:abcd8765 | chpasswd
#Set the working directory to be the users home directory
WORKDIR /home/safeuser
#Setup NPM for non-root global install (like on a mac)
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.
#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 rest.bitcoin.com repository
RUN git clone https://github.com/Permissionless-Software-Foundation/ipfs-p2wdb-service
WORKDIR /home/safeuser/ipfs-p2wdb-service
RUN mkdir .ipfsdata
RUN git checkout ct-unstable
#RUN npm install fsevents
# Install dependencies
#RUN mkdir .ipfsdata
RUN npm install
# Generate the API docs
RUN npm run docs
# Expose the port the API will be served on.
#EXPOSE 5010
# Start the application.
#COPY start-production.sh start-production.sh
CMD ["./start-production.sh"]
#CMD ["npm", "start"]
# Used for debugging
#COPY dummyapp.js dummyapp.js
#CMD ["node", "dummyapp.js"]
+4
View File
@@ -0,0 +1,4 @@
setInterval(function () {
const now = new Date()
console.log(`ping ${now.toLocaleString()}`)
}, 10000)
+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.
export MNEMONIC="mass response fiscal world message exact series swallow forward confirm canoe festival"
# The human readable name this IPFS node identifies as.
export COORD_NAME=generic-p2wdb-production
# Allow this node to function as a circuit relay. It must not be behind a firewall.
#export ENABLE_CIRCUIT_RELAY=true
# 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.
# This value set by docker-compose.yml
#export DEBUG_LEVEL=1
# Log-in information for retrieving a JWT token from FullStack.cash.
export FULLSTACKLOGIN=demo@demo.com
export FULLSTACKPASS=demo
# END: Optional configuration settings
# Production database connection string.
export DBURL=mongodb://172.17.0.1:5666/p2wdb-service-dev
# Configure IPFS ports
export IPFS_TCP_PORT=5668
export IPFS_WS_PORT=5669
# Configure REST API port
export PORT=5667
export P2W_ENV=production
export IPFS_HOST=172.17.0.1
export IPFS_API_PORT=5001
export IPFS_TCP_PORT=4001
export IPFS_WS_PORT=4003
# P2WDB specific env vars
export ORBITDB_NAME=/orbitdb/zdpuAqNiwLiJBfbRK7uihV2hAbNSXj78ufzv5VyQb8GuvRwDh/psf-bch-p2wdb-keyvalue-v3.0.0-0001
npm start
+40
View File
@@ -0,0 +1,40 @@
/*
This script can be used to generate new Orders and Offers, until the UI for
that is built.
Customize the settings below to add your own Order. The token must exist in
the DEX app wallet in order to be acceped.
*/
const axios = require('axios')
const LOCALHOST = 'http://localhost:5700'
// const LOCALHOST = 'http://172.17.0.1:5700'
async function start () {
try {
const mockOrder = {
lokadId: 'SWP',
messageType: 1,
messageClass: 1,
tokenId:
'a4fb5c2da1aa064e25018a43f9165040071d9e984ba190c222a7f59053af84b2',
buyOrSell: 'sell',
rateInBaseUnit: 5000,
minUnitsToExchange: 5000,
numTokens: 2
}
const options = {
method: 'post',
url: `${LOCALHOST}/order`,
data: { order: mockOrder }
}
const result = await axios(options)
console.log('result.data: ', result.data)
} catch (err) {
console.log(err)
}
}
start()
+32
View File
@@ -0,0 +1,32 @@
/*
Generate a wallet.json file for use with the DEX.
*/
// Public NPM libraries
const BchWallet = require('minimal-slp-wallet/index')
const fs = require('fs').promises
async function createWallet () {
try {
// Configure the minimal-slp-wallet library to use the JSON RPC over IPFS.
const advancedConfig = {
interface: 'consumer-api',
noUpdate: true
}
// Wait for the wallet to be created.
this.bchWallet = new BchWallet(undefined, advancedConfig)
await this.bchWallet.walletInfoPromise
const walletData = this.bchWallet.walletInfo
walletData.nextAddress = 1
// Save the wallet file to disk.
await fs.writeFile('wallet.json', JSON.stringify(walletData, null, 2))
console.log('Generated wallet.json. Copy this file to the docker/bch-dex folder to be used inside the Docker container.')
console.log(`${JSON.stringify(walletData, null, 2)}`)
} catch (err) {
console.error('Error: ', err)
}
}
createWallet()
+143
View File
@@ -0,0 +1,143 @@
/*
This script will sweep the HD wallet, looking for NFTs. When found, it will
send the NFT to the root (index 0) address. It will pay transaction fees from
the root address.
*/
// Global npm libraries
const BchWallet = require('minimal-slp-wallet/index')
// Local libraries
const WalletAdapter = require('../../src/adapters/wallet')
// Constants
const EMTPY_ADDR_CUTOFF = 10
const WEB3_SERVER = 'https://free-bch.fullstack.cash'
async function sweepNfts () {
try {
// Open the wallet files.
const walletLib = new WalletAdapter()
// const walletInfo = await walletLib.openWallet()
const walletInfo = await openWallet(walletLib)
// const walletRoot = await walletLib.instanceWallet(walletInfo)
const walletRoot = new BchWallet(walletInfo.mnemonic, {
interface: 'consumer-api',
restURL: WEB3_SERVER
})
await walletRoot.walletInfoPromise
console.log('walletInfo: ', walletInfo)
const rootAddr = walletInfo.cashAddress
// const rootWif = walletInfo.privateKey
console.log(`Sweeping all funds into root address ${rootAddr}...`)
// Generate an HD tree
const bchjs = walletRoot.bchjs
const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic)
const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
let emptyAddrCnt = 0
let hdIndex = 1
do {
// Generate a keypair from the HD wallet.
const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`)
const cashAddress = bchjs.HDNode.toCashAddress(childNode)
const wifToSweep = bchjs.HDNode.toWIF(childNode)
console.log(`\n${hdIndex}: Sweeping ${cashAddress} with private key ${wifToSweep}`)
const walletChild = new BchWallet(wifToSweep, { interface: 'consumer-api', restURL: WEB3_SERVER })
await walletChild.walletInfoPromise
try {
const tokens = await walletChild.tokens.listTokensFromAddress(cashAddress)
// console.log(`tokens: ${JSON.stringify(tokens, null, 2)}`)
await walletChild.utxos.initUtxoStore(cashAddress)
// console.log(`utxoStore: ${JSON.stringify(utxoStore, null, 2)}`)
for (let i = 0; i < tokens.length; i++) {
const thisToken = tokens[i]
if (thisToken.tokenType === 65) {
console.log(`NFT ${thisToken.ticker} (${thisToken.name}) found. Sweeping to ${rootAddr}`)
await walletRoot.initialize()
// Send BCH to the child address, to pay for transaction fees.
const receiver1 = [{
address: cashAddress,
amountSat: 10000
}]
const txid1 = await walletRoot.send(receiver1)
console.log(`10,000 sats sent to child address. TXID: ${txid1}`)
// Wait for indexers to update.
console.log('Waiting for indexers to update...')
await bchjs.Util.sleep(120000)
await walletChild.initialize()
// Send NFT to root address.
const receiver2 = [{
address: rootAddr,
tokenId: thisToken.tokenId,
qty: thisToken.qty
}]
const txid2 = await walletChild.sendTokens(receiver2)
console.log(`NFT sent from child address to root address. TXID: ${txid2}`)
// Wait for indexers to update.
console.log('Waiting for indexers to update...')
await bchjs.Util.sleep(3000)
// Refresh the UTXO store.
await walletChild.utxos.initUtxoStore(cashAddress)
// Send the rest of the BCH back to the root address.
const txid3 = await walletChild.sendAll(rootAddr)
console.log(`Leftover BCH in child address sent to root address. TXID: ${txid3}`)
emptyAddrCnt = 0
}
}
// Wait between loop iterations.
await bchjs.Util.sleep(3000)
// emptyAddrCnt++
} catch (err) {
console.log(`error message with index ${hdIndex}: ${err.message}`)
console.log(err)
// emptyAddrCnt++
}
emptyAddrCnt++
hdIndex++
} while (emptyAddrCnt < EMTPY_ADDR_CUTOFF)
console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`)
console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n')
} catch (err) {
console.log('Error while sweeping NFTs: ', err)
}
}
sweepNfts()
// Open the wallet file, or create one if the file doesn't exist.
// Does not instance the wallet. The output of this function is expected to
// be passed to instanceWallet().
async function openWallet (walletLib) {
try {
// console.log('this.WALLET_FILE: ', this.WALLET_FILE)
const walletData = await walletLib.jsonFiles.readJSON('./wallet.json')
return walletData
} catch (err) {
console.error('Error in openWallet()')
throw err
}
}
+102
View File
@@ -0,0 +1,102 @@
/*
This script will travers the HD wallet and sweep funds and tokens back
into the root address (index 0). That root address needs to have funds
to pay for the transactions.
This script will sweep BCH and fungible (Type 1) tokens, but not NFTs.
*/
// Public npm libraries
// const BCHJS = require('@psf/bch-js')
const BchTokenSweep = require('bch-token-sweep/index')
// Local libraries
const WalletAdapter = require('../../src/adapters/wallet')
// Constants
const EMTPY_ADDR_CUTOFF = 10
async function sweepFunds () {
try {
// Open the wallet files.
const walletLib = new WalletAdapter()
// const walletInfo = await walletLib.openWallet()
const walletInfo = await openWallet(walletLib)
const wallet = await walletLib.instanceWallet(walletInfo)
console.log('walletInfo: ', walletInfo)
const rootAddr = walletInfo.cashAddress
const rootWif = walletInfo.privateKey
console.log(`Sweeping all funds into root address ${rootAddr}...`)
// Generate an HD tree
const bchjs = wallet.bchjs
const rootSeed = await bchjs.Mnemonic.toSeed(walletInfo.mnemonic)
const masterHDNode = bchjs.HDNode.fromSeed(rootSeed)
let emptyAddrCnt = 0
let hdIndex = 1
do {
// Generate a keypair from the HD wallet.
const childNode = masterHDNode.derivePath(`m/44'/245'/0'/0/${hdIndex}`)
const cashAddress = bchjs.HDNode.toCashAddress(childNode)
const wifToSweep = bchjs.HDNode.toWIF(childNode)
console.log(`\nSweeping ${cashAddress} with private key ${wifToSweep}`)
try {
// Sweep tokens from address
const sweeper = new BchTokenSweep(
wifToSweep,
rootWif,
wallet,
550,
rootAddr
)
await sweeper.populateObjectFromNetwork()
const hex = await sweeper.sweepTo(rootAddr)
// console.log(`hex: ${hex}`)
const txid = await sweeper.blockchain.broadcast(hex)
// console.log('Transaction ID', txid)
console.log(`Swept HD index ${hdIndex}. TXID: ${txid}`)
emptyAddrCnt = 0
// Wait between loop iterations.
await bchjs.Util.sleep(3000)
} catch (err) {
console.log(`error message with index ${hdIndex}: ${err.message}`)
// console.log(err)
emptyAddrCnt++
}
hdIndex++
} while (emptyAddrCnt < EMTPY_ADDR_CUTOFF)
console.log(`${EMTPY_ADDR_CUTOFF} empty addresses detected. Exiting.`)
console.log('\n\nDo not forget to reset the nextAddress property in the wallet.json file!\n\n')
} catch (err) {
console.error('Error in sweepFunds(): ', err)
}
}
sweepFunds()
// Open the wallet file, or create one if the file doesn't exist.
// Does not instance the wallet. The output of this function is expected to
// be passed to instanceWallet().
async function openWallet (walletLib) {
try {
// console.log('this.WALLET_FILE: ', this.WALLET_FILE)
const walletData = await walletLib.jsonFiles.readJSON('./wallet.json')
return walletData
} catch (err) {
console.error('Error in openWallet()')
throw err
}
}
+18 -8
View File
@@ -13,16 +13,24 @@
in the Adapter directory.
*/
'use strict'
const axios = require('axios').default
const mongoose = require('mongoose')
const User = require('../adapters/localdb/models/users')
const config = require('../../config')
const JsonFiles = require('../adapters/json-files')
// Global npm libraries
import axios from 'axios'
import mongoose from 'mongoose'
// Local libraries
import User from '../adapters/localdb/models/users.js'
import config from '../../config/index.js'
import JsonFiles from '../adapters/json-files.js'
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const jsonFiles = new JsonFiles()
const JSON_FILE = `system-user-${config.env}.json`
const JSON_PATH = `${__dirname.toString()}/../../config/${JSON_FILE}`
const JSON_PATH = `${__dirname.toString()}../../config/${JSON_FILE}`
const LOCALHOST = `http://localhost:${config.port}`
const context = {}
@@ -82,6 +90,8 @@ class Admin {
// applications like the Task Manager and the test scripts can access.
await jsonFiles.writeJSON(context, JSON_PATH)
// console.log('context: ', context)
// console.log('JSON_PATH: ', JSON_PATH)
return context
} catch (err) {
@@ -169,4 +179,4 @@ class Admin {
}
}
module.exports = Admin
export default Admin
+5 -4
View File
@@ -3,9 +3,10 @@
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
const MsgLib = require('bch-message-lib')
const BchWallet = require('minimal-slp-wallet/index')
import BCHJS from '@psf/bch-js'
import MsgLib from 'bch-message-lib'
import BchWallet from 'minimal-slp-wallet/index.js'
class Bch {
constructor () {
@@ -79,4 +80,4 @@ class Bch {
}
}
module.exports = Bch
export default Bch
+5 -6
View File
@@ -3,13 +3,12 @@
*/
/* eslint-disable no-useless-escape */
import config from '../../config/index.js'
import NodeMailer from '../adapters/nodemailer.js'
import wlogger from '../adapters/wlogger.js'
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
const config = require('../../config')
const NodeMailer = require('../adapters/nodemailer')
const nodemailer = new NodeMailer()
const { wlogger } = require('../adapters/wlogger')
let _this
@@ -60,4 +59,4 @@ class ContactLib {
}
}
}
module.exports = ContactLib
export default ContactLib
+4 -3
View File
@@ -5,8 +5,9 @@
for this file.
*/
const JwtLib = require('jwt-bch-lib')
const BCHJS = require('@psf/bch-js')
import JwtLib from 'jwt-bch-lib'
import BCHJS from '@psf/bch-js'
class FullStackJWT {
constructor (localConfig = {}) {
@@ -98,4 +99,4 @@ class FullStackJWT {
}
}
module.exports = FullStackJWT
export default FullStackJWT
+37 -35
View File
@@ -5,42 +5,26 @@
*/
// Public NPM libraries
const BCHJS = require('@psf/bch-js')
import BCHJS from '@psf/bch-js'
// Load individual adapter libraries.
const IPFSAdapter = require('./ipfs')
const LocalDB = require('./localdb')
const LogsAPI = require('./logapi')
const Passport = require('./passport')
const Nodemailer = require('./nodemailer')
import IPFSAdapter from './ipfs/index.js'
import LocalDB from './localdb/index.js'
import LogsAPI from './logapi.js'
import Passport from './passport.js'
import Nodemailer from './nodemailer.js'
// const { wlogger } = require('./wlogger')
const JSONFiles = require('./json-files')
const FullStackJWT = require('./fullstack-jwt')
const BCHAdapter = require('./bch')
const WalletAdapter = require('./wallet')
const P2wdbAdapter = require('./p2wdb-adapter')
import JSONFiles from './json-files.js'
//
// // 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 bchjs = new BCHJSAdapter()
//
// module.exports = {
// ipfs,
// localdb,
// logapi,
// passport,
// nodemailer,
// wlogger,
// jsonFiles,
// bchjs
import FullStackJWT from './fullstack-jwt.js'
import config from '../../config/index.js'
const config = require('../../config')
import BCHAdapter from './bch.js'
import WalletAdapter from './wallet.js'
import P2wdbAdapter from './p2wdb-adapter.js'
import Webhook from './webhook.js'
class Adapters {
constructor (localConfig = {}) {
@@ -56,7 +40,9 @@ class Adapters {
this.bch = new BCHAdapter()
this.config = config
this.wallet = new WalletAdapter()
localConfig.bchWallet = this.wallet.bchWallet
this.p2wdb = new P2wdbAdapter(localConfig)
this.webhook = new Webhook()
// Get a valid JWT API key and instance bch-js.
this.fullStackJwt = new FullStackJWT(config)
@@ -73,14 +59,30 @@ class Adapters {
}
// Start the IPFS node.
// await this.ipfs.start()
// Do not start these adapters if this is an e2e test.
// if (this.config.env !== 'test') {
// await this.ipfs.start()
// }
// Open the wallet file
const walletData = await this.wallet.openWallet()
// console.log('walletData: ', walletData)
// Instance the wallet.
await this.wallet.instanceWallet(walletData, this.bchjs)
if (this.config.env !== 'test') {
// Instance the wallet.
await this.wallet.instanceWallet(walletData, this.bchjs)
// Wait until a webhook is established with the P2WDB
await this.webhook.waitUntilSuccess(this.config.webhookTarget)
// Overwrite instances of wallet used by P2WDB lib.
this.p2wdb.bchWallet = this.wallet.bchWallet
this.p2wdb.bchjs = this.wallet.bchWallet.bchjs
}
console.log('Async Adapters have been started.')
return true
} catch (err) {
console.error('Error in adapters/index.js/start()')
throw err
@@ -88,4 +90,4 @@ class Adapters {
}
}
module.exports = Adapters
export default Adapters
+13 -4
View File
@@ -2,8 +2,11 @@
top-level IPFS library that combines the individual IPFS-based libraries.
*/
const IpfsAdapter = require('./ipfs')
const IpfsCoordAdapter = require('./ipfs-coord')
// Local libraries
import IpfsAdapter from './ipfs.js'
import IpfsCoordAdapter from './ipfs-coord.js'
import config from '../../../config/index.js'
class IPFS {
constructor (localConfig = {}) {
@@ -11,6 +14,7 @@ class IPFS {
this.ipfsAdapter = new IpfsAdapter()
this.IpfsCoordAdapter = IpfsCoordAdapter
this.process = process
this.config = config
this.ipfsCoordAdapter = {} // placeholder
@@ -31,11 +35,16 @@ class IPFS {
// Start ipfs-coord
this.ipfsCoordAdapter = new this.IpfsCoordAdapter({
ipfs: this.ipfs
ipfs: this.ipfs,
tcpPort: this.config.ipfsTcpPort,
wsPort: this.config.ipfsWsPort
})
await this.ipfsCoordAdapter.start()
console.log('ipfs-coord is ready.')
// Subscribe to the chat pubsub channel
await this.ipfsCoordAdapter.subscribeToChat()
return true
} catch (err) {
console.error('Error in adapters/ipfs/index.js/start()')
@@ -51,4 +60,4 @@ class IPFS {
}
}
module.exports = IPFS
export default IPFS
+23 -7
View File
@@ -5,12 +5,15 @@
*/
// Global npm libraries
const IpfsCoord = require('ipfs-coord')
const BCHJS = require('@psf/bch-js')
const publicIp = require('public-ip')
import IpfsCoord from 'ipfs-coord-esm'
// import BCHJS from '@psf/bch-js';
import SlpWallet from 'minimal-slp-wallet/index.js'
import publicIp from 'public-ip'
// Local libraries
const config = require('../../../config')
import config from '../../../config/index.js'
// const JSONRPC = require('../../controllers/json-rpc/')
let _this
@@ -28,7 +31,8 @@ class IpfsCoordAdapter {
// Encapsulate dependencies
this.IpfsCoord = IpfsCoord
this.ipfsCoord = {}
this.bchjs = new BCHJS()
// this.bchjs = new BCHJS()
this.wallet = new SlpWallet()
this.config = config
this.publicIp = publicIp
@@ -41,6 +45,9 @@ class IpfsCoordAdapter {
async start () {
const circuitRelayInfo = {}
// Wait for the BCH wallet to create the wallet.
await this.wallet.walletInfoPromise
// If configured as a Circuit Relay, get the public IP addresses for this node.
if (this.config.isCircuitRelay) {
try {
@@ -61,7 +68,7 @@ class IpfsCoordAdapter {
ipfs: this.ipfs,
type: 'node.js',
// type: 'browser',
bchjs: this.bchjs,
wallet: this.wallet,
privateLog: console.log, // Default to console.log
isCircuitRelay: this.config.isCircuitRelay,
circuitRelayInfo,
@@ -97,6 +104,15 @@ class IpfsCoordAdapter {
throw err
}
}
// Subscribe to the chat pubsub channel
async subscribeToChat () {
await this.ipfsCoord.adapters.pubsub.subscribeToPubsubChannel(
this.config.chatPubSubChan,
console.log,
this.ipfsCoord.thisNode
)
}
}
module.exports = IpfsCoordAdapter
export default IpfsCoordAdapter
+32 -31
View File
@@ -11,13 +11,14 @@
// Global npm libraries
// const IPFS = require('ipfs')
// const IPFS = require('@chris.troutner/ipfs')
const IPFSembedded = require('ipfs')
const IPFSexternal = require('ipfs-http-client')
const fs = require('fs')
const http = require('http')
// import IPFSembedded from 'ipfs';
import { create } from 'ipfs-http-client'
import fs from 'fs'
import http from 'http'
// Local libraries
const config = require('../../../config')
import config from '../../../config/index.js'
const IPFS_DIR = './.ipfsdata/ipfs'
@@ -25,17 +26,17 @@ class IpfsAdapter {
constructor (localConfig) {
// Encapsulate dependencies
this.config = config
this.fs = fs
this.create = create
// Choose the IPFS constructor based on the config settings.
this.IPFS = IPFSembedded // default
if (this.config.isProduction) {
this.IPFS = IPFSexternal
}
// this.IPFS = IPFSembedded // default
// if (this.config.isProduction) {
// this.IPFS = IPFSexternal
// }
// Properties of this class instance.
this.isReady = false
this.fs = fs
}
// Start an IPFS node.
@@ -85,7 +86,7 @@ class IpfsAdapter {
}
// Create a new IPFS node.
this.ipfs = await this.IPFS.create(ipfsOptions)
this.ipfs = await this.create(ipfsOptions)
// Set the 'server' profile so the node does not scan private networks.
await this.ipfs.config.profiles.apply('server')
@@ -102,9 +103,9 @@ class IpfsAdapter {
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')) {
this.rmBlocksDir()
}
// if (err.message.includes('No space left on device')) {
// this.rmBlocksDir()
// }
throw err
}
@@ -120,21 +121,21 @@ class IpfsAdapter {
// 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
}
}
// 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
// }
// }
}
module.exports = IpfsAdapter
export default IpfsAdapter
+3 -3
View File
@@ -1,8 +1,8 @@
/*
A utility file for reading and writing JSON files.
*/
'use strict'
const fs = require('fs')
import fs from 'fs'
let _this
@@ -75,4 +75,4 @@ class JsonFiles {
}
}
module.exports = JsonFiles
export default JsonFiles
+5 -5
View File
@@ -3,10 +3,10 @@
*/
// Load Mongoose models.
const Users = require('./models/users')
const Entries = require('./models/entry')
const Order = require('./models/order')
const Offer = require('./models/offer')
import Users from './models/users.js'
import Entries from './models/entry.js'
import Order from './models/order.js'
import Offer from './models/offer.js'
class LocalDB {
constructor () {
@@ -18,4 +18,4 @@ class LocalDB {
}
}
module.exports = LocalDB
export default LocalDB
+2 -2
View File
@@ -1,4 +1,4 @@
const mongoose = require('mongoose')
import mongoose from 'mongoose'
const Entry = new mongoose.Schema({
entry: { type: String },
@@ -10,4 +10,4 @@ const Entry = new mongoose.Schema({
merit: { type: Number }
})
module.exports = mongoose.model('entry', Entry)
export default mongoose.model('entry', Entry)
+8 -3
View File
@@ -1,4 +1,4 @@
const mongoose = require('mongoose')
import mongoose from 'mongoose'
const Offer = new mongoose.Schema({
@@ -7,6 +7,7 @@ const Offer = new mongoose.Schema({
utxoTxid: { type: String },
utxoVout: { type: Number },
ticker: { type: String },
tokenType: { type: Number },
// Trade data
buyOrSell: { type: String },
@@ -23,8 +24,12 @@ const Offer = new mongoose.Schema({
sigMsg: { type: String },
// Utility data
timestamp: { type: String },
timestamp: { type: Number },
globalTimestamp: { type: String },
localTimestamp: { type: String },
displayCategory: { type: String },
nsfw: { type: Boolean, default: false },
flags: { type: Array },
// SWaP Protocol Properties
lokadId: { type: String },
@@ -33,4 +38,4 @@ const Offer = new mongoose.Schema({
})
module.exports = mongoose.model('offer', Offer)
export default mongoose.model('offer', Offer)
+3 -2
View File
@@ -6,7 +6,7 @@
See the dev-docs/specification.md for details on each property.
*/
const mongoose = require('mongoose')
import mongoose from 'mongoose'
const Order = new mongoose.Schema({
// Token data
@@ -14,6 +14,7 @@ const Order = new mongoose.Schema({
utxoTxid: { type: String },
utxoVout: { type: Number },
ticker: { type: String },
tokenType: { type: Number },
// Trade data
buyOrSell: { type: String },
@@ -39,4 +40,4 @@ const Order = new mongoose.Schema({
messageClass: { type: Number }
})
module.exports = mongoose.model('order', Order)
export default mongoose.model('order', Order)
+8 -5
View File
@@ -1,7 +1,10 @@
const mongoose = require('mongoose')
const bcrypt = require('bcryptjs')
const config = require('../../../../config')
const jwt = require('jsonwebtoken')
// Global npm libraries
import mongoose from 'mongoose'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
// Local libraries
import config from '../../../../config/index.js'
const User = new mongoose.Schema({
type: { type: String, default: 'user' },
@@ -51,4 +54,4 @@ User.methods.generateToken = function generateToken () {
}
// export default mongoose.model('user', User)
module.exports = mongoose.model('user', User)
export default mongoose.model('user', User)
+2 -2
View File
@@ -3,7 +3,7 @@
orders from the datatabase.
*/
const Order = require('./models/order')
import Order from './models/order.js'
// let _this
@@ -39,4 +39,4 @@ class OrderPagination {
}
}
module.exports = OrderPagination
export default OrderPagination
+12 -5
View File
@@ -1,9 +1,14 @@
const lineReader = require('line-reader')
const fs = require('fs')
import lineReader from 'line-reader'
import fs from 'fs'
const config = require('../../config')
import config from '../../config/index.js'
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
let _this
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
class LogsApi {
constructor () {
@@ -135,8 +140,10 @@ class LogsApi {
if (!filename || typeof filename !== 'string') {
throw new Error('filename must be a string')
}
// Throw an error if the file does not exist.
console.log('readLines() filename: ', filename)
// Throw an error if the file does not exist.
if (!_this.fs.existsSync(filename)) {
throw new Error('file does not exist')
}
@@ -167,4 +174,4 @@ class LogsApi {
}
}
module.exports = LogsApi
export default LogsApi
+4 -5
View File
@@ -3,11 +3,10 @@
*/
'use strict'
const nodemailer = require('nodemailer')
import nodemailer from 'nodemailer'
const config = require('../../config')
const { wlogger } = require('./wlogger')
import config from '../../config/index.js'
import wlogger from './wlogger.js'
let _this
@@ -150,4 +149,4 @@ class NodeMailer {
}
}
module.exports = NodeMailer
export default NodeMailer
+17 -9
View File
@@ -3,18 +3,19 @@
*/
// Public npm libraries.
const axios = require('axios')
const { Write, Read } = require('p2wdb/index')
import axios from 'axios'
import { Write, Read } from 'p2wdb/index.js'
// Local libraries
const config = require('../../config')
import config from '../../config/index.js'
class P2wdbAdapter {
constructor (localConfig = {}) {
// Dependency injection
this.bchjs = localConfig.bchjs
if (!this.bchjs) {
throw new Error('Must pass an instance of bch-js when instantiating p2wdb.js adapter.')
this.bchWallet = localConfig.bchWallet
if (!this.bchWallet) {
throw new Error('Must pass an instance of minimal-slp-wallet as bchWallet when instantiating p2wdb.js adapter.')
}
// Encapsulate dependencies
@@ -22,6 +23,7 @@ class P2wdbAdapter {
this.config = config
this.Write = Write
this.Read = Read
this.bchjs = this.bchWallet.bchjs
// Allow the localConfig to overwrite the config file values.
this.p2wdbURL = localConfig.p2wdbURL || config.p2wdbUrl
@@ -51,6 +53,10 @@ class P2wdbAdapter {
// settings.
instantiateWriteLib (wif) {
try {
if (!wif) {
throw new Error('WIF input required when calling instantiateWriteLib()')
}
// Object used to configure the Write library.
let configObj = {}
@@ -62,7 +68,8 @@ class P2wdbAdapter {
wif,
serverURL: this.p2wdbURL,
restURL: this.bchjs.restURL,
apiToken: this.bchjs.apiToken
apiToken: this.bchjs.apiToken,
bchWallet: this.bchWallet
}
} else {
// Use web 3 infrastructure.
@@ -72,7 +79,8 @@ class P2wdbAdapter {
wif,
serverURL: this.p2wdbURL,
interface: 'consumer-api',
restURL: this.config.consumerUrl
restURL: this.config.consumerUrl,
bchWallet: this.bchWallet
}
}
@@ -104,4 +112,4 @@ class P2wdbAdapter {
}
}
module.exports = P2wdbAdapter
export default P2wdbAdapter
+2 -2
View File
@@ -2,7 +2,7 @@
koa-passport is an authorization library used for different authentication schemes.
*/
const passport = require('koa-passport')
import passport from 'koa-passport'
let _this
class Passport {
@@ -32,4 +32,4 @@ class Passport {
}
}
module.exports = Passport
export default Passport
+55 -15
View File
@@ -3,12 +3,19 @@
*/
// Public npm libraries
const BchWallet = require('minimal-slp-wallet/index')
const bitcoinJs = require('bitcoincashjs-lib')
import BchWallet from 'minimal-slp-wallet/index.js'
import bitcoinJs from 'bitcoincashjs-lib'
// Local libraries
const JsonFiles = require('./json-files')
const config = require('../../config')
import JsonFiles from './json-files.js'
import config from '../../config/index.js'
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
const WALLET_FILE = `${__dirname.toString()}/../../wallet.json`
// const PROOF_OF_BURN_QTY = 0.01
@@ -20,9 +27,10 @@ class WalletAdapter {
// Encapsulate dependencies
this.jsonFiles = new JsonFiles()
this.WALLET_FILE = WALLET_FILE
this.BchWallet = BchWallet
this.config = config
this.bitcoinJs = bitcoinJs
this.BchWallet = BchWallet
this.bchWallet = {} // Will be replaced when initialized.
}
// Open the wallet file, or create one if the file doesn't exist.
@@ -38,7 +46,7 @@ class WalletAdapter {
walletData = await this.jsonFiles.readJSON(this.WALLET_FILE)
} catch (err) {
// Create a new wallet file if one does not already exist.
console.warn('Wallet file not found. Creating new wallet.json file.')
console.log('Wallet file not found. Creating new wallet.json file.')
// Create a new wallet.
// No-Update flag creates wallet without making any network calls.
@@ -69,7 +77,12 @@ class WalletAdapter {
// and pass the bch-js information to the minimal-slp-wallet library.
async instanceWallet (walletData) {
try {
// console.log(`instanceWallet() walletData: ${JSON.stringify(walletData, null, 2)}`)
// TODO: throw error if wallet data is not passed in.
if (!walletData.mnemonic) {
throw new Error('Wallet data is not formatted correctly. Can not read mnemonic in wallet file!')
}
const advancedConfig = {}
if (this.config.useFullStackCash) {
@@ -86,7 +99,9 @@ class WalletAdapter {
// Wait for wallet to initialize.
await this.bchWallet.walletInfoPromise
console.log('BCH wallet initialized.')
await this.bchWallet.initialize()
console.log(`BCH wallet initialized. Wallet address: ${this.bchWallet.walletInfo.cashAddress}`)
// console.log(`this.bchWallet.walletInfo: ${JSON.stringify(this.bchWallet.walletInfo, null, 2)}`)
return this.bchWallet
} catch (err) {
@@ -202,7 +217,7 @@ class WalletAdapter {
// Get token info on the offered UTXO
const txData = await this.bchWallet.getTxData([offerInfo.utxoTxid])
// console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
console.log(`txData: ${JSON.stringify(txData, null, 2)}`)
// Construct the UTXO being offered for sale.
const offeredUtxo = {
@@ -216,12 +231,27 @@ class WalletAdapter {
// Build First part of the collaborative Tx a.k.a. Alice
// Generate the OP_RETURN code.
const slpSendObj = bchjs.SLP.TokenType1.generateSendOpReturn(
[offeredUtxo],
offerInfo.numTokens.toString()
)
let slpSendObj
if (offerInfo.tokenType === 65) {
// Type 65 NFT
slpSendObj = bchjs.SLP.NFT1.generateNFTChildSendOpReturn(
[offeredUtxo],
offerInfo.numTokens.toString()
)
console.log(`slpOutputs: ${slpSendObj.outputs}`)
} else if (offerInfo.tokenType === 1) {
// Type 1 fungible token
slpSendObj = bchjs.SLP.TokenType1.generateSendOpReturn(
[offeredUtxo],
offerInfo.numTokens.toString()
)
console.log(`slpOutputs: ${slpSendObj.outputs}`)
} else {
throw new Error(`Unknown token type of ${offerInfo.tokenType}. Can not create Counter Offer.`)
}
const slpData = slpSendObj.script
console.log(`slpOutputs: ${slpSendObj.outputs}`)
// Currently this app only supports a single SLP token UTXO for exact
// token quantities (no token change). e.g. 1 UTXO representing the
@@ -328,12 +358,22 @@ class WalletAdapter {
// Update the UTXO store of the wallet.
await this.bchWallet.getUtxos()
// Get the token type of the token being moved.
// Combine Fungible and NFT token UTXOs.
let tokenUtxos = this.bchWallet.utxos.utxoStore.slpUtxos.type1.tokens.concat(
this.bchWallet.utxos.utxoStore.slpUtxos.nft.tokens)
// Get token UTXOs that match the token in the order.
tokenUtxos = tokenUtxos.filter(
x => x.tokenId === tokenId
)
const txid = await this.bchWallet.sendTokens(receiver, 3)
const utxoInfo = {
txid,
vout: 1,
hdIndex: keyPair.hdIndex
hdIndex: keyPair.hdIndex,
tokenType: tokenUtxos[0].tokenType
}
return utxoInfo
@@ -470,4 +510,4 @@ class WalletAdapter {
}
}
module.exports = WalletAdapter
export default WalletAdapter
+44 -3
View File
@@ -2,8 +2,9 @@
The (Clean Architecture) Adapter for manageing a webhook connection to P2WDB.
*/
const config = require('../../config')
const axios = require('axios')
import config from '../../config/index.js'
import axios from 'axios'
let _this
@@ -59,6 +60,46 @@ class WebHook {
throw err
}
}
// Returns a promise that will not resolve until a webhook has been successfully
// created with the P2WDB.
// Dev Note: This was created because establishing a webhook between bch-dex
// and the P2WDB at startup is critical. If it's not established, then bch-dex
// can not 'see' new Offers and Counter Offers.
async waitUntilSuccess (url) {
try {
let success = false
do {
try {
// Delete an old webhook if it exists.
await this.deleteWebhook(this.config.webhookTarget)
} catch (err) {
/* exit quietly */
// console.log('err deleting webhook: ', err)
}
try {
await this.createWebhook(this.config.webhookTarget)
console.log('Webhook created')
success = true
} catch (err) {
const now = new Date()
console.log(`${now.toLocaleString()}: Error trying to create webhook with P2WDB. Trying again...`)
await sleep(2000)
}
} while (!success)
return true
} catch (err) {
console.error('Error in webhook.js/waitUntilSuccess()')
throw err
}
}
}
module.exports = WebHook
function sleep (ms) {
return new Promise(resolve => setTimeout(resolve, ms))
}
export default WebHook
+14 -5
View File
@@ -6,10 +6,17 @@
'use strict'
const winston = require('winston')
require('winston-daily-rotate-file')
// Global npm libraries
import winston from 'winston'
import 'winston-daily-rotate-file'
const config = require('../../config')
// Local libraries
import config from '../../config/index.js'
// Hack to get __dirname back.
// https://blog.logrocket.com/alternatives-dirname-node-js-es-modules/
import * as url from 'url'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
class Wlogger {
constructor (localConfig = {}) {
@@ -49,7 +56,8 @@ class Wlogger {
}
notifyRotation (oldFilename, newFilename) {
this.wlogger.info('Rotating log files')
// this.wlogger.info('Rotating log files')
console.log('Rotating log files')
}
outputToConsole () {
@@ -69,4 +77,5 @@ logger.outputToConsole()
const wlogger = logger.wlogger
module.exports = { wlogger, Wlogger }
export { wlogger as default, Wlogger }
// export default wlogger
+30 -14
View File
@@ -6,28 +6,38 @@
// Public npm libraries.
// Local libraries
const Adapters = require('../adapters')
const JSONRPC = require('./json-rpc')
const UseCases = require('../use-cases')
const RESTControllers = require('./rest-api')
const TimerControllers = require('./timer-controllers')
// Load the Clean Architecture Adapters library
import Adapters from '../adapters/index.js'
// Load the JSON RPC Controller.
import JSONRPC from './json-rpc/index.js'
// Load the Clean Architecture Use Case libraries.
import UseCases from '../use-cases/index.js'
// const useCases = new UseCases({ adapters })
// Load the REST API Controllers.
import RESTControllers from './rest-api/index.js'
import TimerControllers from './timer-controllers.js'
class Controllers {
constructor (localConfig = {}) {
this.adapters = new Adapters()
this.useCases = new UseCases({ adapters: this.adapters })
this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases })
}
async attachControllers (app) {
// Wait for any startup processes to complete for the Adapters libraries.
// Spin up any adapter libraries that have async startup needs.
async initAdapters () {
await this.adapters.start()
}
// Attach the REST controllers to the Koa app.
// this.attachRESTControllers(app)
// this.attachRPCControllers()
this.timerControllers = new TimerControllers({ adapters: this.adapters, useCases: this.useCases })
// Run any Use Cases to startup the app.
async initUseCases () {
await this.useCases.start()
}
// Top-level function for this library.
@@ -42,6 +52,12 @@ class Controllers {
restControllers.attachRESTControllers(app)
}
// Attach any other controllers other than REST API controllers.
async attachControllers (app) {
// this.attachRPCControllers()
}
// Add the JSON RPC router to the ipfs-coord adapter.
attachRPCControllers () {
const jsonRpcController = new JSONRPC({
@@ -56,4 +72,4 @@ class Controllers {
}
}
module.exports = Controllers
export default Controllers
+3 -3
View File
@@ -6,10 +6,10 @@
*/
// Public npm libraries
const jsonrpc = require('jsonrpc-lite')
import jsonrpc from 'jsonrpc-lite'
// Local libraries
const config = require('../../../../config')
import config from '../../../../config/index.js'
class AboutRPC {
constructor (localConfig) {
@@ -48,4 +48,4 @@ class AboutRPC {
}
}
module.exports = AboutRPC
export default AboutRPC
+5 -4
View File
@@ -3,13 +3,14 @@
*/
// Public npm libraries
const jsonrpc = require('jsonrpc-lite')
import jsonrpc from 'jsonrpc-lite'
// Local libraries
// const AuthLib = require('../../lib/auth')
// const UserLib = require('../../../use-cases/user')
const { wlogger } = require('../../../adapters/wlogger')
const RateLimit = require('../rate-limit')
import wlogger from '../../../adapters/wlogger.js'
import RateLimit from '../rate-limit.js'
class AuthRPC {
constructor (localConfig = {}) {
@@ -173,4 +174,4 @@ class AuthRPC {
}
}
module.exports = AuthRPC
export default AuthRPC
+7 -6
View File
@@ -3,13 +3,14 @@
*/
// Public npm libraries
const jsonrpc = require('jsonrpc-lite')
import jsonrpc from 'jsonrpc-lite'
// Local support libraries
const { wlogger } = require('../../adapters/wlogger')
const UserController = require('./users')
const AuthController = require('./auth')
const AboutController = require('./about')
import wlogger from '../../adapters/wlogger.js'
import UserController from './users/index.js'
import AuthController from './auth/index.js'
import AboutController from './about/index.js'
let _this
@@ -190,4 +191,4 @@ class JSONRPC {
}
}
module.exports = JSONRPC
export default JSONRPC
+2 -2
View File
@@ -4,7 +4,7 @@
/* eslint no-useless-catch: 0 */
// Local libraries
const RateLimitLib = require('koa2-ratelimit').RateLimit
import { RateLimit as RateLimitLib } from 'koa2-ratelimit'
class RateLimit {
constructor (options) {
@@ -80,4 +80,4 @@ class RateLimit {
}
}
module.exports = RateLimit
export default RateLimit
+5 -4
View File
@@ -3,12 +3,13 @@
*/
// Public npm libraries
const jsonrpc = require('jsonrpc-lite')
import jsonrpc from 'jsonrpc-lite'
// Local libraries
// const UserLib = require('../../../use-cases/user')
const Validators = require('../validators')
const RateLimit = require('../rate-limit')
import Validators from '../validators.js'
import RateLimit from '../rate-limit.js'
class UserRPC {
constructor (localConfig = {}) {
@@ -533,4 +534,4 @@ class UserRPC {
// TODO create deleteUser()
}
module.exports = UserRPC
export default UserRPC
+4 -3
View File
@@ -4,10 +4,11 @@
/* eslint no-useless-catch: 0 */
// Public npm libraries
const jwt = require('jsonwebtoken')
import jwt from 'jsonwebtoken'
// Local libraries
const config = require('../../../config')
import config from '../../../config/index.js'
// const UserModel = require('../../adapters/localdb/models/users')
class Validators {
@@ -93,4 +94,4 @@ class Validators {
}
}
module.exports = Validators
export default Validators
+2 -2
View File
@@ -1,4 +1,4 @@
const Passport = require('../../../adapters/passport')
import Passport from '../../../adapters/passport.js'
const passport = new Passport()
let _this
@@ -96,4 +96,4 @@ class AuthRESTController {
}
}
module.exports = AuthRESTController
export default AuthRESTController
+3 -3
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const AuthRESTController = require('./controller')
import AuthRESTController from './controller.js'
class AuthRouter {
constructor (localConfig = {}) {
@@ -48,4 +48,4 @@ class AuthRouter {
}
}
module.exports = AuthRouter
export default AuthRouter
@@ -3,9 +3,9 @@
*/
/* eslint-disable no-useless-escape */
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
import ContactLib from '../../../adapters/contact.js'
const ContactLib = require('../../../adapters/contact')
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
const contactLib = new ContactLib()
let _this
@@ -74,4 +74,4 @@ class ContactController {
}
}
}
module.exports = ContactController
export default ContactController
+3 -3
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const ContactRESTControllerLib = require('./controller')
import ContactRESTControllerLib from './controller.js'
class ContactRouter {
constructor (localConfig = {}) {
@@ -53,4 +53,4 @@ class ContactRouter {
}
}
module.exports = ContactRouter
export default ContactRouter
+1 -1
View File
@@ -64,4 +64,4 @@ class EntryRESTControllerLib {
}
}
module.exports = EntryRESTControllerLib
export default EntryRESTControllerLib
+3 -3
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const EntryRESTControllerLib = require('./controller')
import EntryRESTControllerLib from './controller.js'
let _this
@@ -57,4 +57,4 @@ class UserRouter {
}
}
module.exports = UserRouter
export default UserRouter
+10 -10
View File
@@ -6,15 +6,15 @@
// Public npm libraries.
// Load the REST API Controllers.
const AuthRESTController = require('./auth')
const UserRouter = require('./users')
const ContactRESTController = require('./contact')
const LogsRESTController = require('./logs')
const EntryRouter = require('./entry')
const OfferRouter = require('./offer')
const OrderRouter = require('./order')
const P2WDBRouter = require('./p2wdb')
// Local libraries
import AuthRESTController from './auth/index.js'
import UserRouter from './users/index.js'
import ContactRESTController from './contact/index.js'
import LogsRESTController from './logs/index.js'
import EntryRouter from './entry/index.js'
import OfferRouter from './offer/index.js'
import OrderRouter from './order/index.js'
import P2WDBRouter from './p2wdb/index.js'
class RESTControllers {
constructor (localConfig = {}) {
@@ -72,4 +72,4 @@ class RESTControllers {
}
}
module.exports = RESTControllers
export default RESTControllers
+2 -2
View File
@@ -1,4 +1,4 @@
const LogsApiLib = require('../../../adapters/logapi')
import LogsApiLib from '../../../adapters/logapi.js'
const logsApiLib = new LogsApiLib()
let _this
@@ -62,4 +62,4 @@ class LogsApi {
}
}
module.exports = LogsApi
export default LogsApi
+3 -3
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const LogsRESTControllerLib = require('./controller')
import LogsRESTControllerLib from './controller.js'
class LogsRouter {
constructor (localConfig = {}) {
@@ -52,4 +52,4 @@ class LogsRouter {
}
}
module.exports = LogsRouter
export default LogsRouter
+2 -2
View File
@@ -1,4 +1,4 @@
module.exports = function errorMiddleware () {
export default function errorMiddleware () {
return async (ctx, next) => {
try {
await next()
@@ -8,4 +8,4 @@ module.exports = function errorMiddleware () {
ctx.app.emit('error', err, ctx)
}
}
}
};
@@ -1,11 +1,24 @@
/*
REST API validator middleware.
These are a series of functions that ensure the user making a REST API
matches a user in the database (or not). In can do fine-grain user control
such as telling the difference between an admin, a normal user, and an
anonymous user.
This middleware is used to gatekeep access to different REST API resources.
CT 9/17/22:
This library was lightly refactored to make it work with the new unit tests.
This not and the commented code below can be deleted once it is verified that
this refactor did not result in any breaking changes.
*/
const User = require('../../../adapters/localdb/models/users')
const config = require('../../../../config')
const jwt = require('jsonwebtoken')
const { wlogger } = require('../../../adapters/wlogger')
import User from '../../../adapters/localdb/models/users.js'
import config from '../../../../config/index.js'
import jwt from 'jsonwebtoken'
import wlogger from '../../../adapters/wlogger.js'
let _this
@@ -20,12 +33,10 @@ class Validators {
async ensureUser (ctx, next) {
try {
// console.log(`getToken: ${typeof (getToken)}`)
const token = _this.getToken(ctx)
if (!token) {
// console.log(`Err: Token not provided.`)
ctx.throw(401)
throw new Error('Token could not be retrieved from header')
}
let decoded = null
@@ -34,20 +45,23 @@ class Validators {
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
decoded = _this.jwt.verify(token, config.token)
} catch (err) {
// console.log(`Err: Token could not be decoded: ${err}`)
ctx.throw(401)
throw new Error('Could not verify JWT')
}
ctx.state.user = await _this.User.findById(decoded.id, '-password')
if (!ctx.state.user) {
// console.log(`Err: Could not find user.`)
ctx.throw(401)
// console.log('Err: Could not find user.')
throw new Error('Could not find user')
}
// return next()
return true
} catch (error) {
ctx.throw(401)
// console.log('Ensure user error: ', error)
// console.log('ctx: ', ctx)
ctx.status = 401
ctx.throw(401, error.message)
}
}
@@ -60,7 +74,8 @@ class Validators {
if (!token) {
// console.log(`Err: Token not provided.`)
ctx.throw(401)
// ctx.throw(401)
throw new Error('Token could not be retrieved from header')
}
let decoded = null
@@ -70,22 +85,26 @@ class Validators {
decoded = _this.jwt.verify(token, config.token)
} catch (err) {
// console.log(`Err: Token could not be decoded: ${err}`)
ctx.throw(401)
// ctx.throw(401)
throw new Error('Could not verify JWT')
}
ctx.state.user = await _this.User.findById(decoded.id, '-password')
if (!ctx.state.user) {
// console.log(`Err: Could not find user.`)
ctx.throw(401)
// ctx.throw(401)
throw new Error('Could not find user')
}
if (ctx.state.user.type !== 'admin') {
ctx.throw(401, 'not admin')
// ctx.throw(401, 'not admin')
throw new Error('User is not an admin')
}
// return next()
return true
} catch (error) {
ctx.status = 401
ctx.throw(401, error.message)
}
}
@@ -101,7 +120,8 @@ class Validators {
if (!token) {
// console.log(`Err: Token not provided.`)
ctx.throw(401)
// ctx.throw(401)
throw new Error('Token could not be retrieved from header')
}
// The user ID targeted in this API call.
@@ -114,14 +134,16 @@ class Validators {
// console.log(`config: ${JSON.stringify(config, null, 2)}`)
decoded = _this.jwt.verify(token, config.token)
} catch (err) {
// console.log(`Err: Token could not be decoded: ${err}`)
ctx.throw(401)
console.log(`Err: Token could not be decoded: ${err}`)
// ctx.throw(401)
throw new Error('Could not verify JWT')
}
ctx.state.user = await _this.User.findById(decoded.id, '-password')
if (!ctx.state.user) {
// console.log(`Err: Could not find user.`)
ctx.throw(401)
// ctx.throw(401)
throw new Error('Could not find user')
}
// console.log('ctx.state.user: ', ctx.state.user)
@@ -135,7 +157,8 @@ class Validators {
// If they don't match, then the calling user better be an admin.
if (ctx.state.user.type !== 'admin') {
ctx.throw(401, 'not admin')
// ctx.throw(401, 'not admin')
throw new Error('User is not an admin')
} else {
wlogger.verbose("It's ok. The user is an admin.")
}
@@ -144,6 +167,8 @@ class Validators {
// return next()
return true
} catch (error) {
// console.log('Error in ensureTargetUserOrAdmin(): ', error)
ctx.status = 401
ctx.throw(401, error.message)
}
}
@@ -166,4 +191,4 @@ class Validators {
}
}
module.exports = Validators
export default Validators
+38 -5
View File
@@ -2,7 +2,7 @@
REST API Controller library for the /offer route
*/
const { wlogger } = require('../../../adapters/wlogger')
import wlogger from '../../../adapters/wlogger.js'
let _this
@@ -49,14 +49,47 @@ class OfferRESTControllerLib {
}
}
// curl -X GET http://localhost:5700/offer/list
// curl -X GET http://localhost:5700/offer/list/all/0
async listOffers (ctx) {
try {
const offers = await _this.useCases.offer.listOffers()
let page = ctx.params.page
if (!page) page = 0
const offers = await _this.useCases.offer.listOffers(page)
ctx.body = offers
} catch (err) {
console.log('Error in listOffers REST API handler.')
console.log('Error in listOffers REST API handler: ', err)
_this.handleError(ctx, err)
}
}
// curl -X GET http://localhost:5700/offer/list/nft/0
async listNftOffers (ctx) {
try {
let page = ctx.params.page
if (!page) page = 0
const offers = await _this.useCases.offer.listNftOffers(page)
ctx.body = offers
} catch (err) {
console.log('Error in listNftOffers REST API handler: ', err)
_this.handleError(ctx, err)
}
}
// curl -X GET http://localhost:5700/offer/list/fungible/0
async listFungibleOffers (ctx) {
try {
let page = ctx.params.page
if (!page) page = 0
const offers = await _this.useCases.offer.listFungibleOffers(page)
ctx.body = offers
} catch (err) {
console.log('Error in Fungible REST API handler: ', err)
_this.handleError(ctx, err)
}
}
@@ -95,4 +128,4 @@ class OfferRESTControllerLib {
}
}
module.exports = OfferRESTControllerLib
export default OfferRESTControllerLib
+6 -4
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const OfferRESTControllerLib = require('./controller')
import OfferRESTControllerLib from './controller.js'
let _this
@@ -50,8 +50,10 @@ class OfferRouter {
// Define the routes and attach the controller.
this.router.post('/', _this.offerRESTController.createOffer)
this.router.get('/list', _this.offerRESTController.listOffers)
this.router.post('/take', _this.offerRESTController.takeOffer)
this.router.get('/list/all/:page', _this.offerRESTController.listOffers)
this.router.get('/list/nft/:page', _this.offerRESTController.listNftOffers)
this.router.get('/list/fungible/:page', _this.offerRESTController.listFungibleOffers)
// Attach the Controller routes to the Koa app.
app.use(_this.router.routes())
@@ -59,4 +61,4 @@ class OfferRouter {
}
}
module.exports = OfferRouter
export default OfferRouter
+1 -1
View File
@@ -65,4 +65,4 @@ class OrderRESTControllerLib {
}
}
module.exports = OrderRESTControllerLib
export default OrderRESTControllerLib
+3 -3
View File
@@ -3,10 +3,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const OrderRESTControllerLib = require('./controller')
import OrderRESTControllerLib from './controller.js'
let _this
@@ -57,4 +57,4 @@ class OrderRouter {
}
}
module.exports = OrderRouter
export default OrderRouter
+12 -1
View File
@@ -45,12 +45,23 @@ class P2WDBRESTControllerLib {
const counterOffer = ctx.request.body
await _this.useCases.offer.acceptCounterOffer(counterOffer)
//
} else if (dataType.includes('offer')) {
// Detect and handle new Offers
console.log('offer data detected')
const offerObj = ctx.request.body
await _this.useCases.offer.createOffer(offerObj)
//
} else if (dataType.includes('flag')) {
// Detect and handle data generated by users flagging NSFW Offers.
const flagData = ctx.request.body
console.log('Flag type data received: ', flagData)
// const p2wdbHash = flagData.p2wdbHash
await _this.useCases.offer.flagOffer(flagData)
} else {
console.log('Could not route P2WDB webhook data.')
}
@@ -90,4 +101,4 @@ class P2WDBRESTControllerLib {
}
}
module.exports = P2WDBRESTControllerLib
export default P2WDBRESTControllerLib
+3 -3
View File
@@ -5,10 +5,10 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const P2WDBRESTControllerLib = require('./controller')
import P2WDBRESTControllerLib from './controller.js'
let _this
@@ -59,4 +59,4 @@ class P2WDBRouter {
}
}
module.exports = P2WDBRouter
export default P2WDBRouter
+4 -4
View File
@@ -2,7 +2,7 @@
REST API Controller library for the /user route
*/
const { wlogger } = require('../../../adapters/wlogger')
import wlogger from '../../../adapters/wlogger.js'
let _this
@@ -36,7 +36,7 @@ class UserRESTControllerLib {
* @apiGroup REST Users
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X POST -d '{ "user": { "email": "email@format.com", "name": "my name", "password": "secretpasas" } }' localhost:5001/users
* curl -H "Content-Type: application/json" -X POST -d '{ "user": { "email": "email@format.com", "name": "my name", "password": "secretpasas" } }' localhost:5010/users
*
* @apiParam {Object} user User object (required)
* @apiParam {String} user.email Email
@@ -136,7 +136,7 @@ class UserRESTControllerLib {
* @apiGroup REST Users
*
* @apiExample Example usage:
* curl -H "Content-Type: application/json" -X GET localhost:5000/users/56bd1da600a526986cf65c80
* curl -H "Content-Type: application/json" -X GET localhost:5010/users/56bd1da600a526986cf65c80
*
* @apiSuccess {Object} users User object
* @apiSuccess {ObjectId} users._id User id
@@ -281,4 +281,4 @@ class UserRESTControllerLib {
}
}
module.exports = UserRESTControllerLib
export default UserRESTControllerLib
+5 -4
View File
@@ -3,11 +3,12 @@
*/
// Public npm libraries.
const Router = require('koa-router')
import Router from 'koa-router'
// Local libraries.
const UserRESTControllerLib = require('./controller')
const Validators = require('../middleware/validators')
import UserRESTControllerLib from './controller.js'
import Validators from '../middleware/validators.js'
let _this
@@ -85,4 +86,4 @@ class UserRouter {
}
}
module.exports = UserRouter
export default UserRouter
+1 -1
View File
@@ -56,4 +56,4 @@ class TimerControllers {
}
}
module.exports = TimerControllers
export default TimerControllers
+1 -1
View File
@@ -38,4 +38,4 @@ class Entry {
}
}
module.exports = Entry
export default Entry
+14 -4
View File
@@ -29,7 +29,8 @@ class OfferEntity {
utxoVout,
offerStatus,
makerAddr,
ticker
ticker,
tokenType
} = offerData.data
// Input Validation
@@ -69,6 +70,13 @@ class OfferEntity {
if (!ticker || typeof ticker !== 'string') {
throw new Error("Property 'ticker' must be a string.")
}
if (!tokenType || typeof tokenType !== 'number') {
throw new Error("Property 'tokenType' must be a number.")
}
// Convert the timestamp to a number.
let timestamp = new Date(offerData.timestamp)
timestamp = timestamp.getTime()
const validatedOfferData = {
messageType,
@@ -80,17 +88,19 @@ class OfferEntity {
numTokens,
utxoTxid,
utxoVout,
timestamp: offerData.timestamp,
timestamp,
globaltimestamp: offerData.timestamp,
localTimestamp: offerData.localTimeStamp,
txid: offerData.txid,
p2wdbHash: offerData.hash,
offerStatus: offerStatus || this.offerStatus[0],
makerAddr,
ticker
ticker,
tokenType
}
return validatedOfferData
}
}
module.exports = OfferEntity
export default OfferEntity
+1 -1
View File
@@ -65,4 +65,4 @@ class Order {
}
}
module.exports = Order
export default Order
+1 -1
View File
@@ -21,4 +21,4 @@ class User {
}
}
module.exports = User
export default User
+5 -3
View File
@@ -1,6 +1,8 @@
const { wlogger } = require('../adapters/wlogger')
const EntryEntiy = require('../entities/entry')
// local libraries
import wlogger from '../adapters/wlogger.js'
import EntryEntiy from '../entities/entry.js'
class EntryLib {
constructor (localConfig = {}) {
// console.log('User localConfig: ', localConfig)
@@ -63,4 +65,4 @@ class EntryLib {
}
}
module.exports = EntryLib
export default EntryLib
+18 -5
View File
@@ -4,10 +4,10 @@
https://troutsblog.com/blog/clean-architecture
*/
const UserUseCases = require('./user')
const EntryUseCases = require('./entry')
const OfferUseCases = require('./offer')
const OrderUseCases = require('./order')
import UserUseCases from './user.js'
import EntryUseCases from './entry.js'
import OfferUseCases from './offer/index.js'
import OrderUseCases from './order.js'
class UseCases {
constructor (localConfig = {}) {
@@ -25,6 +25,19 @@ class UseCases {
localConfig.order = this.order
this.offer = new OfferUseCases(localConfig)
}
// Run any startup Use Cases at the start of the app.
async start () {
// try {
console.log('Async Use Cases have been started.')
return true
// } catch (err) {
// console.error('Error in use-cases/index.js/start()')
// // console.log(err)
// throw err
// }
}
}
module.exports = UseCases
export default UseCases
+287 -41
View File
@@ -13,9 +13,17 @@
a partially signed transaction.
*/
// Global npm libraries
import axios from 'axios'
// Local libraries
const OfferEntity = require('../../entities/offer')
const config = require('../../../config')
import OfferEntity from '../../entities/offer.js'
import config from '../../../config/index.js'
const DEFAULT_ENTRIES_PER_PAGE = 20
const NFT_ENTRIES_PER_PAGE = 6
const FUNGIBLE_ENTRIES_PER_PAGE = 20
class OfferUseCases {
constructor (localConfig = {}) {
@@ -35,6 +43,7 @@ class OfferUseCases {
// Encapsulate dependencies
this.config = config
this.axios = axios
this.offerEntity = new OfferEntity()
this.OfferModel = this.adapters.localdb.Offer
@@ -46,8 +55,23 @@ class OfferUseCases {
try {
console.log('Use Case createOffer(offerObj): ', offerObj)
// Return if Offer already exists in database with the same P2WDB CID.
try {
await this.findOfferByHash(offerObj.hash)
console.log('Offer already found in local database.')
return false
} catch (err) { /* exit quietly */ }
// console.log('this.adapters.bchjs: ', this.adapters.bchjs)
// Input Validation
// TODO: This is a hack. Find a better way to protect against the corner-
// case of counter-offers getting routed here.
if (offerObj.data.dataType === 'counter-offer') {
console.log('WARN: Counter Offer innappropriately routed to createOffer()')
}
// Verify that UTXO in offer is unspent. If it is spent, then ignore the
// offer.
const txid = offerObj.data.utxoTxid
@@ -65,6 +89,22 @@ class OfferUseCases {
const offerEntity = this.offerEntity.validate(offerObj)
console.log('offerEntity: ', offerEntity)
// Get data about the token.
const tokenId = offerEntity.tokenId
const tokenData = await this.adapters.wallet.bchWallet.getTokenData(tokenId)
console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`)
// Generate a 'display category' for the token. This will allow the
// front end UI to figure out how to display the token.
const displayCategory = await this.categorizeToken(offerEntity, tokenData)
console.log('displayCategory: ', displayCategory)
offerEntity.displayCategory = displayCategory
// Detect if user set the NSFW flag.
let nsfw = false
nsfw = await this.detectNsfw(tokenData)
offerEntity.nsfw = nsfw
// Add offer to the local database.
const offerModel = new this.OfferModel(offerEntity)
await offerModel.save()
@@ -76,15 +116,145 @@ class OfferUseCases {
}
}
async listOffers () {
// By default this function returns false, to indicate the NFT is safe for work.
// If the user who created the token sets the nsfw property in the mutable data,
// this function will return true.
async detectNsfw (tokenData) {
try {
return this.OfferModel.find({})
let nsfw = false
const mutableCid = tokenData.mutableData
// If there is no mutable IPFS CID, then skip this token.
if (!mutableCid.includes('ipfs://')) return nsfw
// Revove the ipfs:// prefix.
const cid = mutableCid.substring(7)
// Retrieve the mutable data from Filecoin/IPFS.
const url = `https://${cid}.ipfs.w3s.link/data.json`
const result = await axios.get(url)
const mutableData = result.data
console.log(`mutableData: ${JSON.stringify(mutableData, null, 2)}`)
// Logical tests
const hasNsfw = !!mutableData.nsfw
const nsfwSetTrue = mutableData.nsfw === true
const nsfwStringTrue = mutableData.nsfw === 'true'
const nsfwDetected = hasNsfw && (nsfwSetTrue || nsfwStringTrue)
if (nsfwDetected) {
console.log('NSFW flag set as true')
nsfw = true
}
return nsfw
} catch (err) {
console.error('Error in detectNsfw(): ', err)
return false
}
}
// Categorize the token for display purposes. This will categorize a token
// into one of these categories:
// - nft
// - group
// - fungible
// - simple-nft
//
// The first three are easy to categorize. The simple-nft is a fungible token
// with a quantity of 1, decimals of 0, and no minting baton. Categorizing this
// type of token is the main reason why this function exists.
async categorizeToken (offerData, tokenData) {
try {
// console.log(`categorizeToken(): ${JSON.stringify(offerData, null, 2)}`)
// const tokenId = offerData.tokenId
//
// const tokenData = await this.adapters.wallet.bchWallet.getTokenData(tokenId)
// console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`)
if (tokenData.genesisData.type === 65) {
return 'nft'
}
// Create a set of checks to detect a simple NFT
const isType1 = tokenData.genesisData.type === 1
const hasNoMintingBaton = !tokenData.genesisData.mintBatonIsActive
const hasNoDecimals = !tokenData.genesisData.decimals
const hasQtyOfOne = parseInt(tokenData.genesisData.tokensInCirculationStr) === 1
if (isType1 && hasNoMintingBaton && hasNoDecimals && hasQtyOfOne) {
return 'simple-nft'
}
if (isType1) return 'fungible'
throw new Error(`Unknown token type: ${tokenData.genesisData.type}`)
} catch (err) {
console.error('Error in use-cases/offer/index.js categorizeToken(): ', err)
throw err
}
}
async listOffers (page = 0) {
try {
const data = await this.OfferModel.find({})
// Sort entries so newest entries show first.
.sort('-timestamp')
// Skip to the start of the selected page.
.skip(page * DEFAULT_ENTRIES_PER_PAGE)
// Only return 20 results.
.limit(DEFAULT_ENTRIES_PER_PAGE)
return data
} catch (error) {
console.error('Error in use-cases/offer/listOffers()')
throw error
}
}
async listNftOffers (page = 0, nsfw = false) {
try {
const data = await this.OfferModel.find({
displayCategory: { $ne: 'fungible' },
nsfw
})
// Sort entries so newest entries show first.
.sort('-timestamp')
// Skip to the start of the selected page.
.skip(page * NFT_ENTRIES_PER_PAGE)
// Only return 20 results.
.limit(NFT_ENTRIES_PER_PAGE)
// console.log('listNftOffers() returning this data: ', data)
return data
} catch (error) {
console.error('Error in use-cases/offer/listNftOffers()')
throw error
}
}
async listFungibleOffers (page = 0) {
try {
const data = await this.OfferModel.find({ displayCategory: 'fungible' })
// Sort entries so newest entries show first.
.sort('-timestamp')
// Skip to the start of the selected page.
.skip(page * FUNGIBLE_ENTRIES_PER_PAGE)
// Only return 20 results.
.limit(FUNGIBLE_ENTRIES_PER_PAGE)
// console.log('listFungibleOffers() returning this data: ', data)
return data
} catch (error) {
console.error('Error in use-cases/offer/listFungibleOffers()')
throw error
}
}
// Generate phase 2 of 3 - take the other side of an Offer.
// Based on this example:
// https://github.com/Permission=less-Software-Foundation/bch-js-examples/blob/master/bch/applications/collaborate/sell-slp/e2e-exchange/step2-purchase-tx.js
@@ -107,15 +277,21 @@ class OfferUseCases {
}
// Verify that UTXO for sale is unspent. Abort if it's been spent.
const txid = offerInfo.utxoTxid
const vout = offerInfo.utxoVout
const utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
txid,
vout
)
// const txid = offerInfo.utxoTxid
// const vout = offerInfo.utxoVout
const utxo = {
tx_hash: offerInfo.utxoTxid,
tx_pos: offerInfo.utxoVout
}
const utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo)
// const utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
// txid,
// vout
// )
console.log('utxoStatus: ', utxoStatus)
if (utxoStatus === null) {
console.log(`utxo txid: ${txid}, vout: ${vout}`)
if (!utxoStatus) {
console.log(`utxo txid: ${offerInfo.utxoTxid}, vout: ${offerInfo.utxoVout}`)
// TODO: Mark this Offer as 'dead'
@@ -173,6 +349,10 @@ class OfferUseCases {
}
const hash = await this.adapters.p2wdb.write(p2wdbObj)
// Delete the Offer from the database, so that the user doesn't attempt
// to take the offer more than once.
offerInfo.remove()
// Return the P2WDB CID
return hash
@@ -193,6 +373,9 @@ class OfferUseCases {
await this.adapters.wallet.bchWallet.walletInfoPromise
// console.log(`utxos: ${JSON.stringify(this.adapters.wallet.bchWallet.utxos.utxoStore, null, 2)}`)
// Refresh the wallet UTXOs
await this.adapters.wallet.bchWallet.initialize()
// Ensure the app wallet has enough funds to write to the P2WDB.
const wif = this.adapters.wallet.bchWallet.walletInfo.privateKey
const canWriteToP2WDB = await this.adapters.p2wdb.checkForSufficientFunds(wif)
@@ -223,31 +406,39 @@ class OfferUseCases {
return true
} catch (err) {
console.error('Error in ensureFunds()')
console.error('Error in offer/index.js/ensureFunds()')
// Debugging
try {
console.error(`Error with this address: ${this.adapters.wallet.bchWallet.walletInfo.cashAddress}`)
} catch (err) { /* exit quietly */ }
throw err
}
}
async findOfferByHash (p2wdbHash) {
try {
if (typeof p2wdbHash !== 'string' || !p2wdbHash) {
throw new Error('p2wdbHash must be a string')
}
const offer = await this.OfferModel.findOne({ p2wdbHash })
if (!offer) {
throw new Error('offer not found')
}
const offerObject = offer.toObject()
// return this.offerEntity.validateFromModel(offerObject)
return offerObject
} catch (err) {
console.error('Error in findOffer(): ', err)
throw err
// try {
if (typeof p2wdbHash !== 'string' || !p2wdbHash) {
throw new Error('p2wdbHash must be a string')
}
const offer = await this.OfferModel.findOne({ p2wdbHash })
if (!offer) {
throw new Error('offer not found')
}
return offer
// const offerObject = offer.toObject()
// return this.offerEntity.validateFromModel(offerObject)
// return offerObject
// } catch (err) {
// // console.error('Error in findOffer(): ', err)
// throw err
// }
}
// This function is called by the P2WDB webhook REST API handler. When a
@@ -261,8 +452,14 @@ class OfferUseCases {
// See if this instance of bch-dex is managing the Order associated with
// the incoming Counter Offer.
const orderHash = p2wdbData.data.offerHash
const orderData = await this.orderUseCase.findOrderByHash(orderHash)
console.log(`orderData: ${JSON.stringify(orderData, null, 2)}`)
let orderData = {}
try {
orderData = await this.orderUseCase.findOrderByHash(orderHash)
console.log(`orderData: ${JSON.stringify(orderData, null, 2)}`)
} catch (err) {
console.log('Order matching this Counter Offer is not managed by this instance of bch-dex. Exiting.')
return 'N/A'
}
// Deserialize the partially signed transaction.
const txHex = p2wdbData.data.partialTxHex
@@ -319,33 +516,82 @@ class OfferUseCases {
let utxoStatus = null
try {
// Get the status of the UTXO associate with this Offer.
utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
thisOffer.utxoTxid,
thisOffer.utxoVout
)
// utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
// thisOffer.utxoTxid,
// thisOffer.utxoVout
// )
// Get the status of the UTXO associate with this Offer.
const utxo = {
tx_hash: thisOffer.utxoTxid,
tx_pos: thisOffer.utxoVout
}
// console.log(`Checking this UTXO: ${JSON.stringify(utxo, null, 2)}`)
utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo)
// console.log('utxoStatus: ', utxoStatus)
} catch (err) {
// Handle corner case of bad-data in the Offer model.
if (err.message.includes('txid needs to be a proper transaction ID')) {
if (err.message && err.message.includes('txid needs to be a proper transaction ID')) {
console.log(`Deleting Offer with bad data: ${JSON.stringify(thisOffer, null, 2)}`)
await thisOffer.remove()
continue
} else if (err.isAxiosError) {
console.log('Error trying to contact wallet service: ', err)
continue
} else {
throw err
}
}
// If the Offer UTXO is spent, delete the Offer model.
if (utxoStatus === null) {
if (!utxoStatus) {
console.log(`Spent UTXO detected. Deleting this Offer: ${JSON.stringify(thisOffer, null, 2)}`)
await thisOffer.remove()
}
// If the Offer is older than 7 days, delete it.
const nowMs = now.getTime()
const eightWeeks = 1000 * 60 * 60 * 24 * 7 * 8
const eightWeeksAgo = nowMs - eightWeeks
if (thisOffer.timestamp < eightWeeksAgo) {
console.log('Offer older than 8 weeks. Deleting.')
await thisOffer.remove()
}
}
} catch (err) {
console.error('Error in removeStaleOffers()')
console.error('Error in removeStaleOffers(): ', err)
throw err
}
}
async flagOffer (flagData) {
console.log(`flagData: ${JSON.stringify(flagData, null, 2)}`)
const p2wdbHash = flagData.data.p2wdbHash
// Get the offer from the database.
const offer = await this.findOfferByHash(p2wdbHash)
console.log(`Flagging this offer: ${JSON.stringify(offer, null, 2)}`)
if (!offer) {
throw new Error(`Offer ${p2wdbHash} not found in the database.`)
}
// Add the raw flag data to the database model.
offer.flags.push(flagData)
// If flag count is 3 or more, mark the Offer as NSFW
const flagCnt = offer.flags.length
if (flagCnt >= 3) {
offer.nsfw = true
}
// Save the updated offer data to the database.
await offer.save()
return true
}
}
module.exports = OfferUseCases
export default OfferUseCases
+4 -3
View File
@@ -9,8 +9,9 @@
pay-to-write-access-controller.js depends on this library.
*/
const PQueue = require('p-queue').default
const pRetry = require('p-retry')
// Global npm libraries
import PQueue from 'p-queue'
import pRetry from 'p-retry'
let _this
@@ -103,4 +104,4 @@ class RetryQueue {
}
}
module.exports = RetryQueue
export default RetryQueue
+41 -15
View File
@@ -3,9 +3,10 @@
*/
// Local libraries
const { wlogger } = require('../adapters/wlogger')
const OrderEntity = require('../entities/order')
const config = require('../../config')
import wlogger from '../adapters/wlogger.js'
import OrderEntity from '../entities/order.js'
import config from '../../config/index.js'
class OrderLib {
constructor (localConfig = {}) {
@@ -28,17 +29,24 @@ class OrderLib {
async createOrder (entryObj) {
try {
console.log('createOrder(entryObj): ', entryObj)
if (!entryObj) return false
if (!entryObj.tokenId) throw new Error('entry does not contain required properties')
// Specify the address to send payment.
entryObj.makerAddr = this.adapters.wallet.bchWallet.walletInfo.cashAddress
console.log('entryObj.makerAddr: ', entryObj.makerAddr)
// Get Ticker for token ID.
// TODO: Move this below the orderEntity.validate() call.
const tokenData = await this.adapters.wallet.bchWallet.getTxData([entryObj.tokenId])
// console.log(`tokenData: ${JSON.stringify(tokenData, null, 2)}`)
entryObj.ticker = tokenData[0].tokenTicker
// Input Validation
// TODO: Remove ticker from validation.
// TODO: Rename validate() to inputValidate(). Create fullValidate() that
// validates a fully hydrated Order entity.
const orderEntity = this.orderEntity.validate(entryObj)
console.log('orderEntity: ', orderEntity)
@@ -60,6 +68,7 @@ class OrderLib {
// Update the order with the new UTXO information.
orderEntity.utxoTxid = utxoInfo.txid
orderEntity.utxoVout = utxoInfo.vout
orderEntity.tokenType = utxoInfo.tokenType
// Add P2WDB specific flag for signaling that this is a new offer.
orderEntity.dataType = 'offer'
@@ -76,6 +85,7 @@ class OrderLib {
// Create a MongoDB model to hold the Order
orderEntity.hdIndex = utxoInfo.hdIndex
orderEntity.p2wdbHash = hash
console.log(`creating new order model: ${JSON.stringify(orderEntity, null, 2)}`)
const order = new this.OrderModel(orderEntity)
await order.save()
@@ -83,7 +93,7 @@ class OrderLib {
return hash
} catch (err) {
// console.log("Error in use-cases/entry.js/createEntry()", err.message)
wlogger.error('Error in use-cases/createOrder())')
wlogger.error('Error in use-cases/order.js/createOrder())')
console.log('error entryObj: ', entryObj)
throw err
}
@@ -96,6 +106,9 @@ class OrderLib {
// console.log('this.adapters.wallet: ', this.adapters.wallet.bchWallet)
// console.log(`walletInfo: ${JSON.stringify(this.adapters.wallet.bchWallet.walletInfo, null, 2)}`)
// Update the wallet balance
await this.adapters.wallet.bchWallet.getUtxos()
// Ensure the app wallet has enough funds to write to the P2WDB.
const wif = this.adapters.wallet.bchWallet.walletInfo.privateKey
const canWriteToP2WDB = await this.adapters.p2wdb.checkForSufficientFunds(wif)
@@ -108,11 +121,14 @@ class OrderLib {
if (orderEntity.buyOrSell.includes('sell')) {
// Sell Order
// Combine Fungible and NFT token UTXOs.
let tokenUtxos = utxos.slpUtxos.type1.tokens.concat(utxos.slpUtxos.nft.tokens)
// Get token UTXOs that match the token in the order.
const tokenUtxos = utxos.slpUtxos.type1.tokens.filter(
tokenUtxos = tokenUtxos.filter(
x => x.tokenId === orderEntity.tokenId
)
// console.log('tokenUtxos: ', tokenUtxos)
console.log('tokenUtxos: ', tokenUtxos)
// Get the total amount of tokens in the wallet that match the token
// in the order.
@@ -122,7 +138,7 @@ class OrderLib {
// If there are fewer tokens in the wallet than what's in the order,
// throw an error.
if (totalTokenBalance <= orderEntity.numTokens || isNaN(totalTokenBalance)) {
if (totalTokenBalance < orderEntity.numTokens || isNaN(totalTokenBalance)) {
throw new Error(
'App wallet does not have enough tokens to satisfy the SELL order.'
)
@@ -159,7 +175,7 @@ class OrderLib {
return orderObject
} catch (err) {
console.error('Error in findOrder(): ', err)
console.error('Error in findOrder()')
throw err
}
}
@@ -183,24 +199,34 @@ class OrderLib {
let utxoStatus = null
try {
// Get the status of the UTXO associate with this Order.
utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
thisOrder.utxoTxid,
thisOrder.utxoVout
)
// utxoStatus = await this.adapters.bchjs.Blockchain.getTxOut(
// thisOrder.utxoTxid,
// thisOrder.utxoVout
// )
// Get the status of the UTXO associate with this Order.
const utxo = {
tx_hash: thisOrder.utxoTxid,
tx_pos: thisOrder.utxoVout
}
utxoStatus = await this.adapters.wallet.bchWallet.utxoIsValid(utxo)
// console.log('utxoStatus: ', utxoStatus)
} catch (err) {
// Handle corner case of bad-data in the Order model.
if (err.message.includes('txid needs to be a proper transaction ID')) {
if (err.message && err.message.includes('txid needs to be a proper transaction ID')) {
console.log(`Deleting Order with bad data: ${JSON.stringify(thisOrder, null, 2)}`)
await thisOrder.remove()
continue
} else if (err.isAxiosError) {
console.log('Error trying to contact wallet service: ', err)
continue
} else {
throw err
}
}
// If the Order UTXO is spent, delete the Order model.
if (utxoStatus === null) {
if (!utxoStatus) {
console.log(`Spent UTXO detected. Deleting this Order: ${JSON.stringify(thisOrder, null, 2)}`)
await thisOrder.remove()
}
@@ -212,4 +238,4 @@ class OrderLib {
}
}
module.exports = OrderLib
export default OrderLib
+4 -3
View File
@@ -3,8 +3,9 @@
functions are called by the /user REST API endpoints.
*/
const UserEntity = require('../entities/user')
const { wlogger } = require('../adapters/wlogger')
import UserEntity from '../entities/user.js'
import wlogger from '../adapters/wlogger.js'
class UserLib {
constructor (localConfig = {}) {
@@ -181,4 +182,4 @@ class UserLib {
}
}
module.exports = UserLib
export default UserLib
+10 -6
View File
@@ -5,14 +5,18 @@
*/
// Public npm libraries
const assert = require('chai').assert
const axios = require('axios').default
import { assert } from 'chai'
import axios from 'axios'
// const sinon = require('sinon')
// Local support libraries
const config = require('../../../config')
const Server = require('../../../bin/server')
const testUtils = require('../../utils/test-utils')
const AdminLib = require('../../../src/adapters/admin')
import config from '../../../config/index.js'
import Server from '../../../bin/server.js'
import testUtils from '../../utils/test-utils.js'
import AdminLib from '../../../src/adapters/admin.js'
const adminLib = new AdminLib()
// const request = supertest.agent(app.listen())
+10 -14
View File
@@ -1,20 +1,19 @@
const testUtils = require('../../utils/test-utils')
const assert = require('chai').assert
const config = require('../../../config')
const axios = require('axios').default
const sinon = require('sinon')
import testUtils from '../../utils/test-utils.js'
import { assert } from 'chai'
import config from '../../../config/index.js'
import axios from 'axios'
import sinon from 'sinon'
import util from 'util'
const util = require('util')
import UserController from '../../../src/controllers/rest-api/users/controller.js'
import Adapters from '../../../src/adapters/index.js'
import UseCases from '../../../src/use-cases/index.js'
util.inspect.defaultOptions = { depth: 1 }
const LOCALHOST = `http://localhost:${config.port}`
const context = {}
const UserController = require('../../../src/controllers/rest-api/users/controller')
const Adapters = require('../../../src/adapters')
const adapters = new Adapters()
const UseCases = require('../../../src/use-cases/')
let uut
let sandbox
@@ -39,7 +38,7 @@ describe('Users', () => {
// Get the JWT used to log in as the admin 'system' user.
const adminJWT = await testUtils.getAdminJWT()
// console.log(`adminJWT: ${admi nJWT}`)
console.log(`adminJWT: ${adminJWT}`)
context.adminJWT = adminJWT
// const admin = await testUtils.loginAdminUser()
@@ -71,9 +70,6 @@ describe('Users', () => {
await axios(options)
/* console.log(
`result stringified: ${JSON.stringify(result.data, null, 2)}`
) */
assert(false, 'Unexpected result')
} catch (err) {
assert(err.response.status === 422, 'Error code 422 expected.')
+7 -7
View File
@@ -1,15 +1,15 @@
const config = require('../../../config')
const axios = require('axios').default
const assert = require('chai').assert
const sinon = require('sinon')
import config from '../../../config/index.js'
import axios from 'axios'
import { assert } from 'chai'
import sinon from 'sinon'
import { context as mockContext } from '../../unit/mocks/ctx-mock.js'
import ContactController from '../../../src/controllers/rest-api/contact/controller.js'
// Mock data
// const mockData = require('./mocks/contact-mocks')
const LOCALHOST = `http://localhost:${config.port}`
const mockContext = require('../../unit/mocks/ctx-mock').context
const ContactController = require('../../../src/controllers/rest-api/contact/controller')
let uut
let sandbox
+7 -9
View File
@@ -1,17 +1,15 @@
const config = require('../../../config')
const assert = require('chai').assert
import config from '../../../config/index.js'
import { assert } from 'chai'
import axios from 'axios'
import sinon from 'sinon'
import util from 'util'
const axios = require('axios').default
const sinon = require('sinon')
const util = require('util')
import LogsController from '../../../src/controllers/rest-api/logs/controller.js'
import { context as mockContext } from '../../unit/mocks/ctx-mock.js'
util.inspect.defaultOptions = { depth: 1 }
const LOCALHOST = `http://localhost:${config.port}`
const LogsController = require('../../../src/controllers/rest-api/logs/controller')
const mockContext = require('../../unit/mocks/ctx-mock').context
let sandbox
let uut
describe('LogsApi', () => {
@@ -1,12 +1,10 @@
const assert = require('chai').assert
const testUtils = require('../../utils/test-utils')
const Validators = require('../../../src/controllers/rest-api/middleware/validators')
const sinon = require('sinon')
const mockContext = require('../../unit/mocks/ctx-mock').context
const util = require('util')
/*
import { assert } from 'chai';
import testUtils from '../../utils/test-utils.js';
import Validators from '../../../src/controllers/rest-api/middleware/validators.js';
import sinon from 'sinon';
import { context as mockContext } from '../../unit/mocks/ctx-mock.js';
import util from 'util';
util.inspect.defaultOptions = { depth: 1 }
const context = {}
@@ -303,3 +301,4 @@ describe('Validators', () => {
})
})
})
*/
+4 -7
View File
@@ -1,10 +1,7 @@
const assert = require('chai').assert
const Admin = require('../../../src/adapters/admin')
const sinon = require('sinon')
const util = require('util')
import { assert } from 'chai'
import Admin from '../../../src/adapters/admin.js'
import sinon from 'sinon'
import util from 'util'
util.inspect.defaultOptions = { depth: 1 }
let sandbox
+1 -1
View File
@@ -6,7 +6,7 @@
// const assert = require('chai').assert
// const axios = require('axios').default
const sinon = require('sinon')
import sinon from 'sinon'
// const LOCALHOST = `http://localhost:${config.port}`
+1 -1
View File
@@ -5,7 +5,7 @@
Ensure the REST API is up an running before running this test.
*/
const axios = require('axios')
import axios from 'axios'
const LOCALHOST = 'http://localhost:5700'
+1 -1
View File
@@ -2,7 +2,7 @@
Part 2 of 3: Take an offer by submiting a counter-offer.
*/
const axios = require('axios')
import axios from 'axios'
const LOCALHOST = 'http://localhost:5700'
@@ -10,10 +10,10 @@
*/
// Public npm libraries
const BCHJS = require('@psf/bch-js')
import BCHJS from '@psf/bch-js'
// Local libraries
const P2wdbAdapter = require('../../../src/adapters/p2wdb-adapter')
import P2wdbAdapter from '../../../src/adapters/p2wdb-adapter'
const wif = process.env.WIF
if (!wif) {

Some files were not shown because too many files have changed in this diff Show More