Browse Source

fix browser issues for good hopefully

master
nitowa 1 month ago
parent
commit
96e423c151
7 changed files with 1040 additions and 4338 deletions
  1. 889
    4277
      package-lock.json
  2. 7
    4
      package.json
  3. 41
    48
      src/RJSVM/framework/rjsvm.ts
  4. 2
    1
      src/main.ts
  5. 1
    0
      test/Test.ts
  6. 96
    0
      test/index.html
  7. 4
    8
      webpack.js

+ 889
- 4277
package-lock.json
File diff suppressed because it is too large
View File


+ 7
- 4
package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
   "name": "rjsvm",
3
-  "version": "0.3.2",
3
+  "version": "0.4.1",
4 4
   "description": "",
5 5
   "main": "lib/src/main.js",
6 6
   "scripts": {
@@ -16,13 +16,16 @@
16 16
   "license": "ISC",
17 17
   "dependencies": {
18 18
     "axios": "^1.7.7",
19
-    "stream-http": "^3.2.0",
20
-    "url": "^0.11.3",
21
-    "xrpio": "^0.3.0",
19
+    "rjsvm": "^0.4.0",
20
+    "xrpio": "^0.4.0",
22 21
     "xrpl": "^4.0.0",
23 22
     "zod": "^3.21.4"
24 23
   },
25 24
   "devDependencies": {
25
+    "node-polyfill-webpack-plugin": "^4.0.0",
26
+    "stream-http": "^3.2.0",
27
+    "url": "^0.11.3",
28
+
26 29
     "@types/chai": "^4.3.6",
27 30
     "@types/expect": "^1.20.4",
28 31
     "@types/mocha": "^5.2.7",

+ 41
- 48
src/RJSVM/framework/rjsvm.ts View File

@@ -1,5 +1,5 @@
1 1
 import { PaymentTx_T, ParameterizedFunction, Payload, RJSVM, RJSVM_Config, RJSVM_Implementations, Function_Map, Endpoints_Of, State_Of, Generic_Ctor_ReturnType, RJSVM_Endpoint } from "./types"
2
-import { AccountTxTransaction, Client as Xrpl } from 'xrpl';
2
+import { Client as Xrpl } from 'xrpl';
3 3
 import { xrpIO } from 'xrpio';
4 4
 import { DataParser } from "../../util/dataparser";
5 5
 import { XRP_ADDRESS } from "../../util/protocol.constants";
@@ -13,8 +13,8 @@ export abstract class RJSVM_Builder {
13 13
         Impl extends RJSVM_Implementations<any, Endpoints_T>,
14 14
         Endpoints_T extends Function_Map = Endpoints_Of<Generic_Ctor_ReturnType<Base_Ctor>>,
15 15
         State_T = State_Of<Generic_Ctor_ReturnType<Base_Ctor>>
16
-    >(Base: Base_Ctor, defs: Impl): (new (config: RJSVM_Config) => RJSVM<State_T, Endpoints_T>){
17
-        return <any> class RJSVM_Runnable extends (Base as any){
16
+    >(Base: Base_Ctor, defs: Impl): (new (config: RJSVM_Config) => RJSVM<State_T, Endpoints_T>) {
17
+        return <any>class RJSVM_Runnable extends (Base as any) {
18 18
 
19 19
             sync_block_height = -1
20 20
 
@@ -30,13 +30,13 @@ export abstract class RJSVM_Builder {
30 30
                 public readonly config: RJSVM_Config
31 31
             ) {
32 32
                 super()
33
-                
34
-                if(!XRP_ADDRESS.test(this.owner)){
33
+
34
+                if (!XRP_ADDRESS.test(this.owner)) {
35 35
                     const err = new Error(`Inavlid owner address ${this.owner}`)
36 36
                     this.emit('error', err)
37 37
                     throw err
38 38
                 }
39
-                
39
+
40 40
                 this.definitions = Object.freeze(defs)
41 41
                 Object.entries(this.definitions).forEach(([k, v]) => {
42 42
                     this[k] = (env: PaymentTx_T, ...args: any) => (v.implementation as ParameterizedFunction).apply(this as any, [env, ...args])
@@ -47,7 +47,7 @@ export abstract class RJSVM_Builder {
47 47
                 this.rippleApi = new Xrpl(this.config.rippleNode)
48 48
                 await this.rippleApi.connect()
49 49
 
50
-                this.xrpIO = new xrpIO(this.config.rippleNode);
50
+                this.xrpIO = new xrpIO(this.config.rippleNode, { readFreshApi: false });
51 51
                 await this.xrpIO.connect()
52 52
                 await this.sync()
53 53
 
@@ -71,15 +71,15 @@ export abstract class RJSVM_Builder {
71 71
             }
72 72
 
73 73
             public disconnect = async () => {
74
-                if(this.syncTimeout){
74
+                if (this.syncTimeout) {
75 75
                     clearTimeout(this.syncTimeout)
76 76
                     this.syncTimeout = undefined
77 77
                 }
78
-                if(this.xrpIO){
78
+                if (this.xrpIO) {
79 79
                     await this.xrpIO.disconnect()
80 80
                     this.xrpIO = undefined
81 81
                 }
82
-                if(this.rippleApi){
82
+                if (this.rippleApi) {
83 83
                     await this.rippleApi.disconnect()
84 84
                     this.rippleApi = undefined
85 85
                 }
@@ -90,10 +90,10 @@ export abstract class RJSVM_Builder {
90 90
 
91 91
             public on = (event: string, handler: ParameterizedFunction) => {
92 92
                 const availableEvents = ['error', ...Object.keys(this.definitions)]
93
-                if(!availableEvents.includes(event))
93
+                if (!availableEvents.includes(event))
94 94
                     return
95
-                
96
-                if(!this.subscribers[event])
95
+
96
+                if (!this.subscribers[event])
97 97
                     this.subscribers[event] = []
98 98
 
99 99
                 this.subscribers[event].push(handler)
@@ -101,20 +101,20 @@ export abstract class RJSVM_Builder {
101 101
 
102 102
             public once = (event: string, handler: ParameterizedFunction) => {
103 103
                 const availableEvents = ['error', ...Object.keys(this.definitions)]
104
-                if(!availableEvents.includes(event))
104
+                if (!availableEvents.includes(event))
105 105
                     return
106
-                
107
-                if(!this.onceSubscribers[event])
106
+
107
+                if (!this.onceSubscribers[event])
108 108
                     this.onceSubscribers[event] = []
109 109
 
110 110
                 this.onceSubscribers[event].push(handler)
111 111
             }
112 112
 
113 113
             private emit = (event: string, payload: any) => {
114
-                if(this.subscribers[event])
114
+                if (this.subscribers[event])
115 115
                     this.subscribers[event].forEach(handler => handler(payload))
116
-                
117
-                if(this.onceSubscribers[event]){
116
+
117
+                if (this.onceSubscribers[event]) {
118 118
                     this.onceSubscribers[event].forEach(handler => handler(payload))
119 119
                     this.onceSubscribers[event] = []
120 120
                 }
@@ -127,18 +127,18 @@ export abstract class RJSVM_Builder {
127 127
 
128 128
                 const endpointDef: RJSVM_Endpoint<RJSVM, any> = this.definitions[payload.endpoint]
129 129
 
130
-                if(endpointDef.visibility === 'owner' && tx.Account !== this.owner){
130
+                if (endpointDef.visibility === 'owner' && tx.Account !== this.owner) {
131 131
                     const err = new RestrictedAccessError(payload.endpoint, tx.hash, tx.Account, this.owner)
132 132
                     this.emit('error', err)
133 133
                     return
134 134
                 }
135 135
 
136
-                if(endpointDef.fee && Number(tx.Amount) < endpointDef.fee){
136
+                if (endpointDef.fee && Number(tx.Amount) < endpointDef.fee) {
137 137
                     const err = new InsufficientFeeError(tx.hash, Number(endpointDef.fee), Number(tx.Amount))
138 138
                     this.emit('error', err)
139 139
                     return
140 140
                 }
141
-                
141
+
142 142
                 try {
143 143
                     const data = await this.xrpIO.treeRead([payload.data], tx.Account)
144 144
                     const jsonData = JSON.parse(data)
@@ -151,7 +151,7 @@ export abstract class RJSVM_Builder {
151 151
                 }
152 152
             }
153 153
 
154
-            private parseMemos = async (tx:PaymentTx_T) => {
154
+            private parseMemos = async (tx: PaymentTx_T) => {
155 155
                 const memos = tx.Memos
156 156
                 memos
157 157
                     .map((memo: any) => {
@@ -186,43 +186,36 @@ export abstract class RJSVM_Builder {
186 186
                 const resp = await this.rippleApi.request({
187 187
                     command: "account_tx",
188 188
                     account: this.config.listeningAddress,
189
-                    forward: true, 
189
+                    forward: true,
190 190
                     ledger_index_min: this.sync_block_height,
191 191
                     marker: marker,
192 192
                 })
193 193
 
194
-                //results may not be ordered, so sort them
195
-                const raw_txs = await Promise.all(
196
-                    resp.result.transactions
197
-                        .filter(tx => tx.tx_json.TransactionType === "Payment")
198
-                        .sort((a,b) => a.tx_json.ledger_index - b.tx_json.ledger_index)
199
-                        .map((tx) => this.xrpIO.getTransaction(tx.hash))
200
-                )
201
-
202
-                //XRPL API update adaption
194
+                const full_txs = resp.result.transactions
195
+                    .filter(tx => !!tx.tx_json.Memos)
196
+                    .map(tx => {
197
+                        return ({
198
+                            ...tx.tx_json,
199
+                            hash: tx.hash,
200
+                            Amount: tx.tx_json["DeliverMax"],
201
+                            inLedger: tx.tx_json['ledger_index']
202
+                        } as PaymentTx_T)
203
+                    })
204
+                
203 205
                 await Promise.all(
204
-                    raw_txs
205
-                        .filter(tx => !!tx.result.tx_json.Memos)
206
-                        .map(tx => {
207
-                            return({
208
-                                ...tx.result.tx_json,
209
-                                hash: tx.result.hash,
210
-                                Amount: tx.result.tx_json["DeliverMax"],
211
-                                inLedger: tx.result.tx_json['ledger_index']
212
-                            } as PaymentTx_T)
213
-                        })
206
+                    full_txs
214 207
                         .map(tx => this.parseMemos(tx))
215
-                    )
216
-                
208
+                )
209
+
217 210
                 //if marker is present the result is paginated.
218 211
                 //re-run the same request with the marker included
219
-                if(resp.result.marker){
212
+                if (resp.result.marker) {
220 213
                     await this.sync(resp.result.marker)
221
-                }else{
214
+                } else {
222 215
                     //presence of no marker means we caught up to current block height
223 216
                     this.sync_block_height = resp.result.ledger_index_max + 1
224 217
                     //schedule the next sync
225
-                    this.syncTimeout = setTimeout(this.sync, 10000)
218
+                    this.syncTimeout = setTimeout(this.sync, 5000)
226 219
                 }
227 220
             }
228 221
         }

+ 2
- 1
src/main.ts View File

@@ -1,4 +1,5 @@
1 1
 export * from "./RJSVM/framework/rjsvm"
2 2
 export * from "./RJSVM/datawriter/datawriter"
3 3
 export * from "./RJSVM/framework/types"
4
-export * from "./util/dataparser"
4
+export * from "./util/dataparser"
5
+export * from "zod"

+ 1
- 0
test/Test.ts View File

@@ -142,6 +142,7 @@ const setup = async () => {
142 142
     await rjsvm.connect()
143 143
 }
144 144
 
145
+
145 146
 describe('RJSVM basic functions', () => {
146 147
 
147 148
     before(async function () {

+ 96
- 0
test/index.html View File

@@ -0,0 +1,96 @@
1
+<!doctype html>
2
+<html lang="en">
3
+
4
+<head>
5
+    <script src="../lib/browser/rjsvm.browser.js"></script>
6
+</head>
7
+
8
+<body>
9
+    <div style="text-align: center;"></div>
10
+    <script>
11
+
12
+        const xrpNode = "wss://s.altnet.rippletest.net:51233"
13
+        const listeningAddress = "rMBYWyxGx1b5zEjJKF18TTwF5X3vP2WyjR"
14
+
15
+        const drainWallet = {
16
+            address: "rLNEG2ubbW3HUHYL7QCunNX96QrZzq2Udo",
17
+            secret: "sEd7FusyxBpT1JLQjS76nnn4JABredu"
18
+        }
19
+
20
+        const sendWallet = {
21
+            address: "rnNuTh8catLz5T12e1fwbxH3FWvUZCYYTw",
22
+            secret: "sEdSqxN99gFoZ2s8ru7RNCvEXFBmVYa"
23
+        }
24
+
25
+        this.dataWriter = new Datawriter({
26
+            receiveAddress: drainWallet.address,
27
+            sendWallet: sendWallet,
28
+            xrpNode: xrpNode,
29
+            contractAddress: listeningAddress
30
+        })
31
+
32
+        const shoutSchema = z.object({
33
+            title: z.string(),
34
+            body: z.string(),
35
+            from: z.string(),
36
+            hash: z.optional(z.string()),
37
+            date: z.optional(z.string()),
38
+            id: z.optional(z.string())
39
+        })
40
+
41
+
42
+        // #########################
43
+        // Define endpoints
44
+        // #########################
45
+
46
+
47
+        // #########################
48
+        // Define init state
49
+        // #########################
50
+
51
+        class RJSVM_Base
52
+            extends RJSVM {
53
+
54
+            owner = sendWallet.address
55
+
56
+            state = {}
57
+        }
58
+
59
+        // #########################
60
+        // Implement logic
61
+        // #########################
62
+
63
+        const RJSVM_Contract = {
64
+            submit: {
65
+                implementation: function (env, shout) {
66
+                    shout.hash = env.hash;
67
+                    const d = new Date("2000-01-01");
68
+                    d.setSeconds(d.getSeconds() + env.date)
69
+                    shout.date = d.toLocaleString("de-DE")
70
+                },
71
+                visibility: 'public',
72
+                fee: 10,
73
+                parameterSchema: shoutSchema
74
+            }
75
+        }
76
+
77
+        // #########################
78
+        // Build and connect
79
+        // #########################
80
+
81
+        const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
82
+
83
+        const conf = {
84
+            listeningAddress: listeningAddress,
85
+            rippleNode: xrpNode
86
+        }
87
+
88
+        const rjsvm = new Rjsvm(conf)
89
+        rjsvm.connect()
90
+
91
+        rjsvm.on('error', console.log)
92
+        rjsvm.on('submit', console.log)
93
+    </script>
94
+</body>
95
+
96
+</html>

+ 4
- 8
webpack.js View File

@@ -1,6 +1,8 @@
1 1
 const path = require('path');
2 2
 const webpack = require('webpack');
3 3
 const BomPlugin = require('webpack-utf8-bom');
4
+const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
5
+
4 6
 
5 7
 module.exports = {
6 8
   mode: 'production',
@@ -14,14 +16,7 @@ module.exports = {
14 16
   resolve: {
15 17
     extensions: [".ts", ".tsx", ".js"],
16 18
     fallback: {
17
-      "zlib": require.resolve("browserify-zlib"),
18
-      "http": require.resolve("stream-http"),
19
-      "https": require.resolve("https-browserify"),
20
-      "stream": require.resolve("stream-browserify") ,
21
-      "buffer": require.resolve('buffer/'),
22
-      "Buffer": require.resolve('buffer/'),
23
-      "url": require.resolve('url/'),
24
-      "crypto": require.resolve('crypto-browserify'),
19
+      buffer: require.resolve('buffer/'),
25 20
     }
26 21
   },
27 22
   module: {
@@ -33,6 +28,7 @@ module.exports = {
33 28
     minimize: true,
34 29
   },
35 30
   plugins: [
31
+    new NodePolyfillPlugin(),
36 32
     new webpack.ProvidePlugin({
37 33
       Buffer: ['buffer', 'Buffer'],
38 34
     }),

Loading…
Cancel
Save