fix browser issues for good hopefully

This commit is contained in:
nitowa
2024-10-14 15:27:37 +02:00
parent 793a40a66c
commit 96e423c151
7 changed files with 1039 additions and 4337 deletions
+888 -4276
View File
File diff suppressed because it is too large Load Diff
+7 -4
View File
@@ -1,6 +1,6 @@
{ {
"name": "rjsvm", "name": "rjsvm",
"version": "0.3.2", "version": "0.4.1",
"description": "", "description": "",
"main": "lib/src/main.js", "main": "lib/src/main.js",
"scripts": { "scripts": {
@@ -16,13 +16,16 @@
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"axios": "^1.7.7", "axios": "^1.7.7",
"stream-http": "^3.2.0", "rjsvm": "^0.4.0",
"url": "^0.11.3", "xrpio": "^0.4.0",
"xrpio": "^0.3.0",
"xrpl": "^4.0.0", "xrpl": "^4.0.0",
"zod": "^3.21.4" "zod": "^3.21.4"
}, },
"devDependencies": { "devDependencies": {
"node-polyfill-webpack-plugin": "^4.0.0",
"stream-http": "^3.2.0",
"url": "^0.11.3",
"@types/chai": "^4.3.6", "@types/chai": "^4.3.6",
"@types/expect": "^1.20.4", "@types/expect": "^1.20.4",
"@types/mocha": "^5.2.7", "@types/mocha": "^5.2.7",
+32 -39
View File
@@ -1,5 +1,5 @@
import { PaymentTx_T, ParameterizedFunction, Payload, RJSVM, RJSVM_Config, RJSVM_Implementations, Function_Map, Endpoints_Of, State_Of, Generic_Ctor_ReturnType, RJSVM_Endpoint } from "./types" import { PaymentTx_T, ParameterizedFunction, Payload, RJSVM, RJSVM_Config, RJSVM_Implementations, Function_Map, Endpoints_Of, State_Of, Generic_Ctor_ReturnType, RJSVM_Endpoint } from "./types"
import { AccountTxTransaction, Client as Xrpl } from 'xrpl'; import { Client as Xrpl } from 'xrpl';
import { xrpIO } from 'xrpio'; import { xrpIO } from 'xrpio';
import { DataParser } from "../../util/dataparser"; import { DataParser } from "../../util/dataparser";
import { XRP_ADDRESS } from "../../util/protocol.constants"; import { XRP_ADDRESS } from "../../util/protocol.constants";
@@ -13,8 +13,8 @@ export abstract class RJSVM_Builder {
Impl extends RJSVM_Implementations<any, Endpoints_T>, Impl extends RJSVM_Implementations<any, Endpoints_T>,
Endpoints_T extends Function_Map = Endpoints_Of<Generic_Ctor_ReturnType<Base_Ctor>>, Endpoints_T extends Function_Map = Endpoints_Of<Generic_Ctor_ReturnType<Base_Ctor>>,
State_T = State_Of<Generic_Ctor_ReturnType<Base_Ctor>> State_T = State_Of<Generic_Ctor_ReturnType<Base_Ctor>>
>(Base: Base_Ctor, defs: Impl): (new (config: RJSVM_Config) => RJSVM<State_T, Endpoints_T>){ >(Base: Base_Ctor, defs: Impl): (new (config: RJSVM_Config) => RJSVM<State_T, Endpoints_T>) {
return <any> class RJSVM_Runnable extends (Base as any){ return <any>class RJSVM_Runnable extends (Base as any) {
sync_block_height = -1 sync_block_height = -1
@@ -31,7 +31,7 @@ export abstract class RJSVM_Builder {
) { ) {
super() super()
if(!XRP_ADDRESS.test(this.owner)){ if (!XRP_ADDRESS.test(this.owner)) {
const err = new Error(`Inavlid owner address ${this.owner}`) const err = new Error(`Inavlid owner address ${this.owner}`)
this.emit('error', err) this.emit('error', err)
throw err throw err
@@ -47,7 +47,7 @@ export abstract class RJSVM_Builder {
this.rippleApi = new Xrpl(this.config.rippleNode) this.rippleApi = new Xrpl(this.config.rippleNode)
await this.rippleApi.connect() await this.rippleApi.connect()
this.xrpIO = new xrpIO(this.config.rippleNode); this.xrpIO = new xrpIO(this.config.rippleNode, { readFreshApi: false });
await this.xrpIO.connect() await this.xrpIO.connect()
await this.sync() await this.sync()
@@ -71,15 +71,15 @@ export abstract class RJSVM_Builder {
} }
public disconnect = async () => { public disconnect = async () => {
if(this.syncTimeout){ if (this.syncTimeout) {
clearTimeout(this.syncTimeout) clearTimeout(this.syncTimeout)
this.syncTimeout = undefined this.syncTimeout = undefined
} }
if(this.xrpIO){ if (this.xrpIO) {
await this.xrpIO.disconnect() await this.xrpIO.disconnect()
this.xrpIO = undefined this.xrpIO = undefined
} }
if(this.rippleApi){ if (this.rippleApi) {
await this.rippleApi.disconnect() await this.rippleApi.disconnect()
this.rippleApi = undefined this.rippleApi = undefined
} }
@@ -90,10 +90,10 @@ export abstract class RJSVM_Builder {
public on = (event: string, handler: ParameterizedFunction) => { public on = (event: string, handler: ParameterizedFunction) => {
const availableEvents = ['error', ...Object.keys(this.definitions)] const availableEvents = ['error', ...Object.keys(this.definitions)]
if(!availableEvents.includes(event)) if (!availableEvents.includes(event))
return return
if(!this.subscribers[event]) if (!this.subscribers[event])
this.subscribers[event] = [] this.subscribers[event] = []
this.subscribers[event].push(handler) this.subscribers[event].push(handler)
@@ -101,20 +101,20 @@ export abstract class RJSVM_Builder {
public once = (event: string, handler: ParameterizedFunction) => { public once = (event: string, handler: ParameterizedFunction) => {
const availableEvents = ['error', ...Object.keys(this.definitions)] const availableEvents = ['error', ...Object.keys(this.definitions)]
if(!availableEvents.includes(event)) if (!availableEvents.includes(event))
return return
if(!this.onceSubscribers[event]) if (!this.onceSubscribers[event])
this.onceSubscribers[event] = [] this.onceSubscribers[event] = []
this.onceSubscribers[event].push(handler) this.onceSubscribers[event].push(handler)
} }
private emit = (event: string, payload: any) => { private emit = (event: string, payload: any) => {
if(this.subscribers[event]) if (this.subscribers[event])
this.subscribers[event].forEach(handler => handler(payload)) this.subscribers[event].forEach(handler => handler(payload))
if(this.onceSubscribers[event]){ if (this.onceSubscribers[event]) {
this.onceSubscribers[event].forEach(handler => handler(payload)) this.onceSubscribers[event].forEach(handler => handler(payload))
this.onceSubscribers[event] = [] this.onceSubscribers[event] = []
} }
@@ -127,13 +127,13 @@ export abstract class RJSVM_Builder {
const endpointDef: RJSVM_Endpoint<RJSVM, any> = this.definitions[payload.endpoint] const endpointDef: RJSVM_Endpoint<RJSVM, any> = this.definitions[payload.endpoint]
if(endpointDef.visibility === 'owner' && tx.Account !== this.owner){ if (endpointDef.visibility === 'owner' && tx.Account !== this.owner) {
const err = new RestrictedAccessError(payload.endpoint, tx.hash, tx.Account, this.owner) const err = new RestrictedAccessError(payload.endpoint, tx.hash, tx.Account, this.owner)
this.emit('error', err) this.emit('error', err)
return return
} }
if(endpointDef.fee && Number(tx.Amount) < endpointDef.fee){ if (endpointDef.fee && Number(tx.Amount) < endpointDef.fee) {
const err = new InsufficientFeeError(tx.hash, Number(endpointDef.fee), Number(tx.Amount)) const err = new InsufficientFeeError(tx.hash, Number(endpointDef.fee), Number(tx.Amount))
this.emit('error', err) this.emit('error', err)
return return
@@ -151,7 +151,7 @@ export abstract class RJSVM_Builder {
} }
} }
private parseMemos = async (tx:PaymentTx_T) => { private parseMemos = async (tx: PaymentTx_T) => {
const memos = tx.Memos const memos = tx.Memos
memos memos
.map((memo: any) => { .map((memo: any) => {
@@ -191,38 +191,31 @@ export abstract class RJSVM_Builder {
marker: marker, marker: marker,
}) })
//results may not be ordered, so sort them const full_txs = resp.result.transactions
const raw_txs = await Promise.all( .filter(tx => !!tx.tx_json.Memos)
resp.result.transactions .map(tx => {
.filter(tx => tx.tx_json.TransactionType === "Payment") return ({
.sort((a,b) => a.tx_json.ledger_index - b.tx_json.ledger_index) ...tx.tx_json,
.map((tx) => this.xrpIO.getTransaction(tx.hash)) hash: tx.hash,
) Amount: tx.tx_json["DeliverMax"],
inLedger: tx.tx_json['ledger_index']
} as PaymentTx_T)
})
//XRPL API update adaption
await Promise.all( await Promise.all(
raw_txs full_txs
.filter(tx => !!tx.result.tx_json.Memos)
.map(tx => {
return({
...tx.result.tx_json,
hash: tx.result.hash,
Amount: tx.result.tx_json["DeliverMax"],
inLedger: tx.result.tx_json['ledger_index']
} as PaymentTx_T)
})
.map(tx => this.parseMemos(tx)) .map(tx => this.parseMemos(tx))
) )
//if marker is present the result is paginated. //if marker is present the result is paginated.
//re-run the same request with the marker included //re-run the same request with the marker included
if(resp.result.marker){ if (resp.result.marker) {
await this.sync(resp.result.marker) await this.sync(resp.result.marker)
}else{ } else {
//presence of no marker means we caught up to current block height //presence of no marker means we caught up to current block height
this.sync_block_height = resp.result.ledger_index_max + 1 this.sync_block_height = resp.result.ledger_index_max + 1
//schedule the next sync //schedule the next sync
this.syncTimeout = setTimeout(this.sync, 10000) this.syncTimeout = setTimeout(this.sync, 5000)
} }
} }
} }
+1
View File
@@ -2,3 +2,4 @@ export * from "./RJSVM/framework/rjsvm"
export * from "./RJSVM/datawriter/datawriter" export * from "./RJSVM/datawriter/datawriter"
export * from "./RJSVM/framework/types" export * from "./RJSVM/framework/types"
export * from "./util/dataparser" export * from "./util/dataparser"
export * from "zod"
+1
View File
@@ -142,6 +142,7 @@ const setup = async () => {
await rjsvm.connect() await rjsvm.connect()
} }
describe('RJSVM basic functions', () => { describe('RJSVM basic functions', () => {
before(async function () { before(async function () {
+96
View File
@@ -0,0 +1,96 @@
<!doctype html>
<html lang="en">
<head>
<script src="../lib/browser/rjsvm.browser.js"></script>
</head>
<body>
<div style="text-align: center;"></div>
<script>
const xrpNode = "wss://s.altnet.rippletest.net:51233"
const listeningAddress = "rMBYWyxGx1b5zEjJKF18TTwF5X3vP2WyjR"
const drainWallet = {
address: "rLNEG2ubbW3HUHYL7QCunNX96QrZzq2Udo",
secret: "sEd7FusyxBpT1JLQjS76nnn4JABredu"
}
const sendWallet = {
address: "rnNuTh8catLz5T12e1fwbxH3FWvUZCYYTw",
secret: "sEdSqxN99gFoZ2s8ru7RNCvEXFBmVYa"
}
this.dataWriter = new Datawriter({
receiveAddress: drainWallet.address,
sendWallet: sendWallet,
xrpNode: xrpNode,
contractAddress: listeningAddress
})
const shoutSchema = z.object({
title: z.string(),
body: z.string(),
from: z.string(),
hash: z.optional(z.string()),
date: z.optional(z.string()),
id: z.optional(z.string())
})
// #########################
// Define endpoints
// #########################
// #########################
// Define init state
// #########################
class RJSVM_Base
extends RJSVM {
owner = sendWallet.address
state = {}
}
// #########################
// Implement logic
// #########################
const RJSVM_Contract = {
submit: {
implementation: function (env, shout) {
shout.hash = env.hash;
const d = new Date("2000-01-01");
d.setSeconds(d.getSeconds() + env.date)
shout.date = d.toLocaleString("de-DE")
},
visibility: 'public',
fee: 10,
parameterSchema: shoutSchema
}
}
// #########################
// Build and connect
// #########################
const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
const conf = {
listeningAddress: listeningAddress,
rippleNode: xrpNode
}
const rjsvm = new Rjsvm(conf)
rjsvm.connect()
rjsvm.on('error', console.log)
rjsvm.on('submit', console.log)
</script>
</body>
</html>
+4 -8
View File
@@ -1,6 +1,8 @@
const path = require('path'); const path = require('path');
const webpack = require('webpack'); const webpack = require('webpack');
const BomPlugin = require('webpack-utf8-bom'); const BomPlugin = require('webpack-utf8-bom');
const NodePolyfillPlugin = require('node-polyfill-webpack-plugin');
module.exports = { module.exports = {
mode: 'production', mode: 'production',
@@ -14,14 +16,7 @@ module.exports = {
resolve: { resolve: {
extensions: [".ts", ".tsx", ".js"], extensions: [".ts", ".tsx", ".js"],
fallback: { fallback: {
"zlib": require.resolve("browserify-zlib"), buffer: require.resolve('buffer/'),
"http": require.resolve("stream-http"),
"https": require.resolve("https-browserify"),
"stream": require.resolve("stream-browserify") ,
"buffer": require.resolve('buffer/'),
"Buffer": require.resolve('buffer/'),
"url": require.resolve('url/'),
"crypto": require.resolve('crypto-browserify'),
} }
}, },
module: { module: {
@@ -33,6 +28,7 @@ module.exports = {
minimize: true, minimize: true,
}, },
plugins: [ plugins: [
new NodePolyfillPlugin(),
new webpack.ProvidePlugin({ new webpack.ProvidePlugin({
Buffer: ['buffer', 'Buffer'], Buffer: ['buffer', 'Buffer'],
}), }),