|
@@ -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
|
}
|