|
|
|
|
1
|
-# Overview
|
|
|
2
|
-
|
|
|
3
|
-httXrp is a proof of concept for a truly serverless web architecture. If cloud simply means "a server owned by someone else", httXrp pushes that definition to its limit -or- perhaps its logical conclusion: What if that "someone else" never even intended that server to be used that way but can't do anything about it?
|
|
|
4
|
-
|
|
|
5
|
-# How it works
|
|
|
6
|
-
|
|
|
7
|
-## 1: Getting data into and out of the blockchain
|
|
|
8
|
-
|
|
|
9
|
-Transactions on the ripple blockchain are allowed to carry up to 1kB of arbitrary data via the memo field.
|
|
|
10
|
-We can use this to store data of any size by building a tree of references between these transactions that can then be reassembled by reading them back from the blockchain.
|
|
|
11
|
-In order to generate these transactions a library called [xrpio](https://gitea.nitowa.xyz/npm-packages/xrpio.git) is used to send minimum-denomination transactions between two user controlled wallets.
|
|
|
12
|
-
|
|
|
13
|
-Highly simplified, you can visualize the process like this:
|
|
|
14
|
-
|
|
|
15
|
-<img src="https://i.imgur.com/G2HofSE.gif" alt="xrpio" width="800"/>
|
|
|
16
|
-
|
|
|
17
|
-## 2: Abstracting the webserver away from the web
|
|
|
18
|
-
|
|
|
19
|
-Using tools like `webpack`, it is possible to condense even modern complex single-page-applications into a single html file. As `xrpio` is written in JavaScript, it is even possible to embed it into such an HTML file, the use of which will become more clear a few paragraphs below.
|
|
|
20
|
-
|
|
|
21
|
-Since such a condensed HTML file is effectively nothing more than a long string it is possible to use `xrpio` to store them into the ripple blockchain and to retrieve them via a single identifying hash.
|
|
|
22
|
-
|
|
|
23
|
-<img src="https://i.imgur.com/Rwo37xJ.gif" alt="serverless web" width="650"/>
|
|
|
24
|
-
|
|
|
25
|
-## 3: Backendless dynamic web applications: Databases without databases
|
|
|
26
|
-
|
|
|
27
|
-Superficially, this technique is limited to serving static webpages, as there can be no backend communicating with these pages without betraying the serverless premise. However, since it is possible to embed `xrpio` into such a "static" page, it is possible to listen for transactions on the blockchain containing valid xrpio hashes and to dynamically update the webpage's content based on the stored data.
|
|
|
28
|
-
|
|
|
29
|
-All necessary mechanisms can easily be embedded within that webpage, which allows us to build complex webapplications without any need for a backend server.
|
|
|
30
|
-
|
|
|
31
|
-To prove the feasibility of this approach, this project contains a small example application in the form of a shoutbox:
|
|
|
32
|
-
|
|
|
33
|
-<img src="https://i.imgur.com/5gYLuYc.png" alt="shoutbox" width="450"/>
|
|
|
34
|
-
|
|
|
35
|
-The exact procedure is more easily explained in code than visually. The presented code snippets should be considered pseudocode, but if you're interested in the exact steps please take a look into [ShoutboxData.service.ts](https://gitea.nitowa.xyz/nitowa/httxrp/src/branch/master/src/frontend/src/app/services/ShoutboxData.service.ts). The actual implementation isn't any more complex than the steps below but they were altered for readability reasons.
|
|
|
36
|
-
|
|
|
37
|
-### Submitting a new shout to the shoutbox
|
|
|
38
|
-```js
|
|
|
39
|
-//When submitting a new shout, first the user creates a xrpio write between two of their own wallets
|
|
|
40
|
-submitShout = async (shout: any) => {
|
|
|
41
|
- const shoutHash = await xrpio.treeWrite(shout, userWallet1.address, userWallet2.secret)
|
|
|
42
|
- return await submit(shoutHash)
|
|
|
43
|
-}
|
|
|
44
|
-
|
|
|
45
|
-//After the shout has been written to the blockchain,
|
|
|
46
|
-//the hash pointing to the data is sent to the address keeping track of the application's state
|
|
|
47
|
-submit = async (shoutHash: string) => {
|
|
|
48
|
- return await xrpio.writeRaw({ data: shoutHash }, shoutboxAddress, userWallet1.secret)
|
|
|
49
|
-}
|
|
|
50
|
-```
|
|
|
51
|
-
|
|
|
52
|
-### Loading the application state and live updating it
|
|
|
53
|
-```js
|
|
|
54
|
-//Loading old data is as easy as parsing the historical transactions of the shoutboxAddress
|
|
|
55
|
-loadHistory = async () => {
|
|
|
56
|
- const raw_txs = await getTransactions(shoutboxAddress)
|
|
|
57
|
- //Extracts hashes from memos and reads them with xrpio
|
|
|
58
|
- const shouts = await parseMemos(raw_txs.map(getMemo))
|
|
|
59
|
- history = shouts
|
|
|
60
|
-}
|
|
|
61
|
-
|
|
|
62
|
-//Fetching new data as it comes in is also possible by simply subscribing to new transactions for the shoutboxAddress
|
|
|
63
|
-listen = async () => {
|
|
|
64
|
- await subscribeTxs(async (raw_tx: any) => {
|
|
|
65
|
- //Extracts hashes from memos and reads them with xrpio
|
|
|
66
|
- const shout = await parseMemos(getMemo(raw_tx))
|
|
|
67
|
- history.push(shout)
|
|
|
68
|
- })
|
|
|
69
|
-}
|
|
|
70
|
-```
|
|
|
71
|
-
|
|
|
72
|
-# Building the project
|
|
|
73
|
-
|
|
|
74
|
-Prerequisites:
|
|
|
75
|
-- NodeJS 17 (14 and up probably work, versions newer than 18 fail to build the Angular frontend)
|
|
|
76
|
-- npm
|
|
|
77
|
-
|
|
|
78
|
-Setup and build steps:
|
|
|
79
|
-- `npm i` in the project root
|
|
|
80
|
-- `cd src/frontend`
|
|
|
81
|
-- `npm i` again for the frontend build
|
|
|
82
|
-- `npm run start` in the project root. This will iteratively build the frontend, Deploy scripts, Deploy the frontend to the ripple blockchain and ultimately generate a gateway webpage under `gateway/index.html`.
|
|
|
83
|
-- Open `gateway/index.html` with a browser and you should see the shoutbox webpage after a short load.
|
|
|
84
|
-
|
|
|
85
|
-Troubleshooting:
|
|
|
86
|
-- If the project as been dormant for a while it is possible that the testnet wallets have been purged. In this case you have to repopulate the entries under [Configuration.ts](https://gitea.nitowa.xyz/nitowa/httxrp/src/branch/master/src/Configuration.ts) as well as the shoutboxAddress in [ShoutboxData.service.ts](https://gitea.nitowa.xyz/nitowa/httxrp/src/branch/master/src/frontend/src/app/services/ShoutboxData.service.ts) with fresh wallets. Funded testnet wallets can be generated via the [faucet](https://xrpl.org/xrp-testnet-faucet.html).
|
|
|
87
|
-
|
|
|
88
|
-# Credits
|
|
|
89
|
-
|
|
|
90
|
-- This project was originally inspired by indImm (https://ndm-inf.github.io/ndm/main), a ripple-based file storage using IPFS.
|
|
|
91
|
-- xrpio (https://gitea.nitowa.xyz/npm-packages/xrpio.git) is heavily used in the technical architecture of this project. It is also written and maintained by me.
|
|
|