Browse Source

Add README.md and LICENSE.md

master
nitowa 7 months ago
parent
commit
4317fd2bbb
5 changed files with 166 additions and 7 deletions
  1. 25
    0
      LICENSE.md
  2. 138
    1
      README.md
  3. 1
    1
      package.json
  4. 1
    2
      src/RJSVM/framework/rjsvm.ts
  5. 1
    3
      test/Test.ts

+ 25
- 0
LICENSE.md View File

@@ -0,0 +1,25 @@
1
+The MIT License (MIT)
2
+=====================
3
+
4
+Copyright © `2023` `nitowa`
5
+
6
+Permission is hereby granted, free of charge, to any person
7
+obtaining a copy of this software and associated documentation
8
+files (the “Software”), to deal in the Software without
9
+restriction, including without limitation the rights to use,
10
+copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+copies of the Software, and to permit persons to whom the
12
+Software is furnished to do so, subject to the following
13
+conditions:
14
+
15
+The above copyright notice and this permission notice shall be
16
+included in all copies or substantial portions of the Software.
17
+
18
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
19
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+OTHER DEALINGS IN THE SOFTWARE.

+ 138
- 1
README.md View File

@@ -1 +1,138 @@
1
-## The home of RJSVM, the Ripple JavaScript Virtual Machine
1
+# Overview 
2
+
3
+[![Current Version](https://img.shields.io/npm/v/rjsvm.svg)](https://www.npmjs.com/package/rjsvm)
4
+[![Weekly Downloads](https://img.shields.io/npm/dw/rjsvm?color=important)](https://www.npmjs.com/package/rjsvm)
5
+[![License Type](https://img.shields.io/npm/l/rjsvm?color=blueviolet)](https://gitea.nitowa.xyz/docs/rjsvm/src/branch/master/LICENSE.md)
6
+
7
+The Ripple JavaScript Virtual Machine, or RJSVM, aims to standardize and simplify the development of applications that employ the Ripple blockchain as state storage. Internally it employs [xrpIO](https://gitea.nitowa.xyz/npm-packages/xrpio) to read and write all necessary data.
8
+
9
+# How to install
10
+```
11
+npm i rjsvm
12
+```
13
+
14
+# How it works
15
+
16
+The JSVM package comes with two major parts: The RJSVM itself and the Datawriter. The former is used to define initial program state, callable endpoints, and the associated their associated logic. The Datawriter serves as the glue between users and a RJSVM. 
17
+
18
+Due to the blockchain's properties of providing persistent and absolutely ordered transactions every copy of a RJSVM will behave exactly identically.
19
+
20
+![rjsvm schema](https://imgur.com/Wpqp4yX.jpg)
21
+
22
+In order to provide a more robust environment and quasi-typesafe execution this package also requires [zod](https://www.npmjs.com/package/zod).
23
+
24
+# A basic example
25
+
26
+RJSVM
27
+```typescript
28
+import { RJSVM_Builder, RJSVM_Implementations, RJSVM_Interface, RJSVM, RJSVM_Config } from "rjsvm";
29
+import { z } from "zod";
30
+
31
+// Begin by defining the parameter type using Zod
32
+const blogpostSchema = z.object({
33
+    title: z.string(),
34
+    body: z.string(),
35
+    from: z.string(),
36
+})
37
+type Blogpost = z.infer<typeof blogpostSchema>
38
+
39
+// Define the shape of the state the RJSVM will manipulate
40
+type State = {
41
+    data: Blogpost[]
42
+}
43
+
44
+// Define the RJSVM endpoints
45
+type RJSVMEndpoints = {
46
+    submit: (data: Blogpost) => void
47
+    ownerSubmit: (data: Blogpost) => void
48
+    remove: (data: Blogpost) => void
49
+}
50
+
51
+// Define initial RJSVM state. The 'owner' and 'state' fields are both required.
52
+abstract class RJSVM_Base
53
+extends RJSVM<State, RJSVMEndpoints>
54
+implements RJSVM_Interface<RJSVM_Base> {
55
+    owner = ownerWallet.address
56
+
57
+    state: State = {
58
+        blogposts: []
59
+    }
60
+}
61
+
62
+// Implement the program logic
63
+const RJSVM_Contract: RJSVM_Implementations<RJSVM_Base> = {
64
+    // Endpoints may declare a minimum fee in order to be applied
65
+    submit: {
66
+        implementation: function (env, data) {
67
+            this.state.blogposts.unshift(data)
68
+        },
69
+        visibility: 'public',
70
+        fee: 10,
71
+        parameterSchema: blogpostSchema
72
+    },
73
+
74
+    // Endpoints can be owner-exclusive in order to grant free access
75
+    ownerSubmit: {
76
+        implementation: function (env, shout) {
77
+            this.state.blogposts.unshift(shout)
78
+        },
79
+        visibility: 'owner',
80
+        parameterSchema: blogpostSchema
81
+    },
82
+
83
+    // Owner-exclusive endpoints can also be used to implement protected functionality
84
+    remove: {
85
+        implementation: function (env, data) {
86
+            this.state.blogposts = this.state.blogposts.filter(post => post.title != post.title)
87
+        },
88
+        visibility: 'owner',
89
+        parameterSchema: blogpostSchema,
90
+    }
91
+}
92
+
93
+// Finally build and connect the RJSVM
94
+const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
95
+
96
+const conf: RJSVM_Config = {
97
+    listeningAddress: listeningWallet.address,          // The XRP address to check for endpoint calls
98
+    rippleNode: "wss://s.altnet.rippletest.net:51233"   // Any online XRP node connected to the right chain
99
+}
100
+
101
+const rjsvm = new Rjsvm(conf)
102
+rjsvm.connect()
103
+```
104
+
105
+Datawriter
106
+```typescript
107
+import { Datawriter } from "rjsvm";
108
+
109
+const datawriter = new Datawriter({
110
+    sendWallet: userWallet,                     // A wallet controlled by the user
111
+    receiveAddress: drainWallet.address,        // A secondary address controlled by the user
112
+    xrpNode: xrpNode,                           // Any online XRP node connected to the right chain
113
+    contractAddress: listeningWallet.address    // The XRP associated with the RJSVM
114
+})
115
+
116
+datawriter.callEndpoint('submit', { 
117
+    title: "My first blogpost", 
118
+    body: "Hello hello this is a blogpost!", 
119
+    from: "#1 RJSVM User in the world" 
120
+}, 10)
121
+// once the ripple blockchain persists the transaction, all copies of the RJSVM defined above will contain this blogpost
122
+
123
+datawriter.callEndpoint('submit', { 
124
+    title: "A underfunded blogpost", 
125
+    body: "Oh no this will never show up!", 
126
+    from: "#1 RJSVM User in the world" 
127
+})
128
+// Insufficient fee, the RJSVMs will not contain this blogpost. No refunds.
129
+
130
+datawriter.ownerSubmit('ownerSubmit', { 
131
+    title: "A underprivileged blogpost", 
132
+    body: "Oh no this will never show up!", 
133
+    from: "#1 RJSVM User in the world" 
134
+})
135
+// userWallet.address != ownerWallet.address, the RJSVMs will not contain this blogpost.
136
+```
137
+
138
+# [For a full list of examples please refer to the unit tests](https://gitea.nitowa.xyz/nitowa/RJSVM/src/branch/master/test/Test.ts)

+ 1
- 1
package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "rjsvm",
3
-  "version": "0.1.2",
3
+  "version": "0.2.0",
4 4
   "description": "",
5 5
   "main": "lib/main.js",
6 6
   "scripts": {

+ 1
- 2
src/RJSVM/framework/rjsvm.ts View File

@@ -30,7 +30,6 @@ export abstract class RJSVM_Builder {
30 30
                 public readonly config: RJSVM_Config
31 31
             ) {
32 32
                 super()
33
-
34 33
                 
35 34
                 if(!XRP_ADDRESS.test(this.owner)){
36 35
                     const err = new Error(`Inavlid owner address ${this.owner}`)
@@ -38,7 +37,6 @@ export abstract class RJSVM_Builder {
38 37
                     throw err
39 38
                 }
40 39
                 
41
-
42 40
                 this.definitions = Object.freeze(defs)
43 41
                 Object.entries(this.definitions).forEach(([k, v]) => {
44 42
                     this[k] = (env: PaymentTx_T, ...args: any) => (v.implementation as ParameterizedFunction).apply(this as any, [env, ...args])
@@ -87,6 +85,7 @@ export abstract class RJSVM_Builder {
87 85
                 }
88 86
 
89 87
                 this.subscribers = {}
88
+                this.onceSubscribers = {}
90 89
             }
91 90
 
92 91
             public on = (event: string, handler: ParameterizedFunction) => {

+ 1
- 3
test/Test.ts View File

@@ -1,7 +1,5 @@
1 1
 import { z } from "zod";
2
-import { RJSVM_Implementations, RJSVM_Interface, RJSVM, RJSVM_Config } from "../src/RJSVM/framework/types"
3
-import { DataParser, RJSVM_Builder } from "../src/main";
4
-import { xrp_transaction_hash_schema } from "../src/RJSVM/framework/schemas";
2
+import { DataParser, RJSVM_Builder, RJSVM_Implementations, RJSVM_Interface, RJSVM, RJSVM_Config } from "../src/main";
5 3
 
6 4
 //Test requirements
7 5
 import { assert, expect } from 'chai';

Loading…
Cancel
Save