working prototype and updated README
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# Overview
|
||||
|
||||
httXrp is a proof of concept for a truly serverless web architecture. If serverless simply means "a server owned by someone else", httXrp pushes that definition to its limit.
|
||||
httXrp is a proof of concept for a truly serverless web architecture. If serverless 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?
|
||||
|
||||
# How it works
|
||||
|
||||
@@ -8,11 +8,11 @@ httXrp is a proof of concept for a truly serverless web architecture. If serverl
|
||||
|
||||
Transactions on the ripple blockchain are allowed to carry up to 1kB of arbitrary data via the memo field.
|
||||
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.
|
||||
In order to generate these transactions a library called [xrpio](https://gitea.nitowa.xyz/npm-packages/xrpio.git) is used.
|
||||
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.
|
||||
|
||||
Highly simplified, you can visualize the process like this:
|
||||
|
||||

|
||||
<img src="https://i.imgur.com/G2HofSE.gif" alt="xrpio" width="650"/>
|
||||
|
||||
## 2: Abstracting the webserver away from the web
|
||||
|
||||
@@ -20,11 +20,53 @@ Using tools like `webpack`, it is possible to condense even modern complex singl
|
||||
|
||||
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.
|
||||
|
||||

|
||||
<img src="https://i.imgur.com/Rwo37xJ.gif" alt="serverless web" width="650"/>
|
||||
|
||||
## 3: Dynamic web applications without a backend
|
||||
## 3: Backendless dynamic web applications: Databases without databases
|
||||
|
||||
Superficially, this technique is limited to serving static webpages, as there is no *real* backend serving these pages. However, since it is possible to embed `xrpio` into such a "static" page, it is possible to listen for transactions on the Ripple blockchain containing valid xrpio hashes and to dynamically update the webpage's content based on the stored data.
|
||||
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.
|
||||
|
||||
All necessary mechanisms can easily be embedded within that webpage, which allows us to build complex webapplications without any need for a backend server.
|
||||
|
||||
To prove the feasibility of this approach, this project contains a small example application in the form of a shoutbox:
|
||||
|
||||
<img src="https://i.imgur.com/5gYLuYc.png" alt="shoutbox" width="450"/>
|
||||
|
||||
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 `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.
|
||||
|
||||
### Submitting a new shout to the shoutbox
|
||||
```js
|
||||
//When submitting a new shout, first the user creates a xrpio write between two of their own wallets
|
||||
submitShout = async (shout: any) => {
|
||||
const shoutHash = await xrpio.treeWrite(shout, userWallet1.address, userWallet2.secret)
|
||||
return await submit(shoutHash)
|
||||
}
|
||||
|
||||
//After the shout has been written to the blockchain, the hash pointing to the data is sent to the address keeping track of the application's state
|
||||
submit = async (shoutHash: string) => {
|
||||
return await xrpio.writeRaw({ data: shoutHash }, shoutboxAddress, userWallet1.secret)
|
||||
}
|
||||
```
|
||||
|
||||
### Loading the application state and live updating it
|
||||
```js
|
||||
//Loading old data is as easy as parsing the historical transactions of the shoutboxAddress
|
||||
loadHistory = async () => {
|
||||
const raw_txs = await getTransactions(shoutboxAddress)
|
||||
//Extracts hashes from memos and reads them with xrpio
|
||||
const shouts = await parseMemos(raw_txs.map(getMemo))
|
||||
history = shouts
|
||||
}
|
||||
|
||||
//Fetching new data as it comes in is also possible by simply subscribing to new transactions for the shoutboxAddress
|
||||
listen = async () => {
|
||||
await subscribeTxs(async (raw_tx: any) => {
|
||||
//Extracts hashes from memos and reads them with xrpio
|
||||
const shout = await parseMemos(getMemo(raw_tx))
|
||||
history.push(shout)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
# Credits
|
||||
|
||||
|
||||
Reference in New Issue
Block a user