Git Product home page Git Product logo

dshop's Introduction

Origin Protocol

A decentralized e-commerce store served entirely from IPFS.

Repo structure

  • shop: front-end code
  • backend: server code
  • packages: utility packages
  • scripts: development helper scripts

Documentation

Deploy to Heroku

Deploy

Notes

  • The release branch will be deployed to Heroku
  • The release branch is far behind master and has some known issues. Help wanted from the community to help fixing this!

dshop's People

Contributors

cipherzzz avatar danielvf avatar etnlbck avatar franckc avatar github-actions[bot] avatar iam-hussain avatar micahalcorn avatar mikeshultz avatar nathanjessen avatar nick avatar nouex avatar phyninja avatar rembrandtreyes avatar renovate-bot avatar renovate[bot] avatar shahthepro avatar theprivileges avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dshop's Issues

Accounting

We should have a way to break down profit per order, taking into account Printful printing costs and Stripe fees. This should be presented in the admin, possibly downloadable by CSV, aggregated by order / day / week / month.

Discount code validation / data

Most of the discount code functionality hasn't yet been implemented:

  • Start date
  • End date
  • Max uses
  • 1 per customer

(Max uses and 1 per customer are commented out in the UI).

Also the '# used' on the list of discount codes is currently always 0.

Internal deployer: access to store admin panels for Origin employees

During the store creation process, we (Origin employees) should be able to create accounts for us to access the admin panel of every store that we deploy, for example store.brave.com/#/admin and store.solana.com/#/admin, in order to have oversight of the store's activities.

Replace web3 with ether.js

Ether.js is arguably much better than web3: the API is cleaner and leaner. You can define the ABI inline, etc...

I'd vote for us to completely deprecate our usage of web3 and to only use ether.js, both on the fron-end dand bakc-end.

Internal deployer: basic store setup

When deploying a store for a merchant, I need to be able to do the following for them:

  • add a custom domain or use a default dshop domain (if we have one)
  • add/edit store name
  • add/edit store favicon
  • add/edit store logo
  • add/edit the message that goes where it says “100% of all sales…” at the top right hand of the Stay At Home shop

Add private IPFS node to Dshop container

We need to be able to sync data to the DSHOP_CACHE from IPFS. Can probably restrict the daemon to only connect to a few peers to limit unnecessary traffic, eg the Origin IPFS server + Pinata

Could either use a separate go-ipfs process, or us js-ipfs in the backend process itself (which we already have as a dependency)

Super-admin: custom domain setup

The self service super-admin needs to allow for custom domain setup. Right now there is a script for CloudFlare API - we need the GCP equivalent, for which we can use Google DNS API.

Deployer: creating a 2nd shop fails

When trying to create another shop after having successfully created a first one, the 2nd shop creation gets stuck on the "Continue" button. The console shows the /shop api responds with the following: 200 {"success":true,"gateway":"https://ipfs-prod.ogn.app"}

Internal deployer: set up supported payment methods

Origin employees should be able to choose which payment methods merchants want to support (e.g. OGN, CC, or additional methods like FIL when we integrate them in future), and help merchants set up the ways they want to receive funds (e.g. which wallet address should OGN payments go to). There should also be a way for us and the merchant to edit these preferences.

Store Stripe webhook data

We should store data from Stripe webhook so we know, for example, exactly when a CC payment was made and what fees were charged. I already created a model in backend/models/external_payment.js - we just need to populate it

Internal deployer: option to accept donations

When I'm deploying a store for a merchant, I would need to be able to select the option for the merchant to accept or to not accept donations. The merchant and I should also be able to edit these preferences later on.

Internal deployer: sync dshop with Printful

The Origin employee deploying a dshop should be able to easily sync with the store created on Printful and import all products, categories, prices, variants etc. Should any further changes be made on Printful (e.g. new products added), there should be a way to re-sync the store to reflect the latest changes.

Refund Stripe payments

We need to be able to issue refunds to customers who cancel orders via the Admin, as well as see the current status of the payment (ie whether it was already refunded).

Store shop's private key server side and use it for marketplace listing creation/updates

Currently when setting up a shop the super-admin has to use their web wallet (ex: metamask) to create a listing on the marketplace contract. Later, when the shop admin wants to export the shop's product data to BigQuery, they also have to use their web wallet to issue a "ListingUpdated" event on the blockchain.

We'd like to change that so that during the store setup, we prompt the super-admin for the shop's private key and store it in the encrypted configs in the DB. The back-end can then use the priv key to send transactions to the marketplace contract for listing creation and update.

Note that the back-end will then store two private keys:

  1. shop private key, used for listing creation, listing updates
  2. buyer private key, used for creating offers on the marketplace for credit card payments

Internal deployer: create admin account for merchants

During the store creation process, we (Origin employees) should be able to create an account for the merchant to access the admin panel of their store so that they can track order history etc.

The merchant should have the option to reset their password in order to feel more secure.

Shop View link error

Using the 'View' link on the super-admin shops page breaks super-admin session.

sessionStorage.dataDir = shop.authToken
window.open(location.origin)

This seems to have broken the loaded super-admin config and attempts to load the API from 0.0.0.0:3000. Not sure if this is from network being broken. The shop config loads and appears correct, though I'm not sure why we're changing the entire super-admin session to begin with instead of just linking to the domain or IPFS hash?

Undefining sessionStorage.dataDir returns the session to normal.

Internal deployer: Add/edit social media links

When deploying a store for a merchant, we need to be able to add their social media links and also edit them if needed.

  1. I should be able to choose which social media links I want to add (Facebook, Twitter, YouTube, Instagram, Medium)
  2. The social media icons should show up below the sidebar on the left, and take me to the respective pages when I click on them
  3. I should be able to add/remove social media platforms I want to link to, and also edit the links

Shop deployment, move IPFS priming to queue

Consider moving the IPFS priming to a queue so the shop deployment API isn't waiting on IPFS propagation. In an ideal world, it shouldn't be an issue, but it cold take a couple minutes in certain situations.

Decouple Affiliates from Origin Rewards

Currently on Stay At Home shop, users are required to have an Origin Rewards account to become an Affiliate.

We should remove this requirement for all other shops moving forward.

For now we can just collect the user's full name, email address and a wallet address, which we will use for commission payouts.

Rename "authTokens" throughout code

Auth tokens are actually just a shop identifier, used so that the code can know which shop web actions are for. They aren't secret, and are not used for authentication.

Two open questions for @nick. What do we call its replacement? And you had mentioned including it in the the URL instead. Does this means that all backend urls would be in the form of /myshop/auth/login?

Error serving static content

Seen when loading super admin:

TypeError: Cannot read property 'length' of null
    at SendStream.hasTrailingSlash (/app/node_modules/send/index.js:304:30)
    at SendStream.pipe (/app/node_modules/send/index.js:590:34)
    at serveStatic (/app/node_modules/serve-static/index.js:125:12)
    at app.get (/app/backend/app.js:140:19)
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    at next (/app/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/app/node_modules/express/lib/router/route.js:112:3)
    at Layer.handle [as handle_request] (/app/node_modules/express/lib/router/layer.js:95:5)
    at /app/node_modules/express/lib/router/index.js:281:22
    at param (/app/node_modules/express/lib/router/index.js:354:14)
    at param (/app/node_modules/express/lib/router/index.js:365:14)
    at Function.process_params (/app/node_modules/express/lib/router/index.js:410:3)
    at next (/app/node_modules/express/lib/router/index.js:275:10)
    at SendStream.error (/app/node_modules/serve-static/index.js:121:7)
    at SendStream.emit (events.js:198:13)
    at SendStream.EventEmitter.emit (domain.js:448:20)
    at SendStream.error (/app/node_modules/send/index.js:270:17)
    at SendStream.onStatError (/app/node_modules/send/index.js:421:12)
    at onstat (/app/node_modules/send/index.js:726:26)
    at FSReqWrap.oncomplete (fs.js:153:21)

Add admin functionality to accept and finalize crypto offers

Currently when a buyer pays in crypto, we have to accept the offer using shoporigin.com.

We should have functionality under the dshop admin to accept those offers.
This would call the marketplace contract and release the funds that were held in escrow.

Error attempting to make Stripe payment using IPFS through Brave

Submitted by Protocol Labs:

When attempting to complete a purchase through the Brave Swag store at roughly 2200EST 21APR2020 while accessing it through a local IPFS node using the IPFS Companion, it errored when attempting to complete the payment. I was attempting to make a ~$6 purchase using a Mastercard CC shipping to a valid US address.

Brave Desktop (Mac) v 1.5.123
go-ipfs v 0.4.23
IPFS Companion v 2.11.0

Initial Guess:

Could be that Stripe.js doesn't like that the live connection doesn't appear to be over HTTPS. The Security tab reports: "This page has a non-HTTPS secure origin"

URI:

http://localhost:8080/ipns/store.brave.com/#/order/QmNX3pv55134tQnatD6KD7ueKfdpKNVDbDCf52p9wqTEbL?auth=2c2dd03bljc61fc3rg911p05w6449dj

Console Log:

DomDistiller debug level: 0
0.da54ef82.bundle.js:121 Invalid asm.js: Unexpected token
(index):1 You may test your Stripe.js integration over HTTP. However, live Stripe.js integrations must use HTTPS.
value @ (index):1
5.da54ef82.bundle.js:1 Make Stripe payment request...
(index):1 You may test your Stripe.js integration over HTTP. However, live Stripe.js integrations must use HTTPS.
value @ (index):1
inpage.js:1 Heads up! ethereum._metamask exposes methods that have not been standardized yet. This means that these methods may not be implemented in other dapp browsers and may be removed from MetaMask in the future.
get @ inpage.js:1
5.da54ef82.bundle.js:1 Make Stripe payment request...

Snapshot:
Screen Shot 2020-04-21 at 10 24 45 PM

Internal deployer: edit About page

When deploying a store for a merchant, I (or other origin employees) would want to be able to edit the About page according to the merchant's requirements.

I should be able to add text and links to other websites to this About page.

Backend error when fetching config

Seen when trying to checkout with crypto:

{ FetchError: request to https://single-product/single-product/config.json failed, reason: getaddrinfo ENOTFOUND single-product single-product:443
    at ClientRequest.<anonymous> (/app/node_modules/node-fetch/lib/index.js:1455:11)
    at ClientRequest.emit (events.js:198:13)
    at ClientRequest.EventEmitter.emit (domain.js:448:20)
    at TLSSocket.socketErrorListener (_http_client.js:401:9)
    at TLSSocket.emit (events.js:198:13)
    at TLSSocket.EventEmitter.emit (domain.js:448:20)
    at emitErrorNT (internal/streams/destroy.js:91:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
    at process._tickCallback (internal/process/next_tick.js:63:19)
  message:
   'request to https://single-product/single-product/config.json failed, reason: getaddrinfo ENOTFOUND single-product single-product:443',
  type: 'system',
  errno: 'ENOTFOUND',
  code: 'ENOTFOUND' }

Shop was created & configured with the super-admin. Domain should have been single-product.example.com

Tertiary IPFS cluster node deployment

Create an easy-deploy script for setting up tertiary nodes for our IFPS cluster. Allow us (or others) to standup cheap VMs anywhere and join our cluster (at least as a follower) to replicate our pins.

This also needs to be tested, in general.

Ref: #50

Improve back-end resilience by using queues

We should add a DB backed queue for listener tasks that are business critical. In particular for the following:

  • creation of offers for credit card payments.
  • acceptance of offers

The queueing framework should be relatively generic so that we can use it for any type of tasks in the future.

Automatically send orders to Printful

Right now, Printful API requests are sent manually via a button on the admin page. This should happen automatically, once some basic validation has passed.

  • Listener watches for OrderCreated event
  • Order is validated to check items exist and are correctly priced, discount code is valid, etc
  • Order is sent to Printful via API (via Queue)
  • Any errors in the API call to Printful are sent as an email alert

Record order in the DB prior to submitting it to the blockchain

Currently the order flow is as follow:

  1. Front-end creates the offer data in IPFS
  2. Front-end calls the back-end to record the order
  3. Back-end enqueues a task in the queue for processing the order
  4. Back-end queue processor picks up the task and calls the markeplace contract to record an offer on-chain
  5. Listen receives the OfferCreated event, records the order in the orders table and sends notifications (email to the user, post on discord)

In the eventuality that either the tx fails getting mined (step 4) or that the listener does not get the event (step 5), the order would not get fulfilled.

The proposal is to record the data in the DB in step 2 so that we can:

  • have alerts in case an order does not get fulfilled
  • in case of failure, we'll have the data and can re-process the order

This would involve using a different id for rows in the orders table since currently we use the offerId which is only available after the tx is mined. An idea would be to use as a replacement <listing_id>-<offer_ipfs_hash> since that is available right after step 1.

Store shop's IPFS hash in the DB

Currently when the super admin deploys a store, we don't record the IPFS hash of the deployed store in the DB.

It would be convenient to have this information. For example:

  • To show it in the admin UI
  • For internal server operations, such as verifying an offer coming from the front-end against the products metadata stored in IPFS (ex: price, product ids, etc...) - See #17
  • To keep track of what version of the code a shop is running
  • Others?

In terms of implementation, we could add a new column "ipfs_hash" to the existing "shops" DB table. Alternatively, if we want to keep track of older versions of the shop that were published, we could create a new DB table "shops_ipfs" with each row storing a hash and a shop_id (e.g. 1 to many relationship between a row in "shops" and rows in "shops_ipfs").

"Your order has shipped"

Printful have a webhook api (and simulator) which we should leverage in order to send customers shipping tracking numbers when they become available.

This should be pretty much the same as the receipt email that is sent to customers, but with the following text at the top. We can keep the order summary.

Your order has shipped!

Hi Nick,

Just letting you know that your order #1-001-123-456 has been sent out!

Here's the tracking number:

920019025601923479127
USPS First Class Mail

Note: Tracking information can take up to 48 hours to be updated after the order is shipped.

Thanks,

The Origin Swag Team

Create IPFS cluster

Create a standalone IPFS cluster.

  • Primarily for dshop but with pins from previous node for added redundancy
  • multi-region
  • probably with ipfs-cluster

Questions

Questions I'd like to answer along the way...

  • What ops/orchestration/config management to use for distributed cluster?
  • will still need a gateway, with cert issuer, perhaps regional? does let's encrypt offer cert management for multiple nodes yet?
  • Dshop uses API, how will that be available now? Can we add pins without? ipfs-cluster ACLs?
  • Consider how might "nodes" fit within this cluster? Follower? Can these nodes add pins to the cluster?

Ref #31

Add server side check on offers

Currently the back-end does not perform any check to validate the offer data it receives before processing it.

We should add some checks on metadata such as

  • ID of the product
  • price

Purchasing hangs for 35 seconds, then crashes

Somehow, I still have no origin swag. And I needed a good t-shirt. So I went to the Origin Swag Store to order one, and things crashed and burned when placing the order. 🔥 🚗

What happened:

  • Picked out a shirt, added to cart, filled in my info, shipping, and payment info.
  • Clicking the payment button seemed to "hang" for a tiny bit. Nothing happened on the page for too long. I was going to make a bug report that we should add some kind of display that processing is happening in the background after the button click.
  • After too long, the whole page changed to what I think was a white page with "loading" displayed
  • Then it eventually crashed to a white page with nothing on it.

image

I still could use another T-shirt. Here goes another order with and open network tab and full profiling running. Results:

  • After clicking the "Pay $20.00" button, the button color changed slightly about 25ms later.
  • It did crypto stuff for about 250ms. (no screen change)
  • It took 2000ms to post to our IPFS. We've got something wrong there then. (no screen change)
  • It took 612ms to pay at swag.ogn.app
  • 2700ms for confirm at api.stripe.com
  • Roughly five and a half seconds after clicking "pay", the screen changed to a "Loading" page.
  • This loading page lasted 30 seconds! It was attempting to load https://originswag.eth.link/dist/4.0f591475.bundle.js
  • I actually got my purchase order email while the screen still said "loading"
  • That bundle request failed. This white screened the app.

Issues:

  • Posting to IPFS is taking way too long
  • We need a better progress view after clicking "Pay". Even a second is too long to wait without some kind of spinner thing.
  • Requesting https://originswag.eth.link/dist/4.0f591475.bundle.js is broken. I can't get that file.
  • Why do we go to a "loading" screen after purchase, anyway?

Investigate sketchy IPFS behavior when DNS first updated

When I first update DNS records, IPFS can't only intermittently find content for a few minutes. Refreshing the page multiple times can result in any one of the following:

  • ipfs resolve -r /ipns/minds.ogn.app/: could not resolve name
  • 404 page not found
  • Actual content

Here's a video of me pressing refresh dozens of times. (Blank page means it served HTML correctly)

ezgif com-video-to-gif

Recommend Projects

  • React photo React

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

  • Vue.js photo Vue.js

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

  • Typescript photo Typescript

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

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

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

Recommend Topics

  • javascript

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

  • web

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

  • server

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

  • Machine learning

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

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

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

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.