3cities-open
Overview
3cities is a research product in web3 e-commerce by Ryan Berckmans.
Currently, 3cities is a checkout link generator similar to Stripe checkout links.
To use 3cities, a seller wishing to generate a checkout link (ie. sell something) goes through the flow, picks which tokens they are satisfied to receive in payment, and picks on which L2s they are satisfied to receive those tokens.
Demo
Please wait up to 1 minute for the demo link to load (it uses the cloudflare IPFS gateway, which is slow. I hear Web3.Storage is great)
Tech stack
- TypeScript (stragglers: why are you using pure JavaScript? Do you like moving slowly; needing expensive & unnecessary unit tests that could be replaced with reliable types; having avoidable runtime bugs; and only enabling the original authors understand the code very well?)
- React v18 (the new concurrent mode is a big deal if you’re using it correctly)
- Tailwindcss v3
- usedapp (see architectural note below)
Architectural note
3cities was built on usedapp. But imo, it should have been built on wagmi and rainbowkit. Some of 3cities’ plumbing (such as the token and chain lists) are already better supported on wagmi (in addition to other wonderful features and ergonomic apis in wagmi, and the fact that rainbowkit is terrific and requires wagmi), so it isn’t necessarily a quick swapping out of usedapp for wagmi within 3cities, rather the plumbing needs to be rebuilt to best leverage wagmi and rainbowkit’s data and functionality.
Novel features
- Checkout link details are stored only in the link itself. When a seller generates a checkout link, the complete details of that checkout are fully and only stored in the link itself, there’s no server or (centralized or decentralized) DB of checkout links. This creates privacy because the checkout details are known only to those who possess the link. As well, it allows us to use trad social media as offchain data availability because the checkout link details are stored eg. in the tweet where you post it, or in your Twitch profile.
- Automatically and dynamically detect the buyer’s tokens/chains, with 1-click checkout. 3cities lets a seller focus on (1) the tokens they’ll accept and (2) the L2s they’ll work with, and the software then automatically and dynamically discovers “payment methods” for the buyer’s connected wallet. For example, if a seller accepts (DAI, USDC) on (Arbitrum, Optimism), and the buyer connects a wallet that has only DAI on Arbitrum, 3cities will auto-detect this matching at runtime and suggest “Pay DAI on Arbitrum with 1-click”. 3cities contains hardcoded lists of supported tokens and chains, and supporting new tokens and chains is as easy as appending to these lists. The core algorithms for this “payment method strategy generation” are in strategies.ts.
- A react hook to have easy access to the wallet’s up-to-date token balances on all L2s in a single context object. 3cities contains a useful abstraction, data type, and associated algorithms/React contexts/hooks to provide the app with a react hook for an always-up-to-date snapshot of the token balances for the connected wallet for all supported tokens and all supported L2s in one single context object. The underlying data type is AddressContext. The core algorithms are in connectedWalletContextProvider.tsx. The API for the app code is the hook useConnectedWalletAddressContext (it’s in the same file connectedWalletContextProvider.tsx).
TODO: paying in ETH
3cities was designed to easily support automatic conversion of “Seller wants to get paid $100” into “Buyer 1-click checkout to pay $100 in ETH at the current spot price”. It would take only a bit of new code to support this. But, I didn’t add it. That’s why the buyer UX today never shows ETH as an option.
Below here was generated by create-eth-app
Project Structure
This project was bootstrapped with Create Eth App.
The default template is a monorepo created with Yarn Workspaces.
Workspaces makes it possible to setup multiple packages in such a way that we only need to run yarn install
once to install all of them in
a single pass. Dependencies are hoisted at the root.
my-eth-app
├── README.md
├── node_modules
├── package.json
├── .gitignore
└── packages
├── contracts
│ ├── README.json
│ ├── package.json
│ └── src
│ ├── abis
│ │ ├── erc20.json
│ │ └── ownable.json
│ ├── addresses.js
│ └── index.js
├── react-app
│ ├── README.md
│ ├── node_modules
│ ├── package.json
│ ├── public
│ │ ├── favicon.ico
│ │ ├── index.html
│ │ ├── logo192.png
│ │ ├── logo512.png
│ │ ├── manifest.json
│ │ └── robots.txt
│ └── src
│ ├── App.css
│ ├── App.js
│ ├── App.test.js
│ ├── ethereumLogo.svg
│ ├── index.css
│ ├── index.js
│ ├── serviceWorker.js
│ └── setupTests.js
└── subgraph
├── README.md
├── abis
│ └── erc20.json
├── package.json
├── schema.graphql
├── src
│ └── mappings
│ ├── tokens.ts
│ └── transfers.ts
└── subgraph.yaml
Owing to this dependency on Yarn Workspaces, Create Eth App can’t be used with npm.
Available Scripts
In the project directory, you can run:
React App
yarn react-app:start
Runs the React app in development mode.
Open http://localhost:3000 to view it in the browser.
The page will automatically reload if you make changes to the code.
You will see the build errors and lint warnings in the console.
yarn react-app:test
Runs the React test watcher in an interactive mode.
By default, runs tests related to files changed since the last commit.
Read more about testing React.
yarn react-app:build
Builds the React app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the React documentation on deployment for more information.
yarn react-app:eject
Note: this is a one-way operation. Once you react-app:eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration choices, you can eject
the React app at any time. This command will
remove the single build dependency from your React package.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right
into the react-app
package so you have full control over them. All of the commands except react-app:eject
will still work,
but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
You don’t have to ever use react-app:eject
. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
Subgraph
The Graph is a tool for for indexing events emitted on the Ethereum blockchain. It provides you with an easy-to-use GraphQL API.
To learn more, check out the The Graph documentation.
yarn subgraph:codegen
Generates AssemblyScript types for smart contract ABIs and the subgraph schema.
yarn subgraph:build
Compiles the subgraph to WebAssembly.
yarn subgraph:auth
Before deploying your subgraph, you need to sign up on the
Graph Explorer. There, you will be given an access token. Drop it in the command
below:
GRAPH_ACCESS_TOKEN=your-access-token-here yarn subgraph:auth
yarn subgraph:deploy
Deploys the subgraph to the official Graph Node.
Replace paulrberg/create-eth-app
in the package.json script with your subgraph’s name.
You may also want to read more about the hosted service.