Browse Source

0.1 release, add .on(...) and .once(...) to RJSVM, add tests

master
nitowa 1 year ago
parent
commit
270c41a3dc
46 changed files with 5789 additions and 958 deletions
  1. 9
    0
      .gitignore
  2. 9
    0
      .npmignore
  3. 0
    4
      lib/RJSVM/framework/rjsvm.d.ts
  4. 0
    127
      lib/RJSVM/framework/rjsvm.js
  5. 0
    67
      lib/RJSVM/framework/types.d.ts
  6. 0
    17
      lib/RJSVM/framework/types.js
  7. 0
    15
      lib/RJSVM/protocol/datawriter.d.ts
  8. 0
    53
      lib/RJSVM/protocol/datawriter.js
  9. 0
    3
      lib/main.d.ts
  10. 0
    19
      lib/main.js
  11. 0
    1
      lib/user-defined-contract.d.ts
  12. 0
    55
      lib/user-defined-contract.js
  13. 0
    3
      lib/util/dataparser.d.ts
  14. 0
    14
      lib/util/dataparser.js
  15. 0
    15
      lib/util/protocol.constants.d.ts
  16. 0
    18
      lib/util/protocol.constants.js
  17. 0
    3
      lib/util/schemas.d.ts
  18. 0
    8
      lib/util/schemas.js
  19. 1852
    130
      node_modules/.package-lock.json
  20. 28
    0
      node_modules/define-properties/CHANGELOG.md
  21. 13
    13
      node_modules/define-properties/index.js
  22. 27
    5
      node_modules/define-properties/package.json
  23. 1
    0
      node_modules/get-intrinsic/.eslintrc
  24. 19
    0
      node_modules/get-intrinsic/CHANGELOG.md
  25. 25
    8
      node_modules/get-intrinsic/index.js
  26. 8
    6
      node_modules/get-intrinsic/package.json
  27. 1
    1
      node_modules/get-intrinsic/test/GetIntrinsic.js
  28. 14
    0
      node_modules/is-typed-array/CHANGELOG.md
  29. 2
    55
      node_modules/is-typed-array/index.js
  30. 8
    10
      node_modules/is-typed-array/package.json
  31. 15
    0
      node_modules/which-typed-array/CHANGELOG.md
  32. 56
    22
      node_modules/which-typed-array/index.js
  33. 5
    6
      node_modules/which-typed-array/package.json
  34. 1
    1
      node_modules/which-typed-array/test/index.js
  35. 3144
    106
      package-lock.json
  36. 8
    0
      package.json
  37. 48
    0
      src/RJSVM/datawriter/datawriter.ts
  38. 78
    11
      src/RJSVM/framework/rjsvm.ts
  39. 10
    0
      src/RJSVM/framework/schemas.ts
  40. 8
    13
      src/RJSVM/framework/types.ts
  41. 0
    79
      src/RJSVM/protocol/datawriter.ts
  42. 126
    64
      src/user-defined-contract.ts
  43. 11
    0
      src/util/errors.ts
  44. 0
    6
      src/util/schemas.ts
  45. 247
    0
      test/Test.ts
  46. 16
    0
      test/tools.ts

+ 9
- 0
.gitignore View File

@@ -0,0 +1,9 @@
1
+build
2
+node_modules
3
+.vscode
4
+lib
5
+docs
6
+gui/*.js
7
+src/gui/build
8
+src/gui/dist
9
+src/gui/node_modules

+ 9
- 0
.npmignore View File

@@ -0,0 +1,9 @@
1
+src
2
+.git
3
+.vscode
4
+node_modules
5
+test
6
+.drone.yml
7
+.gitignore
8
+tsconfig.json
9
+lib/src/xrpIO/ripple-bindings.*

+ 0
- 4
lib/RJSVM/framework/rjsvm.d.ts View File

@@ -1,4 +0,0 @@
1
-import { RJSVM, RJSVM_Config, RJSVM_Implementations, Function_Map, Endpoints_Of, State_Of, Generic_Ctor_ReturnType } from "./types";
2
-export declare abstract class RJSVM_Builder {
3
-    static from<Base_Ctor extends (new (...args: any) => RJSVM<State_T, Endpoints_T>) | (abstract new (...args: any) => RJSVM<State_T, Endpoints_T>), Impl extends RJSVM_Implementations<any, Endpoints_T>, Endpoints_T extends Function_Map = Endpoints_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>);
4
-}

+ 0
- 127
lib/RJSVM/framework/rjsvm.js View File

@@ -1,127 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.RJSVM_Builder = void 0;
4
-const types_1 = require("./types");
5
-const xrpl_1 = require("xrpl");
6
-const xrpio_1 = require("xrpio");
7
-const dataparser_1 = require("../../util/dataparser");
8
-const protocol_constants_1 = require("../../util/protocol.constants");
9
-class RJSVM_Builder {
10
-    static from(Base, defs) {
11
-        return class RJSVM_Runnable extends Base {
12
-            config;
13
-            sync_block_height = -1;
14
-            rippleApi;
15
-            xrpIO;
16
-            definitions;
17
-            constructor(config) {
18
-                super();
19
-                this.config = config;
20
-                if (!protocol_constants_1.XRP_ADDRESS.test(this.owner)) {
21
-                    throw new Error(`Inavlid owner address ${this.owner}`);
22
-                }
23
-                this.definitions = Object.freeze(defs);
24
-                Object.entries(this.definitions).forEach(([k, v]) => {
25
-                    this[k] = (env, ...args) => v.implementation.apply(this, [env, ...args]);
26
-                });
27
-            }
28
-            connect = async () => {
29
-                this.rippleApi = new xrpl_1.Client(this.config.rippleNode);
30
-                await this.rippleApi.connect();
31
-                this.xrpIO = new xrpio_1.xrpIO(this.config.rippleNode);
32
-                await this.xrpIO.connect();
33
-                await this.sync();
34
-                this.rippleApi.on('ledgerClosed', (ledger) => {
35
-                    /*
36
-                    console.log("---- Ledger ----")
37
-                    console.log("index",ledger.ledger_index)
38
-                    console.log("hash", ledger.ledger_hash)
39
-                    console.log("---- /Ledger ----")
40
-                    */
41
-                });
42
-                await this.rippleApi.request({
43
-                    command: 'subscribe',
44
-                    streams: ['ledger']
45
-                });
46
-            };
47
-            handlePayload = async (tx, payload) => {
48
-                if (!(payload.endpoint in this.definitions)) {
49
-                    return;
50
-                }
51
-                const endpointDef = this.definitions[payload.endpoint];
52
-                if (endpointDef.visibility === 'owner' && tx.Account !== this.owner) {
53
-                    console.log(`owner restricted endpoint "${payload.endpoint}" called from ${tx.hash}. But ${tx.Account} != ${this.owner}`);
54
-                    return;
55
-                }
56
-                if (endpointDef.fee && Number(tx.Amount) < endpointDef.fee) {
57
-                    console.log(`Insufficient fee ${tx.hash}. Required ${endpointDef.fee}, was ${tx.Amount}`);
58
-                    return;
59
-                }
60
-                try {
61
-                    const data = await this.xrpIO.treeRead([payload.data], tx.Account);
62
-                    const jsonData = JSON.parse(data);
63
-                    endpointDef.parameterSchema.parse(jsonData);
64
-                    this[payload.endpoint].apply(this, [tx, jsonData]);
65
-                }
66
-                catch (err) {
67
-                    console.log(err);
68
-                    return;
69
-                }
70
-            };
71
-            parseMemos = async (tx, memos) => {
72
-                memos
73
-                    .map((memo) => {
74
-                    if (!memo.Memo || !memo.Memo.MemoData) {
75
-                        return;
76
-                    }
77
-                    try {
78
-                        const data = dataparser_1.DataParser.hex_to_ascii(memo.Memo.MemoData);
79
-                        return JSON.parse(data);
80
-                    }
81
-                    catch (e) {
82
-                        return;
83
-                    }
84
-                })
85
-                    .filter((data) => data != undefined)
86
-                    .forEach(payload => {
87
-                    try {
88
-                        const parsedPayload = types_1.payloadSchema.parse(payload);
89
-                        this.handlePayload(tx, parsedPayload);
90
-                    }
91
-                    catch (e) {
92
-                    }
93
-                });
94
-            };
95
-            sync = async (marker) => {
96
-                //If `forward` is set to true, returns values indexed with the oldest ledger first. 
97
-                //Otherwise, the results are indexed with the newest ledger first. 
98
-                //(Each page of results may not be internally ordered, but the pages are overall ordered.)
99
-                const resp = await this.rippleApi.request({
100
-                    command: "account_tx",
101
-                    account: this.config.listeningAddress,
102
-                    forward: true,
103
-                    ledger_index_min: this.sync_block_height,
104
-                    marker: marker,
105
-                });
106
-                //results may not be ordered, so sort them
107
-                const raw_txs = resp.result.transactions
108
-                    .sort((a, b) => a.tx.ledger_index - b.tx.ledger_index)
109
-                    .map((entry) => entry.tx);
110
-                //apply any state changes
111
-                await Promise.all(raw_txs.map((tx) => this.parseMemos(tx, tx.Memos)));
112
-                //if marker is present the result is paginated.
113
-                //re-run the same request with the marker included
114
-                if (resp.result.marker) {
115
-                    await this.sync(resp.result.marker);
116
-                }
117
-                else {
118
-                    //presence of no marker means we caught up to current block height
119
-                    this.sync_block_height = resp.result.ledger_index_max + 1;
120
-                    //schedule the next sync
121
-                    setTimeout(this.sync, 10000);
122
-                }
123
-            };
124
-        };
125
-    }
126
-}
127
-exports.RJSVM_Builder = RJSVM_Builder;

+ 0
- 67
lib/RJSVM/framework/types.d.ts View File

@@ -1,67 +0,0 @@
1
-import { z } from "zod";
2
-export declare abstract class RJSVM<State_T = any, Definitions_T extends Function_Map = Function_Map> {
3
-    owner: string;
4
-    state: State_T;
5
-    sync_block_height: number;
6
-    config: RJSVM_Config;
7
-    definitions: RJSVM_Implementations<any, Definitions_T>;
8
-    connect: () => Promise<void>;
9
-}
10
-export type Generic_Ctor_ReturnType<Ctor> = Ctor extends new (...args: any) => infer T ? T : Ctor extends abstract new (...args: any) => infer A ? A : never;
11
-export type State_Of<T extends RJSVM<any>> = T extends RJSVM<infer State_T> ? State_T : any;
12
-export type Endpoints_Of<T extends RJSVM<any, any>> = T extends RJSVM<any, infer Endpoints_T> ? Endpoints_T : any;
13
-export type PaymentTx_T = {
14
-    Account: string;
15
-    Amount: string;
16
-    Destination: string;
17
-    Fee: string;
18
-    Flags: number;
19
-    LastLedgerSequence: number;
20
-    Memos: any[];
21
-    Sequence: number;
22
-    SigningPubKey: string;
23
-    TransactionType: 'Payment';
24
-    TxnSignature: string;
25
-    date: number;
26
-    hash: string;
27
-    inLedger: number;
28
-    ledger_index: number;
29
-};
30
-export type ParameterizedFunction = (...args: any) => void;
31
-export type Function_Map = {
32
-    [K in string]: ParameterizedFunction;
33
-};
34
-export type RJSVM_Endpoint<RJSVM_T extends RJSVM<any, Definitions_T>, Definitions_T extends Function_Map = Endpoints_Of<RJSVM_T>, Impl extends RJSVM_EndpointHandler<RJSVM_T, Definitions_T, ParameterizedFunction> = RJSVM_EndpointHandler<RJSVM_T, Definitions_T, ParameterizedFunction>> = {
35
-    implementation: Impl;
36
-    visibility: 'owner' | 'public';
37
-    fee?: number;
38
-    parameterSchema: z.Schema;
39
-};
40
-export type RJSVM_Implementations<RJSVM_T extends RJSVM<any, Definitions>, Definitions extends Function_Map = Endpoints_Of<RJSVM_T>> = {
41
-    [Key in keyof Definitions]: RJSVM_Endpoint<RJSVM_T, Definitions, RJSVM_EndpointHandler<RJSVM_T, Definitions, Definitions[Key]>>;
42
-};
43
-export type RJSVM_EndpointHandler<RJSVM_T extends RJSVM<any, Definitions_T>, Definitions_T extends Function_Map = Endpoints_Of<RJSVM_T>, Fn extends ParameterizedFunction = ParameterizedFunction> = (this: RJSVM_T & RJSVM_Interface<RJSVM_T, State_Of<RJSVM_T>, Definitions_T>, env: PaymentTx_T, ...args: Parameters<Fn>) => void;
44
-export type RJSVM_Interface<RJSVM_T extends RJSVM<State_T, Definitions_T>, State_T = State_Of<RJSVM_T>, Definitions_T extends Function_Map = Endpoints_Of<RJSVM_T>> = {
45
-    state: State_T;
46
-} & {
47
-    [K in keyof Definitions_T]?: RJSVM_EndpointHandler<RJSVM_T, Definitions_T, Definitions_T[K]>;
48
-};
49
-export type RJSVM_InitState<State_T> = {
50
-    owner: string;
51
-    state: State_T;
52
-};
53
-export type RJSVM_Config = {
54
-    rippleNode: string;
55
-    listeningAddress: string;
56
-};
57
-export declare const payloadSchema: z.ZodObject<{
58
-    endpoint: z.ZodString;
59
-    data: z.ZodString;
60
-}, "strip", z.ZodTypeAny, {
61
-    endpoint?: string;
62
-    data?: string;
63
-}, {
64
-    endpoint?: string;
65
-    data?: string;
66
-}>;
67
-export type Payload = z.infer<typeof payloadSchema>;

+ 0
- 17
lib/RJSVM/framework/types.js View File

@@ -1,17 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.payloadSchema = exports.RJSVM = void 0;
4
-const zod_1 = require("zod");
5
-class RJSVM {
6
-    owner;
7
-    state;
8
-    sync_block_height;
9
-    config;
10
-    definitions;
11
-    connect;
12
-}
13
-exports.RJSVM = RJSVM;
14
-exports.payloadSchema = zod_1.z.object({
15
-    endpoint: zod_1.z.string(),
16
-    data: zod_1.z.string()
17
-});

+ 0
- 15
lib/RJSVM/protocol/datawriter.d.ts View File

@@ -1,15 +0,0 @@
1
-type Wallet = {
2
-    address: string;
3
-    secret: string;
4
-};
5
-type DatawriterConfig = {
6
-    receiveAddress: string;
7
-    sendWallet: Wallet;
8
-    xrpNode: string;
9
-};
10
-export declare class Datawriter {
11
-    private config;
12
-    constructor(config: DatawriterConfig);
13
-    callEndpoint(endpointName: string, contractAddress: string, parameter: any, fee?: number): Promise<void>;
14
-}
15
-export {};

+ 0
- 53
lib/RJSVM/protocol/datawriter.js View File

@@ -1,53 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.Datawriter = void 0;
4
-const xrpio_1 = require("xrpio");
5
-class Datawriter {
6
-    config;
7
-    constructor(config) {
8
-        this.config = config;
9
-    }
10
-    async callEndpoint(endpointName, contractAddress, parameter, fee) {
11
-        const xrpio = new xrpio_1.xrpIO(this.config.xrpNode);
12
-        await xrpio.connect();
13
-        try {
14
-            const dataHash = await xrpio.treeWrite(JSON.stringify(parameter), this.config.receiveAddress, this.config.sendWallet.secret);
15
-            await xrpio.writeRaw({
16
-                data: JSON.stringify({
17
-                    endpoint: endpointName,
18
-                    data: dataHash
19
-                })
20
-            }, contractAddress, this.config.sendWallet.secret, undefined, fee ? String(fee) : undefined);
21
-        }
22
-        catch (e) {
23
-            console.log(e);
24
-        }
25
-        finally {
26
-            await xrpio.disconnect();
27
-        }
28
-    }
29
-}
30
-exports.Datawriter = Datawriter;
31
-(async () => {
32
-    const owner_dw = new Datawriter({
33
-        receiveAddress: "rDuXvMYNCEJCYDMFQykcafXhgi2NvMWqR",
34
-        sendWallet: {
35
-            address: "rUsPfG1hn6w6is28p5FUDWdMwvCo1iHrYq",
36
-            secret: "sEdTMicaTVmfsVMLhxrufyAzEQSnsaP"
37
-        },
38
-        xrpNode: "wss://s.altnet.rippletest.net:51233"
39
-    });
40
-    //await owner_dw.callEndpoint('submit', 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq', { title: "1", body: "2", from: "3" }, 100)
41
-    const user_dw = new Datawriter({
42
-        receiveAddress: "rwqCiEr3SLF43rAduhCChkR2K1XDhiqx5g",
43
-        sendWallet: {
44
-            address: "rHWN4X3hbodryX8H1EoPvmMV7AFHngEiBe",
45
-            secret: "sEdTdLPWvz69UAUmt1zYijTyWheER9u"
46
-        },
47
-        xrpNode: "wss://s.altnet.rippletest.net:51233"
48
-    });
49
-    //await owner_dw.callEndpoint('submit', 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq', { title: "1", body: "2", from: "3" }, 100)
50
-    //await user_dw.callEndpoint('restricted', 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq', { title: "user", body: "user", from: "user" })
51
-    //await owner_dw.callEndpoint('restricted', 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq', { title: "owner", body: "owner", from: "owner" })
52
-    await user_dw.callEndpoint('setTns', 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq', { hash: '01708abcF00636CE10E191FD782DBDC8F4076F28404BD88EBC31DE42DD084C0944B', name: 'test' });
53
-})();

+ 0
- 3
lib/main.d.ts View File

@@ -1,3 +0,0 @@
1
-export * from "./RJSVM/framework/rjsvm";
2
-export * from "./RJSVM/framework/types";
3
-export * from "./util/dataparser";

+ 0
- 19
lib/main.js View File

@@ -1,19 +0,0 @@
1
-"use strict";
2
-var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
-    if (k2 === undefined) k2 = k;
4
-    var desc = Object.getOwnPropertyDescriptor(m, k);
5
-    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
-      desc = { enumerable: true, get: function() { return m[k]; } };
7
-    }
8
-    Object.defineProperty(o, k2, desc);
9
-}) : (function(o, m, k, k2) {
10
-    if (k2 === undefined) k2 = k;
11
-    o[k2] = m[k];
12
-}));
13
-var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
-    for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
-};
16
-Object.defineProperty(exports, "__esModule", { value: true });
17
-__exportStar(require("./RJSVM/framework/rjsvm"), exports);
18
-__exportStar(require("./RJSVM/framework/types"), exports);
19
-__exportStar(require("./util/dataparser"), exports);

+ 0
- 1
lib/user-defined-contract.d.ts View File

@@ -1 +0,0 @@
1
-export {};

+ 0
- 55
lib/user-defined-contract.js View File

@@ -1,55 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-const zod_1 = require("zod");
4
-const types_1 = require("./RJSVM/framework/types");
5
-const main_1 = require("./main");
6
-const schemas_1 = require("./util/schemas");
7
-const shoutSchema = zod_1.z.object({
8
-    title: zod_1.z.string(),
9
-    body: zod_1.z.string(),
10
-    from: zod_1.z.string(),
11
-    id: zod_1.z.optional(zod_1.z.string())
12
-});
13
-const tnsEntrySchema = zod_1.z.object({
14
-    hash: schemas_1.xrp_transaction_hash_schema,
15
-    name: zod_1.z.string(),
16
-});
17
-class RJSVM_Base extends types_1.RJSVM {
18
-    owner = "rUsPfG1hn6w6is28p5FUDWdMwvCo1iHrYq";
19
-    state = {
20
-        shouts: []
21
-    };
22
-}
23
-const RJSVM_Contract = {
24
-    submit: {
25
-        implementation: function (env, shout) {
26
-            this.state.shouts.unshift(shout);
27
-            console.log(shout);
28
-        },
29
-        visibility: 'public',
30
-        fee: 10,
31
-        parameterSchema: shoutSchema
32
-    },
33
-    restricted: {
34
-        implementation: function (env, shout) {
35
-            this.state.shouts.unshift(shout);
36
-            console.log(shout);
37
-        },
38
-        visibility: 'owner',
39
-        parameterSchema: shoutSchema
40
-    },
41
-    setTns: {
42
-        implementation: function (env, tnsEntry) {
43
-            console.log(tnsEntry);
44
-        },
45
-        visibility: 'public',
46
-        parameterSchema: tnsEntrySchema,
47
-    }
48
-};
49
-const Rjsvm = main_1.RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
50
-const conf = {
51
-    listeningAddress: "rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq",
52
-    rippleNode: "wss://s.altnet.rippletest.net:51233"
53
-};
54
-const rjsvm = new Rjsvm(conf);
55
-rjsvm.connect();

+ 0
- 3
lib/util/dataparser.d.ts View File

@@ -1,3 +0,0 @@
1
-export declare class DataParser {
2
-    static hex_to_ascii(input: any): string;
3
-}

+ 0
- 14
lib/util/dataparser.js View File

@@ -1,14 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.DataParser = void 0;
4
-class DataParser {
5
-    static hex_to_ascii(input) {
6
-        var hex = input.toString();
7
-        var str = '';
8
-        for (var n = 0; n < hex.length; n += 2) {
9
-            str += String.fromCharCode(parseInt(hex.substr(n, 2), 16));
10
-        }
11
-        return str;
12
-    }
13
-}
14
-exports.DataParser = DataParser;

+ 0
- 15
lib/util/protocol.constants.d.ts View File

@@ -1,15 +0,0 @@
1
-export declare const MSG_DELIM: string;
2
-export declare const MSG_DATA_MAX: number;
3
-export declare const PUBKEY_LEN: number;
4
-export declare const NON_ZERO_TX_HASH: RegExp;
5
-export declare const PTR_FORMAT: RegExp;
6
-export declare const DATA_FORMAT: RegExp;
7
-export declare const SIGNATURE_FORMAT: RegExp;
8
-export declare const SIGNER_FORMAT: RegExp;
9
-export declare const MSG_FORMAT: RegExp;
10
-export declare const AMOUNT_DECIMALS = 18;
11
-export declare const MAX_SUPPLY = 20000000;
12
-export declare const AMOUNT_FORMAT: RegExp;
13
-export declare const MIN_XRP_FEE = "0.00001";
14
-export declare const MIN_XRP_TX_VALUE = "0.000001";
15
-export declare const XRP_ADDRESS: RegExp;

+ 0
- 18
lib/util/protocol.constants.js View File

@@ -1,18 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.XRP_ADDRESS = exports.MIN_XRP_TX_VALUE = exports.MIN_XRP_FEE = exports.AMOUNT_FORMAT = exports.MAX_SUPPLY = exports.AMOUNT_DECIMALS = exports.MSG_FORMAT = exports.SIGNER_FORMAT = exports.SIGNATURE_FORMAT = exports.DATA_FORMAT = exports.PTR_FORMAT = exports.NON_ZERO_TX_HASH = exports.PUBKEY_LEN = exports.MSG_DATA_MAX = exports.MSG_DELIM = void 0;
4
-exports.MSG_DELIM = ' ';
5
-exports.MSG_DATA_MAX = 925;
6
-exports.PUBKEY_LEN = 66;
7
-exports.NON_ZERO_TX_HASH = new RegExp(`[0-9A-F]{64}`);
8
-exports.PTR_FORMAT = new RegExp(`^((${exports.NON_ZERO_TX_HASH.source})|0)`);
9
-exports.DATA_FORMAT = new RegExp(`(.{1,${exports.MSG_DATA_MAX}})`);
10
-exports.SIGNATURE_FORMAT = new RegExp(`(\\S{140}|\\S{142})$`);
11
-exports.SIGNER_FORMAT = new RegExp(`(\\S{${exports.PUBKEY_LEN}})`);
12
-exports.MSG_FORMAT = new RegExp(`${exports.PTR_FORMAT.source}${exports.MSG_DELIM}${exports.DATA_FORMAT.source}`, 'm');
13
-exports.AMOUNT_DECIMALS = 18;
14
-exports.MAX_SUPPLY = 20_000_000;
15
-exports.AMOUNT_FORMAT = new RegExp(`\d+(\.\d{1,${exports.AMOUNT_DECIMALS}})?`);
16
-exports.MIN_XRP_FEE = "0.00001";
17
-exports.MIN_XRP_TX_VALUE = "0.000001";
18
-exports.XRP_ADDRESS = new RegExp(`^([r])([1-9A-HJ-NP-Za-km-z]{24,34})`);

+ 0
- 3
lib/util/schemas.d.ts View File

@@ -1,3 +0,0 @@
1
-import { z } from "zod";
2
-export declare const xrp_address_schema: z.ZodString;
3
-export declare const xrp_transaction_hash_schema: z.ZodString;

+ 0
- 8
lib/util/schemas.js View File

@@ -1,8 +0,0 @@
1
-"use strict";
2
-Object.defineProperty(exports, "__esModule", { value: true });
3
-exports.xrp_transaction_hash_schema = exports.xrp_address_schema = void 0;
4
-const zod_1 = require("zod");
5
-const protocol_constants_1 = require("./protocol.constants");
6
-const xrpio_1 = require("xrpio");
7
-exports.xrp_address_schema = zod_1.z.string().regex(protocol_constants_1.XRP_ADDRESS, "Not a valid XRP address");
8
-exports.xrp_transaction_hash_schema = zod_1.z.string().regex(xrpio_1.NON_ZERO_TX_HASH, "Not a valid XRP transaction hash");

+ 1852
- 130
node_modules/.package-lock.json
File diff suppressed because it is too large
View File


+ 28
- 0
node_modules/define-properties/CHANGELOG.md View File

@@ -1,3 +1,31 @@
1
+# Changelog
2
+
3
+All notable changes to this project will be documented in this file.
4
+
5
+The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6
+and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+## [v1.2.1](https://github.com/ljharb/define-properties/compare/v1.2.0...v1.2.1) - 2023-09-12
9
+
10
+### Commits
11
+
12
+- [Refactor] use `define-data-property` [`e7782a7`](https://github.com/ljharb/define-properties/commit/e7782a7480a62f8b6e141b49371e6de4df176c97)
13
+- [actions] use reusable rebase action [`cd249c3`](https://github.com/ljharb/define-properties/commit/cd249c3920607bc8eeb7c0cd5b672b810983cac5)
14
+- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`8205f97`](https://github.com/ljharb/define-properties/commit/8205f9734a4da8ee5b3b29798788567a09b330e8)
15
+
16
+## [v1.2.0](https://github.com/ljharb/define-properties/compare/v1.1.4...v1.2.0) - 2023-02-10
17
+
18
+### Commits
19
+
20
+- [New] if the predicate is boolean `true`, it compares the existing value with `===` as the predicate [`d8dd6fc`](https://github.com/ljharb/define-properties/commit/d8dd6fca40d7c5878a4b643b91e66ae5a513a194)
21
+- [meta] add `auto-changelog` [`7ebe2b0`](https://github.com/ljharb/define-properties/commit/7ebe2b0a0f90e62b842942cd45e86864fe75d9f6)
22
+- [meta] use `npmignore` to autogenerate an npmignore file [`647478a`](https://github.com/ljharb/define-properties/commit/647478a8401fbf053fb633c0a3a7c982da6bad74)
23
+- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`e620d70`](https://github.com/ljharb/define-properties/commit/e620d707d2e1118a38796f22a862200eb0a53fff)
24
+- [Dev Deps] update `aud`, `tape` [`f1e5072`](https://github.com/ljharb/define-properties/commit/f1e507225c2551a99ed4fe40d3fe71b0f44acf88)
25
+- [actions] update checkout action [`628b3af`](https://github.com/ljharb/define-properties/commit/628b3af5c74b8f0963296d811a8f6fa657baf964)
26
+
27
+<!-- auto-changelog-above -->
28
+
1 29
 1.1.4 / 2022-04-14
2 30
 =================
3 31
  * [Refactor] use `has-property-descriptors`

+ 13
- 13
node_modules/define-properties/index.js View File

@@ -5,29 +5,29 @@ var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbo
5 5
 
6 6
 var toStr = Object.prototype.toString;
7 7
 var concat = Array.prototype.concat;
8
-var origDefineProperty = Object.defineProperty;
8
+var defineDataProperty = require('define-data-property');
9 9
 
10 10
 var isFunction = function (fn) {
11 11
 	return typeof fn === 'function' && toStr.call(fn) === '[object Function]';
12 12
 };
13 13
 
14
-var hasPropertyDescriptors = require('has-property-descriptors')();
15
-
16
-var supportsDescriptors = origDefineProperty && hasPropertyDescriptors;
14
+var supportsDescriptors = require('has-property-descriptors')();
17 15
 
18 16
 var defineProperty = function (object, name, value, predicate) {
19
-	if (name in object && (!isFunction(predicate) || !predicate())) {
20
-		return;
17
+	if (name in object) {
18
+		if (predicate === true) {
19
+			if (object[name] === value) {
20
+				return;
21
+			}
22
+		} else if (!isFunction(predicate) || !predicate()) {
23
+			return;
24
+		}
21 25
 	}
26
+
22 27
 	if (supportsDescriptors) {
23
-		origDefineProperty(object, name, {
24
-			configurable: true,
25
-			enumerable: false,
26
-			value: value,
27
-			writable: true
28
-		});
28
+		defineDataProperty(object, name, value, true);
29 29
 	} else {
30
-		object[name] = value; // eslint-disable-line no-param-reassign
30
+		defineDataProperty(object, name, value);
31 31
 	}
32 32
 };
33 33
 

+ 27
- 5
node_modules/define-properties/package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
 	"name": "define-properties",
3
-	"version": "1.1.4",
3
+	"version": "1.2.1",
4 4
 	"author": "Jordan Harband <ljharb@gmail.com>",
5 5
 	"funding": {
6 6
 		"url": "https://github.com/sponsors/ljharb"
@@ -9,13 +9,16 @@
9 9
 	"license": "MIT",
10 10
 	"main": "index.js",
11 11
 	"scripts": {
12
+		"prepack": "npmignore --auto --commentLines=autogenerated",
12 13
 		"prepublish": "not-in-publish || npm run prepublishOnly",
13 14
 		"prepublishOnly": "safe-publish-latest",
14 15
 		"pretest": "npm run lint",
15 16
 		"test": "npm run tests-only",
16 17
 		"posttest": "aud --production",
17 18
 		"tests-only": "nyc tape 'test/**/*.js'",
18
-		"lint": "eslint --ext=js,mjs ."
19
+		"lint": "eslint --ext=js,mjs .",
20
+		"version": "auto-changelog && git add CHANGELOG.md",
21
+		"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
19 22
 	},
20 23
 	"repository": {
21 24
 		"type": "git",
@@ -31,16 +34,20 @@
31 34
 		"ES5"
32 35
 	],
33 36
 	"dependencies": {
37
+		"define-data-property": "^1.0.1",
34 38
 		"has-property-descriptors": "^1.0.0",
35 39
 		"object-keys": "^1.1.1"
36 40
 	},
37 41
 	"devDependencies": {
38
-		"@ljharb/eslint-config": "^21.0.0",
39
-		"aud": "^2.0.0",
42
+		"@ljharb/eslint-config": "^21.1.0",
43
+		"aud": "^2.0.3",
44
+		"auto-changelog": "^2.4.0",
40 45
 		"eslint": "=8.8.0",
46
+		"in-publish": "^2.0.1",
47
+		"npmignore": "^0.3.0",
41 48
 		"nyc": "^10.3.2",
42 49
 		"safe-publish-latest": "^2.0.0",
43
-		"tape": "^5.5.3"
50
+		"tape": "^5.6.6"
44 51
 	},
45 52
 	"testling": {
46 53
 		"files": "test/index.js",
@@ -62,5 +69,20 @@
62 69
 	},
63 70
 	"engines": {
64 71
 		"node": ">= 0.4"
72
+	},
73
+	"auto-changelog": {
74
+		"output": "CHANGELOG.md",
75
+		"template": "keepachangelog",
76
+		"unreleased": false,
77
+		"commitLimit": false,
78
+		"backfillLimit": false,
79
+		"hideCredit": true,
80
+		"startingVersion": "1.1.5"
81
+	},
82
+	"publishConfig": {
83
+		"ignore": [
84
+			".github/workflows",
85
+			"test/"
86
+		]
65 87
 	}
66 88
 }

+ 1
- 0
node_modules/get-intrinsic/.eslintrc View File

@@ -17,6 +17,7 @@
17 17
 		"eqeqeq": [2, "allow-null"],
18 18
 		"func-name-matching": 0,
19 19
 		"id-length": 0,
20
+		"max-lines": 0,
20 21
 		"max-lines-per-function": [2, 90],
21 22
 		"max-params": [2, 4],
22 23
 		"max-statements": 0,

+ 19
- 0
node_modules/get-intrinsic/CHANGELOG.md View File

@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5 5
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6 6
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
 
8
+## [v1.2.1](https://github.com/ljharb/get-intrinsic/compare/v1.2.0...v1.2.1) - 2023-05-13
9
+
10
+### Commits
11
+
12
+- [Fix] avoid a crash in envs without `__proto__` [`7bad8d0`](https://github.com/ljharb/get-intrinsic/commit/7bad8d061bf8721733b58b73a2565af2b6756b64)
13
+- [Dev Deps] update `es-abstract` [`c60e6b7`](https://github.com/ljharb/get-intrinsic/commit/c60e6b7b4cf9660c7f27ed970970fd55fac48dc5)
14
+
15
+## [v1.2.0](https://github.com/ljharb/get-intrinsic/compare/v1.1.3...v1.2.0) - 2023-01-19
16
+
17
+### Commits
18
+
19
+- [actions] update checkout action [`ca6b12f`](https://github.com/ljharb/get-intrinsic/commit/ca6b12f31eaacea4ea3b055e744cd61623385ffb)
20
+- [Dev Deps] update `@ljharb/eslint-config`, `es-abstract`, `object-inspect`, `tape` [`41a3727`](https://github.com/ljharb/get-intrinsic/commit/41a3727d0026fa04273ae216a5f8e12eefd72da8)
21
+- [Fix] ensure `Error.prototype` is undeniable [`c511e97`](https://github.com/ljharb/get-intrinsic/commit/c511e97ae99c764c4524b540dee7a70757af8da3)
22
+- [Dev Deps] update `aud`, `es-abstract`, `tape` [`1bef8a8`](https://github.com/ljharb/get-intrinsic/commit/1bef8a8fd439ebb80863199b6189199e0851ac67)
23
+- [Dev Deps] update `aud`, `es-abstract` [`0d41f16`](https://github.com/ljharb/get-intrinsic/commit/0d41f16bcd500bc28b7bfc98043ebf61ea081c26)
24
+- [New] add `BigInt64Array` and `BigUint64Array` [`a6cca25`](https://github.com/ljharb/get-intrinsic/commit/a6cca25f29635889b7e9bd669baf9e04be90e48c)
25
+- [Tests] use `gopd` [`ecf7722`](https://github.com/ljharb/get-intrinsic/commit/ecf7722240d15cfd16edda06acf63359c10fb9bd)
26
+
8 27
 ## [v1.1.3](https://github.com/ljharb/get-intrinsic/compare/v1.1.2...v1.1.3) - 2022-09-12
9 28
 
10 29
 ### Commits

+ 25
- 8
node_modules/get-intrinsic/index.js View File

@@ -43,18 +43,23 @@ var ThrowTypeError = $gOPD
43 43
 	: throwTypeError;
44 44
 
45 45
 var hasSymbols = require('has-symbols')();
46
+var hasProto = require('has-proto')();
46 47
 
47
-var getProto = Object.getPrototypeOf || function (x) { return x.__proto__; }; // eslint-disable-line no-proto
48
+var getProto = Object.getPrototypeOf || (
49
+	hasProto
50
+		? function (x) { return x.__proto__; } // eslint-disable-line no-proto
51
+		: null
52
+);
48 53
 
49 54
 var needsEval = {};
50 55
 
51
-var TypedArray = typeof Uint8Array === 'undefined' ? undefined : getProto(Uint8Array);
56
+var TypedArray = typeof Uint8Array === 'undefined' || !getProto ? undefined : getProto(Uint8Array);
52 57
 
53 58
 var INTRINSICS = {
54 59
 	'%AggregateError%': typeof AggregateError === 'undefined' ? undefined : AggregateError,
55 60
 	'%Array%': Array,
56 61
 	'%ArrayBuffer%': typeof ArrayBuffer === 'undefined' ? undefined : ArrayBuffer,
57
-	'%ArrayIteratorPrototype%': hasSymbols ? getProto([][Symbol.iterator]()) : undefined,
62
+	'%ArrayIteratorPrototype%': hasSymbols && getProto ? getProto([][Symbol.iterator]()) : undefined,
58 63
 	'%AsyncFromSyncIteratorPrototype%': undefined,
59 64
 	'%AsyncFunction%': needsEval,
60 65
 	'%AsyncGenerator%': needsEval,
@@ -62,6 +67,8 @@ var INTRINSICS = {
62 67
 	'%AsyncIteratorPrototype%': needsEval,
63 68
 	'%Atomics%': typeof Atomics === 'undefined' ? undefined : Atomics,
64 69
 	'%BigInt%': typeof BigInt === 'undefined' ? undefined : BigInt,
70
+	'%BigInt64Array%': typeof BigInt64Array === 'undefined' ? undefined : BigInt64Array,
71
+	'%BigUint64Array%': typeof BigUint64Array === 'undefined' ? undefined : BigUint64Array,
65 72
 	'%Boolean%': Boolean,
66 73
 	'%DataView%': typeof DataView === 'undefined' ? undefined : DataView,
67 74
 	'%Date%': Date,
@@ -82,10 +89,10 @@ var INTRINSICS = {
82 89
 	'%Int32Array%': typeof Int32Array === 'undefined' ? undefined : Int32Array,
83 90
 	'%isFinite%': isFinite,
84 91
 	'%isNaN%': isNaN,
85
-	'%IteratorPrototype%': hasSymbols ? getProto(getProto([][Symbol.iterator]())) : undefined,
92
+	'%IteratorPrototype%': hasSymbols && getProto ? getProto(getProto([][Symbol.iterator]())) : undefined,
86 93
 	'%JSON%': typeof JSON === 'object' ? JSON : undefined,
87 94
 	'%Map%': typeof Map === 'undefined' ? undefined : Map,
88
-	'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols ? undefined : getProto(new Map()[Symbol.iterator]()),
95
+	'%MapIteratorPrototype%': typeof Map === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Map()[Symbol.iterator]()),
89 96
 	'%Math%': Math,
90 97
 	'%Number%': Number,
91 98
 	'%Object%': Object,
@@ -98,10 +105,10 @@ var INTRINSICS = {
98 105
 	'%Reflect%': typeof Reflect === 'undefined' ? undefined : Reflect,
99 106
 	'%RegExp%': RegExp,
100 107
 	'%Set%': typeof Set === 'undefined' ? undefined : Set,
101
-	'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols ? undefined : getProto(new Set()[Symbol.iterator]()),
108
+	'%SetIteratorPrototype%': typeof Set === 'undefined' || !hasSymbols || !getProto ? undefined : getProto(new Set()[Symbol.iterator]()),
102 109
 	'%SharedArrayBuffer%': typeof SharedArrayBuffer === 'undefined' ? undefined : SharedArrayBuffer,
103 110
 	'%String%': String,
104
-	'%StringIteratorPrototype%': hasSymbols ? getProto(''[Symbol.iterator]()) : undefined,
111
+	'%StringIteratorPrototype%': hasSymbols && getProto ? getProto(''[Symbol.iterator]()) : undefined,
105 112
 	'%Symbol%': hasSymbols ? Symbol : undefined,
106 113
 	'%SyntaxError%': $SyntaxError,
107 114
 	'%ThrowTypeError%': ThrowTypeError,
@@ -117,6 +124,16 @@ var INTRINSICS = {
117 124
 	'%WeakSet%': typeof WeakSet === 'undefined' ? undefined : WeakSet
118 125
 };
119 126
 
127
+if (getProto) {
128
+	try {
129
+		null.error; // eslint-disable-line no-unused-expressions
130
+	} catch (e) {
131
+		// https://github.com/tc39/proposal-shadowrealm/pull/384#issuecomment-1364264229
132
+		var errorProto = getProto(getProto(e));
133
+		INTRINSICS['%Error.prototype%'] = errorProto;
134
+	}
135
+}
136
+
120 137
 var doEval = function doEval(name) {
121 138
 	var value;
122 139
 	if (name === '%AsyncFunction%') {
@@ -132,7 +149,7 @@ var doEval = function doEval(name) {
132 149
 		}
133 150
 	} else if (name === '%AsyncIteratorPrototype%') {
134 151
 		var gen = doEval('%AsyncGenerator%');
135
-		if (gen) {
152
+		if (gen && getProto) {
136 153
 			value = getProto(gen.prototype);
137 154
 		}
138 155
 	}

+ 8
- 6
node_modules/get-intrinsic/package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
 	"name": "get-intrinsic",
3
-	"version": "1.1.3",
3
+	"version": "1.2.1",
4 4
 	"description": "Get and robustly cache all JS language-level intrinsics at first require time",
5 5
 	"main": "index.js",
6 6
 	"exports": {
@@ -48,24 +48,25 @@
48 48
 	},
49 49
 	"homepage": "https://github.com/ljharb/get-intrinsic#readme",
50 50
 	"devDependencies": {
51
-		"@ljharb/eslint-config": "^21.0.0",
52
-		"aud": "^2.0.0",
51
+		"@ljharb/eslint-config": "^21.0.1",
52
+		"aud": "^2.0.2",
53 53
 		"auto-changelog": "^2.4.0",
54 54
 		"call-bind": "^1.0.2",
55
-		"es-abstract": "^1.20.2",
55
+		"es-abstract": "^1.21.2",
56 56
 		"es-value-fixtures": "^1.4.2",
57 57
 		"eslint": "=8.8.0",
58 58
 		"evalmd": "^0.0.19",
59 59
 		"for-each": "^0.3.3",
60
+		"gopd": "^1.0.1",
60 61
 		"make-async-function": "^1.0.0",
61 62
 		"make-async-generator-function": "^1.0.0",
62 63
 		"make-generator-function": "^2.0.0",
63 64
 		"mock-property": "^1.0.0",
64 65
 		"npmignore": "^0.3.0",
65 66
 		"nyc": "^10.3.2",
66
-		"object-inspect": "^1.12.2",
67
+		"object-inspect": "^1.12.3",
67 68
 		"safe-publish-latest": "^2.0.0",
68
-		"tape": "^5.6.0"
69
+		"tape": "^5.6.3"
69 70
 	},
70 71
 	"auto-changelog": {
71 72
 		"output": "CHANGELOG.md",
@@ -78,6 +79,7 @@
78 79
 	"dependencies": {
79 80
 		"function-bind": "^1.1.1",
80 81
 		"has": "^1.0.3",
82
+		"has-proto": "^1.0.1",
81 83
 		"has-symbols": "^1.0.3"
82 84
 	},
83 85
 	"testling": {

+ 1
- 1
node_modules/get-intrinsic/test/GetIntrinsic.js View File

@@ -12,7 +12,7 @@ var mockProperty = require('mock-property');
12 12
 
13 13
 var callBound = require('call-bind/callBound');
14 14
 var v = require('es-value-fixtures');
15
-var $gOPD = require('es-abstract/helpers/getOwnPropertyDescriptor');
15
+var $gOPD = require('gopd');
16 16
 var DefinePropertyOrThrow = require('es-abstract/2021/DefinePropertyOrThrow');
17 17
 
18 18
 var $isProto = callBound('%Object.prototype.isPrototypeOf%');

+ 14
- 0
node_modules/is-typed-array/CHANGELOG.md View File

@@ -5,6 +5,20 @@ All notable changes to this project will be documented in this file.
5 5
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6 6
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
 
8
+## [v1.1.12](https://github.com/inspect-js/is-typed-array/compare/v1.1.11...v1.1.12) - 2023-07-17
9
+
10
+### Commits
11
+
12
+- [Refactor] use `which-typed-array` for all internals [`7619405`](https://github.com/inspect-js/is-typed-array/commit/761940532de595f6721fed101b02814dcfa7fe4e)
13
+
14
+## [v1.1.11](https://github.com/inspect-js/is-typed-array/compare/v1.1.10...v1.1.11) - 2023-07-17
15
+
16
+### Commits
17
+
18
+- [Fix] `node &lt; v0.6` lacks proper Object toString behavior [`c94b90d`](https://github.com/inspect-js/is-typed-array/commit/c94b90dc6bc457783d6f8cc208415a49da0933b7)
19
+- [Robustness] use `call-bind` [`573b00b`](https://github.com/inspect-js/is-typed-array/commit/573b00b8deec42ac1ac262415e442ea0b7e1c96b)
20
+- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `object-inspect`, `tape` [`c88c2d4`](https://github.com/inspect-js/is-typed-array/commit/c88c2d479976110478fa4038fe8921251c06a163)
21
+
8 22
 ## [v1.1.10](https://github.com/inspect-js/is-typed-array/compare/v1.1.9...v1.1.10) - 2022-11-02
9 23
 
10 24
 ### Commits

+ 2
- 55
node_modules/is-typed-array/index.js View File

@@ -1,60 +1,7 @@
1 1
 'use strict';
2 2
 
3
-var forEach = require('for-each');
4
-var availableTypedArrays = require('available-typed-arrays');
5
-var callBound = require('call-bind/callBound');
6
-
7
-var $toString = callBound('Object.prototype.toString');
8
-var hasToStringTag = require('has-tostringtag/shams')();
9
-var gOPD = require('gopd');
10
-
11
-var g = typeof globalThis === 'undefined' ? global : globalThis;
12
-var typedArrays = availableTypedArrays();
13
-
14
-var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
15
-	for (var i = 0; i < array.length; i += 1) {
16
-		if (array[i] === value) {
17
-			return i;
18
-		}
19
-	}
20
-	return -1;
21
-};
22
-var $slice = callBound('String.prototype.slice');
23
-var toStrTags = {};
24
-var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
25
-if (hasToStringTag && gOPD && getPrototypeOf) {
26
-	forEach(typedArrays, function (typedArray) {
27
-		var arr = new g[typedArray]();
28
-		if (Symbol.toStringTag in arr) {
29
-			var proto = getPrototypeOf(arr);
30
-			var descriptor = gOPD(proto, Symbol.toStringTag);
31
-			if (!descriptor) {
32
-				var superProto = getPrototypeOf(proto);
33
-				descriptor = gOPD(superProto, Symbol.toStringTag);
34
-			}
35
-			toStrTags[typedArray] = descriptor.get;
36
-		}
37
-	});
38
-}
39
-
40
-var tryTypedArrays = function tryAllTypedArrays(value) {
41
-	var anyTrue = false;
42
-	forEach(toStrTags, function (getter, typedArray) {
43
-		if (!anyTrue) {
44
-			try {
45
-				anyTrue = getter.call(value) === typedArray;
46
-			} catch (e) { /**/ }
47
-		}
48
-	});
49
-	return anyTrue;
50
-};
3
+var whichTypedArray = require('which-typed-array');
51 4
 
52 5
 module.exports = function isTypedArray(value) {
53
-	if (!value || typeof value !== 'object') { return false; }
54
-	if (!hasToStringTag || !(Symbol.toStringTag in value)) {
55
-		var tag = $slice($toString(value), 8, -1);
56
-		return $indexOf(typedArrays, tag) > -1;
57
-	}
58
-	if (!gOPD) { return false; }
59
-	return tryTypedArrays(value);
6
+	return !!whichTypedArray(value);
60 7
 };

+ 8
- 10
node_modules/is-typed-array/package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
 	"name": "is-typed-array",
3
-	"version": "1.1.10",
3
+	"version": "1.1.12",
4 4
 	"author": {
5 5
 		"name": "Jordan Harband",
6 6
 		"email": "ljharb@gmail.com",
@@ -58,27 +58,25 @@
58 58
 		"@@toStringTag"
59 59
 	],
60 60
 	"dependencies": {
61
-		"available-typed-arrays": "^1.0.5",
62
-		"call-bind": "^1.0.2",
63
-		"for-each": "^0.3.3",
64
-		"gopd": "^1.0.1",
65
-		"has-tostringtag": "^1.0.0"
61
+		"which-typed-array": "^1.1.11"
66 62
 	},
67 63
 	"devDependencies": {
68
-		"@ljharb/eslint-config": "^21.0.0",
69
-		"aud": "^2.0.1",
64
+		"@ljharb/eslint-config": "^21.1.0",
65
+		"aud": "^2.0.3",
70 66
 		"auto-changelog": "^2.4.0",
71 67
 		"eslint": "=8.8.0",
72 68
 		"evalmd": "^0.0.19",
69
+		"for-each": "^0.3.3",
70
+		"has-tostringtag": "^1.0.0",
73 71
 		"in-publish": "^2.0.1",
74 72
 		"is-callable": "^1.2.7",
75 73
 		"make-arrow-function": "^1.2.0",
76 74
 		"make-generator-function": "^2.0.0",
77 75
 		"npmignore": "^0.3.0",
78 76
 		"nyc": "^10.3.2",
79
-		"object-inspect": "^1.12.2",
77
+		"object-inspect": "^1.12.3",
80 78
 		"safe-publish-latest": "^2.0.0",
81
-		"tape": "^5.6.1"
79
+		"tape": "^5.6.5"
82 80
 	},
83 81
 	"testling": {
84 82
 		"files": "test/index.js",

+ 15
- 0
node_modules/which-typed-array/CHANGELOG.md View File

@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5 5
 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
6 6
 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7 7
 
8
+## [v1.1.11](https://github.com/inspect-js/which-typed-array/compare/v1.1.10...v1.1.11) - 2023-07-17
9
+
10
+### Commits
11
+
12
+- [Fix] `node &lt; v0.6` lacks proper Object toString behavior [`b8fd654`](https://github.com/inspect-js/which-typed-array/commit/b8fd65479c0bd18385378cfae79750ebf7cb6ee7)
13
+- [Dev Deps] update `tape` [`e1734c9`](https://github.com/inspect-js/which-typed-array/commit/e1734c99d79880ab11efa55220498a7a1e887834)
14
+
15
+## [v1.1.10](https://github.com/inspect-js/which-typed-array/compare/v1.1.9...v1.1.10) - 2023-07-10
16
+
17
+### Commits
18
+
19
+- [actions] update rebase action to use reusable workflow [`2c10582`](https://github.com/inspect-js/which-typed-array/commit/2c105820d77274c079cb6d040cb348396e516ef5)
20
+- [Robustness] use `call-bind` [`b2335fd`](https://github.com/inspect-js/which-typed-array/commit/b2335fdfca80840995eea5e6fcfffc6d712279a1)
21
+- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`ad5e41b`](https://github.com/inspect-js/which-typed-array/commit/ad5e41ba18e7d23af1f9b211215c43a64bf75d70)
22
+
8 23
 ## [v1.1.9](https://github.com/inspect-js/which-typed-array/compare/v1.1.8...v1.1.9) - 2022-11-02
9 24
 
10 25
 ### Commits

+ 56
- 22
node_modules/which-typed-array/index.js View File

@@ -2,6 +2,7 @@
2 2
 
3 3
 var forEach = require('for-each');
4 4
 var availableTypedArrays = require('available-typed-arrays');
5
+var callBind = require('call-bind');
5 6
 var callBound = require('call-bind/callBound');
6 7
 var gOPD = require('gopd');
7 8
 
@@ -12,44 +13,77 @@ var g = typeof globalThis === 'undefined' ? global : globalThis;
12 13
 var typedArrays = availableTypedArrays();
13 14
 
14 15
 var $slice = callBound('String.prototype.slice');
15
-var toStrTags = {};
16 16
 var getPrototypeOf = Object.getPrototypeOf; // require('getprototypeof');
17
+
18
+var $indexOf = callBound('Array.prototype.indexOf', true) || function indexOf(array, value) {
19
+	for (var i = 0; i < array.length; i += 1) {
20
+		if (array[i] === value) {
21
+			return i;
22
+		}
23
+	}
24
+	return -1;
25
+};
26
+var cache = { __proto__: null };
17 27
 if (hasToStringTag && gOPD && getPrototypeOf) {
18 28
 	forEach(typedArrays, function (typedArray) {
19
-		if (typeof g[typedArray] === 'function') {
20
-			var arr = new g[typedArray]();
21
-			if (Symbol.toStringTag in arr) {
22
-				var proto = getPrototypeOf(arr);
23
-				var descriptor = gOPD(proto, Symbol.toStringTag);
24
-				if (!descriptor) {
25
-					var superProto = getPrototypeOf(proto);
26
-					descriptor = gOPD(superProto, Symbol.toStringTag);
27
-				}
28
-				toStrTags[typedArray] = descriptor.get;
29
+		var arr = new g[typedArray]();
30
+		if (Symbol.toStringTag in arr) {
31
+			var proto = getPrototypeOf(arr);
32
+			var descriptor = gOPD(proto, Symbol.toStringTag);
33
+			if (!descriptor) {
34
+				var superProto = getPrototypeOf(proto);
35
+				descriptor = gOPD(superProto, Symbol.toStringTag);
29 36
 			}
37
+			cache['$' + typedArray] = callBind(descriptor.get);
30 38
 		}
31 39
 	});
40
+} else {
41
+	forEach(typedArrays, function (typedArray) {
42
+		var arr = new g[typedArray]();
43
+		cache['$' + typedArray] = callBind(arr.slice);
44
+	});
32 45
 }
33 46
 
34 47
 var tryTypedArrays = function tryAllTypedArrays(value) {
35
-	var foundName = false;
36
-	forEach(toStrTags, function (getter, typedArray) {
37
-		if (!foundName) {
48
+	var found = false;
49
+	forEach(cache, function (getter, typedArray) {
50
+		if (!found) {
38 51
 			try {
39
-				var name = getter.call(value);
40
-				if (name === typedArray) {
41
-					foundName = name;
52
+				if ('$' + getter(value) === typedArray) {
53
+					found = $slice(typedArray, 1);
42 54
 				}
43
-			} catch (e) {}
55
+			} catch (e) { /**/ }
44 56
 		}
45 57
 	});
46
-	return foundName;
58
+	return found;
47 59
 };
48 60
 
49
-var isTypedArray = require('is-typed-array');
61
+var trySlices = function tryAllSlices(value) {
62
+	var found = false;
63
+	forEach(cache, function (getter, name) {
64
+		if (!found) {
65
+			try {
66
+				getter(value);
67
+				found = $slice(name, 1);
68
+			} catch (e) { /**/ }
69
+		}
70
+	});
71
+	return found;
72
+};
50 73
 
51 74
 module.exports = function whichTypedArray(value) {
52
-	if (!isTypedArray(value)) { return false; }
53
-	if (!hasToStringTag || !(Symbol.toStringTag in value)) { return $slice($toString(value), 8, -1); }
75
+	if (!value || typeof value !== 'object') { return false; }
76
+	if (!hasToStringTag) {
77
+		var tag = $slice($toString(value), 8, -1);
78
+		if ($indexOf(typedArrays, tag) > -1) {
79
+			return tag;
80
+		}
81
+		if (tag !== 'Object') {
82
+			return false;
83
+		}
84
+		// node < 0.6 hits here on real Typed Arrays
85
+		return trySlices(value);
86
+	}
87
+	if (!gOPD) { return null; } // unknown engine
54 88
 	return tryTypedArrays(value);
55 89
 };

+ 5
- 6
node_modules/which-typed-array/package.json View File

@@ -1,6 +1,6 @@
1 1
 {
2 2
 	"name": "which-typed-array",
3
-	"version": "1.1.9",
3
+	"version": "1.1.11",
4 4
 	"author": {
5 5
 		"name": "Jordan Harband",
6 6
 		"email": "ljharb@gmail.com",
@@ -62,12 +62,11 @@
62 62
 		"call-bind": "^1.0.2",
63 63
 		"for-each": "^0.3.3",
64 64
 		"gopd": "^1.0.1",
65
-		"has-tostringtag": "^1.0.0",
66
-		"is-typed-array": "^1.1.10"
65
+		"has-tostringtag": "^1.0.0"
67 66
 	},
68 67
 	"devDependencies": {
69
-		"@ljharb/eslint-config": "^21.0.0",
70
-		"aud": "^2.0.1",
68
+		"@ljharb/eslint-config": "^21.1.0",
69
+		"aud": "^2.0.3",
71 70
 		"auto-changelog": "^2.4.0",
72 71
 		"eslint": "=8.8.0",
73 72
 		"in-publish": "^2.0.1",
@@ -77,7 +76,7 @@
77 76
 		"npmignore": "^0.3.0",
78 77
 		"nyc": "^10.3.2",
79 78
 		"safe-publish-latest": "^2.0.0",
80
-		"tape": "^5.6.1"
79
+		"tape": "^5.6.5"
81 80
 	},
82 81
 	"testling": {
83 82
 		"files": "test/index.js",

+ 1
- 1
node_modules/which-typed-array/test/index.js View File

@@ -90,7 +90,7 @@ test('Typed Arrays', function (t) {
90 90
 		var TypedArray = global[typedArray];
91 91
 		if (isCallable(TypedArray)) {
92 92
 			var arr = new TypedArray(10);
93
-			t.equal(typedArray, whichTypedArray(arr), 'new ' + typedArray + '(10) is typed array of type ' + typedArray);
93
+			t.equal(whichTypedArray(arr), typedArray, 'new ' + typedArray + '(10) is typed array of type ' + typedArray);
94 94
 		} else {
95 95
 			t.comment('# SKIP ' + typedArray + ' is not supported');
96 96
 		}

+ 3144
- 106
package-lock.json
File diff suppressed because it is too large
View File


+ 8
- 0
package.json View File

@@ -8,6 +8,7 @@
8 8
     "start": "npm run build && npm run launch",
9 9
     "build": "npm run clean && npm run tsc",
10 10
     "launch": "node lib/launcher.js",
11
+    "test": "npm run clean && npm run build && mocha --bail=true lib/test/Test.js",
11 12
     "tsc": "tsc"
12 13
   },
13 14
   "author": "",
@@ -18,7 +19,14 @@
18 19
     "zod": "^3.21.4"
19 20
   },
20 21
   "devDependencies": {
22
+    "@types/chai": "^4.3.6",
23
+    "@types/expect": "^1.20.4",
24
+    "@types/mocha": "^5.2.7",
21 25
     "@types/node": "^18.11.9",
26
+    "chai": "^4.3.4",
27
+    "chai-as-promised": "^7.1.1",
28
+    "mocha": "^6.2.0",
29
+    "ts-mocha": "^6.0.0",
22 30
     "typescript": "^4.9.3"
23 31
   },
24 32
   "files": [

+ 48
- 0
src/RJSVM/datawriter/datawriter.ts View File

@@ -0,0 +1,48 @@
1
+import { xrpIO } from "xrpio";
2
+
3
+type Wallet = {
4
+    address: string,
5
+    secret: string
6
+}
7
+
8
+type DatawriterConfig = {
9
+    receiveAddress: string
10
+    sendWallet: Wallet
11
+    xrpNode: string
12
+    contractAddress: string
13
+}
14
+
15
+export class Datawriter {
16
+
17
+    constructor(private config: DatawriterConfig) {
18
+    }
19
+
20
+
21
+    async callEndpoint(endpointName: string, parameter: any, fee?: number) {
22
+        const xrpio: xrpIO = new xrpIO(this.config.xrpNode)
23
+        await xrpio.connect()
24
+        try{
25
+            const dataHash = await xrpio.treeWrite(
26
+                JSON.stringify(parameter),
27
+                this.config.receiveAddress,
28
+                this.config.sendWallet.secret
29
+            )
30
+            const hash = await xrpio.writeRaw(
31
+                {
32
+                    data: JSON.stringify({
33
+                        endpoint: endpointName,
34
+                        data: dataHash
35
+                    })
36
+                },
37
+                this.config.contractAddress,
38
+                this.config.sendWallet.secret,
39
+                undefined,
40
+                fee ? String(fee) : undefined
41
+            )
42
+        }catch(e){
43
+            console.log(e)
44
+        }finally{
45
+            await xrpio.disconnect()
46
+        }
47
+    }
48
+}

+ 78
- 11
src/RJSVM/framework/rjsvm.ts View File

@@ -1,8 +1,10 @@
1
-import { PaymentTx_T, ParameterizedFunction, Payload, RJSVM, RJSVM_Config, RJSVM_Endpoint, RJSVM_Implementations, payloadSchema, Function_Map, Endpoints_Of, State_Of, Generic_Ctor_ReturnType } from "./types"
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 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";
6
+import { payloadSchema } from "./schemas";
7
+import { InsufficientFeeError, RestrictedAccessError } from "../../util/errors";
6 8
 
7 9
 
8 10
 export abstract class RJSVM_Builder {
@@ -18,6 +20,10 @@ export abstract class RJSVM_Builder {
18 20
 
19 21
             private rippleApi: Xrpl
20 22
             private xrpIO: xrpIO
23
+            private syncTimeout: NodeJS.Timeout
24
+            private subscribers = {}
25
+            private onceSubscribers = {}
26
+
21 27
             public readonly definitions: Impl
22 28
 
23 29
             constructor(
@@ -27,7 +33,9 @@ export abstract class RJSVM_Builder {
27 33
 
28 34
                 
29 35
                 if(!XRP_ADDRESS.test(this.owner)){
30
-                    throw new Error(`Inavlid owner address ${this.owner}`)
36
+                    const err = new Error(`Inavlid owner address ${this.owner}`)
37
+                    this.emit('error', err)
38
+                    throw err
31 39
                 }
32 40
                 
33 41
 
@@ -45,18 +53,72 @@ export abstract class RJSVM_Builder {
45 53
                 await this.xrpIO.connect()
46 54
                 await this.sync()
47 55
 
56
+                /*
57
+                prototype for a new-block listener. would call on every closed ledger (i.e. new block)
58
+                could be used to implement limited lifetime states without requiring new events to trigger
59
+
48 60
                 this.rippleApi.on('ledgerClosed', (ledger: any) => {
49
-                    /*
50 61
                     console.log("---- Ledger ----")
51 62
                     console.log("index",ledger.ledger_index)
52 63
                     console.log("hash", ledger.ledger_hash)
53 64
                     console.log("---- /Ledger ----")
54
-                    */
55 65
                 })
66
+
56 67
                 await this.rippleApi.request({
57 68
                     command: 'subscribe',
58 69
                     streams: ['ledger']
59 70
                 })
71
+                */
72
+
73
+            }
74
+
75
+            public disconnect = async () => {
76
+                if(this.syncTimeout){
77
+                    clearTimeout(this.syncTimeout)
78
+                    this.syncTimeout = undefined
79
+                }
80
+                if(this.xrpIO){
81
+                    await this.xrpIO.disconnect()
82
+                    this.xrpIO = undefined
83
+                }
84
+                if(this.rippleApi){
85
+                    await this.rippleApi.disconnect()
86
+                    this.rippleApi = undefined
87
+                }
88
+
89
+                this.subscribers = {}
90
+            }
91
+
92
+            public on = (event: string, handler: ParameterizedFunction) => {
93
+                const availableEvents = ['error', ...Object.keys(this.definitions)]
94
+                if(!availableEvents.includes(event))
95
+                    return
96
+                
97
+                if(!this.subscribers[event])
98
+                    this.subscribers[event] = []
99
+
100
+                this.subscribers[event].push(handler)
101
+            }
102
+
103
+            public once = (event: string, handler: ParameterizedFunction) => {
104
+                const availableEvents = ['error', ...Object.keys(this.definitions)]
105
+                if(!availableEvents.includes(event))
106
+                    return
107
+                
108
+                if(!this.onceSubscribers[event])
109
+                    this.onceSubscribers[event] = []
110
+
111
+                this.onceSubscribers[event].push(handler)
112
+            }
113
+
114
+            private emit = (event: string, payload: any) => {
115
+                if(this.subscribers[event])
116
+                    this.subscribers[event].forEach(handler => handler(payload))
117
+                
118
+                if(this.onceSubscribers[event]){
119
+                    this.onceSubscribers[event].forEach(handler => handler(payload))
120
+                    this.onceSubscribers[event] = []
121
+                }
60 122
             }
61 123
 
62 124
             private handlePayload = async (tx: PaymentTx_T, payload: Payload) => {
@@ -65,15 +127,16 @@ export abstract class RJSVM_Builder {
65 127
                 }
66 128
 
67 129
                 const endpointDef: RJSVM_Endpoint<RJSVM, any> = this.definitions[payload.endpoint]
68
- 
69 130
 
70 131
                 if(endpointDef.visibility === 'owner' && tx.Account !== this.owner){
71
-                    console.log(`owner restricted endpoint "${payload.endpoint}" called from ${tx.hash}. But ${tx.Account} != ${this.owner}`)
132
+                    const err = new RestrictedAccessError(payload.endpoint, tx.hash, tx.Account, this.owner)
133
+                    this.emit('error', err)
72 134
                     return
73 135
                 }
74 136
 
75 137
                 if(endpointDef.fee && Number(tx.Amount) < endpointDef.fee){
76
-                    console.log(`Insufficient fee ${tx.hash}. Required ${endpointDef.fee}, was ${tx.Amount}`)
138
+                    const err = new InsufficientFeeError(tx.hash, Number(endpointDef.fee), Number(tx.Amount))
139
+                    this.emit('error', err)
77 140
                     return
78 141
                 }
79 142
                 
@@ -82,8 +145,9 @@ export abstract class RJSVM_Builder {
82 145
                     const jsonData = JSON.parse(data)
83 146
                     endpointDef.parameterSchema.parse(jsonData)
84 147
                     this[payload.endpoint].apply(this, [tx, jsonData])
148
+                    this.emit(payload.endpoint, jsonData)
85 149
                 } catch (err) {
86
-                    console.log(err)
150
+                    this.emit('error', err)
87 151
                     return
88 152
                 }
89 153
             }
@@ -97,7 +161,8 @@ export abstract class RJSVM_Builder {
97 161
                         try {
98 162
                             const data = DataParser.hex_to_ascii(memo.Memo.MemoData)
99 163
                             return JSON.parse(data)
100
-                        } catch (e) {
164
+                        } catch (err) {
165
+                            this.emit('error', err)
101 166
                             return
102 167
                         }
103 168
                     })
@@ -106,7 +171,9 @@ export abstract class RJSVM_Builder {
106 171
                         try {
107 172
                             const parsedPayload = payloadSchema.parse(payload)
108 173
                             this.handlePayload(tx, parsedPayload)
109
-                        } catch (e) {
174
+                        } catch (err) {
175
+                            this.emit('error', err)
176
+                            return
110 177
                         }
111 178
                     })
112 179
             }
@@ -140,7 +207,7 @@ export abstract class RJSVM_Builder {
140 207
                     //presence of no marker means we caught up to current block height
141 208
                     this.sync_block_height = resp.result.ledger_index_max + 1
142 209
                     //schedule the next sync
143
-                    setTimeout(this.sync, 10000)
210
+                    this.syncTimeout = setTimeout(this.sync, 10000)
144 211
                 }
145 212
             }
146 213
         }

+ 10
- 0
src/RJSVM/framework/schemas.ts View File

@@ -0,0 +1,10 @@
1
+import { z } from "zod";
2
+import { NON_ZERO_TX_HASH, XRP_ADDRESS } from "../../util/protocol.constants";
3
+
4
+export const payloadSchema = z.object({
5
+    endpoint: z.string(),
6
+    data: z.string()
7
+})
8
+
9
+export const xrp_address_schema = z.string().regex(XRP_ADDRESS, "Not a valid XRP address")
10
+export const xrp_transaction_hash_schema = z.string().regex(NON_ZERO_TX_HASH, "Not a valid XRP transaction hash")

+ 8
- 13
src/RJSVM/framework/types.ts View File

@@ -1,12 +1,16 @@
1 1
 import { z } from "zod";
2
+import { payloadSchema } from "./schemas";
2 3
 
3 4
 export abstract class RJSVM<State_T = any, Definitions_T extends Function_Map = Function_Map>{
4 5
     owner: string
5 6
     state: State_T
6 7
     sync_block_height: number
7 8
     config: RJSVM_Config
8
-    definitions: RJSVM_Implementations<any, Definitions_T>
9
+    definitions: RJSVM_Implementations<RJSVM<any, Definitions_T>, Definitions_T>
9 10
     connect: () => Promise<void>
11
+    disconnect: () => Promise<void>
12
+    on: (event: string, handler: ParameterizedFunction) => void
13
+    once: (event: string, handler: ParameterizedFunction) => void
10 14
 }
11 15
 
12 16
 export type Generic_Ctor_ReturnType<Ctor> 
@@ -14,8 +18,8 @@ export type Generic_Ctor_ReturnType<Ctor>
14 18
 : Ctor extends abstract new (...args:any) => infer A ? A
15 19
 : never
16 20
 
17
-export type State_Of<T extends RJSVM<any>> = T extends RJSVM<infer State_T> ? State_T : any
18
-export type Endpoints_Of<T extends RJSVM<any, any>> = T extends RJSVM<any, infer Endpoints_T> ? Endpoints_T : any
21
+export type State_Of<T extends RJSVM> = T extends RJSVM<infer State_T> ? State_T : any
22
+export type Endpoints_Of<T extends RJSVM> = T extends RJSVM<any, infer Endpoints_T> ? Endpoints_T : any
19 23
 
20 24
 
21 25
 export type PaymentTx_T = {
@@ -72,24 +76,15 @@ export type RJSVM_Interface<
72 76
     State_T = State_Of<RJSVM_T>,
73 77
     Definitions_T extends Function_Map = Endpoints_Of<RJSVM_T>,
74 78
 > = {
79
+    owner: string
75 80
     state: State_T
76 81
 } & {
77 82
     [K in keyof Definitions_T]?: RJSVM_EndpointHandler<RJSVM_T, Definitions_T, Definitions_T[K]>
78 83
 }
79 84
 
80
-export type RJSVM_InitState<State_T> = {
81
-    owner: string,
82
-    state: State_T
83
-}
84
-
85 85
 export type RJSVM_Config = {
86 86
     rippleNode: string,
87 87
     listeningAddress: string
88 88
 }
89 89
 
90
-export const payloadSchema = z.object({
91
-    endpoint: z.string(),
92
-    data: z.string()
93
-})
94
-
95 90
 export type Payload = z.infer<typeof payloadSchema>

+ 0
- 79
src/RJSVM/protocol/datawriter.ts View File

@@ -1,79 +0,0 @@
1
-import { xrpIO } from "xrpio";
2
-
3
-type Wallet = {
4
-    address: string,
5
-    secret: string
6
-}
7
-
8
-type DatawriterConfig = {
9
-    receiveAddress: string
10
-    sendWallet: Wallet
11
-    xrpNode: string
12
-    contractAddress: string
13
-}
14
-
15
-export class Datawriter {
16
-
17
-    constructor(private config: DatawriterConfig) {
18
-    }
19
-
20
-
21
-    async callEndpoint(endpointName: string, parameter: any, fee?: number) {
22
-        const xrpio: xrpIO = new xrpIO(this.config.xrpNode)
23
-        await xrpio.connect()
24
-        try{
25
-            const dataHash = await xrpio.treeWrite(
26
-                JSON.stringify(parameter),
27
-                this.config.receiveAddress,
28
-                this.config.sendWallet.secret
29
-            )
30
-            await xrpio.writeRaw(
31
-                {
32
-                    data: JSON.stringify({
33
-                        endpoint: endpointName,
34
-                        data: dataHash
35
-                    })
36
-                },
37
-                this.config.contractAddress,
38
-                this.config.sendWallet.secret,
39
-                undefined,
40
-                fee ? String(fee) : undefined
41
-            )
42
-        }catch(e){
43
-            console.log(e)
44
-        }finally{
45
-            await xrpio.disconnect()
46
-        }
47
-    }
48
-}
49
-
50
-(async () => {
51
-    const owner_dw = new Datawriter({
52
-        receiveAddress: "rDuXvMYNCEJCYDMFQykcafXhgi2NvMWqR",
53
-        sendWallet: {
54
-            address: "rUsPfG1hn6w6is28p5FUDWdMwvCo1iHrYq",
55
-            secret: "sEdTMicaTVmfsVMLhxrufyAzEQSnsaP"
56
-        },
57
-        xrpNode: "wss://s.altnet.rippletest.net:51233",
58
-        contractAddress: 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq'
59
-    })
60
-
61
-    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
62
-
63
-    const user_dw = new Datawriter({
64
-        receiveAddress: "rwqCiEr3SLF43rAduhCChkR2K1XDhiqx5g",
65
-        sendWallet: {
66
-            address: "rHWN4X3hbodryX8H1EoPvmMV7AFHngEiBe",
67
-            secret: "sEdTdLPWvz69UAUmt1zYijTyWheER9u"
68
-        },
69
-        xrpNode: "wss://s.altnet.rippletest.net:51233",
70
-        contractAddress: 'rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq'
71
-    })
72
-
73
-    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
74
-    //await user_dw.callEndpoint('restricted', { title: "user", body: "user", from: "user" })
75
-    //await owner_dw.callEndpoint('restricted', { title: "owner", body: "owner", from: "owner" })
76
-
77
-    await user_dw.callEndpoint('setTns', { hash: '01708abcF00636CE10E191FD782DBDC8F4076F28404BD88EBC31DE42DD084C0944B', name: 'test'})
78
-
79
-})()

+ 126
- 64
src/user-defined-contract.ts View File

@@ -1,78 +1,140 @@
1 1
 import { z } from "zod";
2
-import { RJSVM_Implementations, RJSVM_Interface, RJSVM, RJSVM_Config, RJSVM_InitState } from "./RJSVM/framework/types"
3
-import { RJSVM_Builder } from "./main";
4
-import { xrp_transaction_hash_schema } from "./util/schemas";
5
-
6
-const shoutSchema = z.object({
7
-    title: z.string(),
8
-    body: z.string(),
9
-    from: z.string(),
10
-    id: z.optional(z.string())
11
-})
12
-type Shout = z.infer<typeof shoutSchema>
13
-
14
-const tnsEntrySchema = z.object({
15
-    hash: xrp_transaction_hash_schema,
16
-    name: z.string(),
17
-})
18
-type TnsEntry = z.infer<typeof tnsEntrySchema>
19
-
20
-type State = {
21
-    shouts: Shout[]
22
-}
2
+import { RJSVM_Implementations, RJSVM_Interface, RJSVM, RJSVM_Config } from "../src/RJSVM/framework/types"
3
+import { RJSVM_Builder } from "../src/main";
4
+import { Wallet } from "xrpio";
5
+import { Datawriter } from "./RJSVM/datawriter/datawriter";
6
+import { makeTestnetWallet } from "../test/tools";
7
+import { xrp_transaction_hash_schema } from "./RJSVM/framework/schemas";
23 8
 
24
-type RJSVM_Endpoints = {
25
-    submit: (data: Shout) => void
26
-    restricted: (data: Shout) => void
27
-    setTns: (entry: TnsEntry) => void
28
-}
9
+const xrpNode = "wss://s.altnet.rippletest.net:51233"
10
+
11
+let ownerWallet: Wallet //the RJSVM owner
12
+let userWallet: Wallet //a RJSVM user
13
+let listeningWallet: Wallet //wallet the RJSVM listens to
14
+let drainWallet: Wallet //random wallet to send stuff to, could be anything
15
+let rjsvm: RJSVM
16
+
17
+let user_datawriter: Datawriter
18
+let owner_datawriter: Datawriter
19
+
20
+
21
+const setup = async () => {
22
+
23
+    [ownerWallet, listeningWallet, userWallet, drainWallet] = await Promise.all([makeTestnetWallet(),makeTestnetWallet(),makeTestnetWallet(),makeTestnetWallet()])
29 24
 
30
-abstract class RJSVM_Base
31
-extends RJSVM<State, RJSVM_Endpoints>
32
-implements RJSVM_Interface<RJSVM_Base> {
33
-    owner = "rUsPfG1hn6w6is28p5FUDWdMwvCo1iHrYq"
25
+    owner_datawriter = new Datawriter({
26
+        receiveAddress: drainWallet.address,
27
+        sendWallet: ownerWallet,
28
+        xrpNode: xrpNode,
29
+        contractAddress: listeningWallet.address
30
+    })
34 31
 
35
-    state: State = {
36
-        shouts: []
32
+    user_datawriter = new Datawriter({
33
+        receiveAddress: drainWallet.address,
34
+        sendWallet: userWallet,
35
+        xrpNode: xrpNode,
36
+        contractAddress: listeningWallet.address
37
+    })
38
+
39
+    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
40
+    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
41
+    //await user_dw.callEndpoint('restricted', { title: "user", body: "user", from: "user" })
42
+    //await owner_dw.callEndpoint('restricted', { title: "owner", body: "owner", from: "owner" })
43
+
44
+    // #########################
45
+    // Define parameter types
46
+    // #########################
47
+    
48
+    const shoutSchema = z.object({
49
+        title: z.string(),
50
+        body: z.string(),
51
+        from: z.string(),
52
+        id: z.optional(z.string())
53
+    })
54
+    type Shout = z.infer<typeof shoutSchema>
55
+
56
+    const tnsEntrySchema = z.object({
57
+        hash: xrp_transaction_hash_schema,
58
+        name: z.string(),
59
+    })
60
+    type TnsEntry = z.infer<typeof tnsEntrySchema>
61
+
62
+    type State = {
63
+        shouts: Shout[]
37 64
     }
38
-}
39 65
 
40
-const RJSVM_Contract: RJSVM_Implementations<RJSVM_Base> = {
41
-    submit: {
42
-        implementation: function (env, shout) {
43
-            this.state.shouts.unshift(shout)
44
-            console.log(shout)
45
-        },
46
-        visibility: 'public',
47
-        fee: 10,
48
-        parameterSchema: shoutSchema
49
-    },
50
-
51
-    restricted: {
52
-        implementation: function (env, shout) {
53
-            this.state.shouts.unshift(shout)
54
-            console.log(shout)
66
+    // #########################
67
+    // Define endpoints
68
+    // #########################
69
+
70
+    type RJSVM_Endpoints = {
71
+        submit: (data: Shout) => void
72
+        restricted: (data: Shout) => void
73
+        setTns: (entry: TnsEntry) => void
74
+    }
75
+
76
+    // #########################
77
+    // Define init state
78
+    // #########################
79
+
80
+    abstract class RJSVM_Base
81
+    extends RJSVM<State, RJSVM_Endpoints>
82
+    implements RJSVM_Interface<RJSVM_Base> {
83
+        owner = ownerWallet.address
84
+
85
+        state: State = {
86
+            shouts: []
87
+        }
88
+    }
89
+
90
+    // #########################
91
+    // Implement logic
92
+    // #########################
93
+
94
+    const RJSVM_Contract: RJSVM_Implementations<RJSVM_Base> = {
95
+        submit: {
96
+            implementation: function (env, shout) {
97
+                this.state.shouts.unshift(shout)
98
+                console.log(shout)
99
+            },
100
+            visibility: 'public',
101
+            fee: 10,
102
+            parameterSchema: shoutSchema
55 103
         },
56
-        visibility: 'owner',
57
-        parameterSchema: shoutSchema
58
-    },
59
-    setTns: {
60
-        implementation: function (env, tnsEntry) {
61
-            console.log(tnsEntry)
104
+
105
+        restricted: {
106
+            implementation: function (env, shout) {
107
+                this.state.shouts.unshift(shout)
108
+                console.log(shout)
109
+            },
110
+            visibility: 'owner',
111
+            parameterSchema: shoutSchema
62 112
         },
63
-        visibility: 'public',
64
-        parameterSchema: tnsEntrySchema,
113
+        setTns: {
114
+            implementation: function (env, tnsEntry) {
115
+                console.log(tnsEntry)
116
+            },
117
+            visibility: 'public',
118
+            parameterSchema: tnsEntrySchema,
119
+        }
65 120
     }
66
-}
67 121
 
122
+    // #########################
123
+    // Build and connect
124
+    // #########################
125
+    
126
+    const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
68 127
 
69
-const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
128
+    const conf: RJSVM_Config = {
129
+        listeningAddress: listeningWallet.address,
130
+        rippleNode: "wss://s.altnet.rippletest.net:51233"
131
+    }
70 132
 
71
-const conf: RJSVM_Config = {
72
-    listeningAddress: "rLaXUiYvW1EMns69PsAfwSLb2VgNtPpZwq",
73
-    rippleNode: "wss://s.altnet.rippletest.net:51233"
133
+    rjsvm = new Rjsvm(conf)
134
+    await rjsvm.connect()
74 135
 }
75 136
 
76
-const rjsvm = new Rjsvm(conf)
77
-
78
-rjsvm.connect()
137
+(async () => {
138
+        await setup()
139
+        await owner_datawriter.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
140
+})()

+ 11
- 0
src/util/errors.ts View File

@@ -0,0 +1,11 @@
1
+export class RestrictedAccessError extends Error{
2
+    constructor(endpoint:string, hash:string, callee:string, expecedCallee:string){
3
+        super(`Restricted endpoint "${endpoint}" called in ${hash}. But callee ${callee} is not owner ${expecedCallee}`)
4
+    }
5
+}
6
+
7
+export class InsufficientFeeError extends Error{
8
+    constructor(hash: string, requiredFee:number, suppliedFee:number){
9
+        super(`Insufficient fee in ${hash}. Required fee is ${requiredFee}, but was ${suppliedFee}`)
10
+    }
11
+}

+ 0
- 6
src/util/schemas.ts View File

@@ -1,6 +0,0 @@
1
-import { z } from "zod";
2
-import { XRP_ADDRESS } from "./protocol.constants";
3
-import { NON_ZERO_TX_HASH } from "xrpio";
4
-
5
-export const xrp_address_schema = z.string().regex(XRP_ADDRESS, "Not a valid XRP address")
6
-export const xrp_transaction_hash_schema = z.string().regex(NON_ZERO_TX_HASH, "Not a valid XRP transaction hash")

+ 247
- 0
test/Test.ts View File

@@ -0,0 +1,247 @@
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";
5
+
6
+//Test requirements
7
+import { assert, expect } from 'chai';
8
+import { describe, it } from "mocha";
9
+import { makeTestnetWallet } from "./tools";
10
+import { Wallet } from "xrpio";
11
+import { Datawriter } from "../src/RJSVM/datawriter/datawriter";
12
+import { InsufficientFeeError, RestrictedAccessError } from "../src/util/errors";
13
+var should = require('chai').should();
14
+var chai = require('chai');
15
+var chaiAsPromised = require('chai-as-promised');
16
+chai.use(chaiAsPromised);
17
+
18
+
19
+const xrpNode = "wss://s.altnet.rippletest.net:51233"
20
+
21
+let ownerWallet: Wallet //the RJSVM owner
22
+let userWallet: Wallet //a RJSVM user
23
+let listeningWallet: Wallet //wallet the RJSVM listens to
24
+let drainWallet: Wallet //random wallet to send stuff to, could be any user-controlled secondary wallet
25
+let rjsvm: RJSVM
26
+
27
+let user_datawriter: Datawriter
28
+let owner_datawriter: Datawriter
29
+
30
+
31
+const setup = async () => {
32
+
33
+    [ownerWallet, listeningWallet, userWallet, drainWallet] = await Promise.all([makeTestnetWallet(), makeTestnetWallet(), makeTestnetWallet(), makeTestnetWallet()])
34
+
35
+    owner_datawriter = new Datawriter({
36
+        receiveAddress: drainWallet.address,
37
+        sendWallet: ownerWallet,
38
+        xrpNode: xrpNode,
39
+        contractAddress: listeningWallet.address
40
+    })
41
+
42
+    user_datawriter = new Datawriter({
43
+        receiveAddress: drainWallet.address,
44
+        sendWallet: userWallet,
45
+        xrpNode: xrpNode,
46
+        contractAddress: listeningWallet.address
47
+    })
48
+
49
+    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
50
+    //await owner_dw.callEndpoint('submit', { title: "1", body: "2", from: "3" }, 100)
51
+    //await user_dw.callEndpoint('restricted', { title: "user", body: "user", from: "user" })
52
+    //await owner_dw.callEndpoint('restricted', { title: "owner", body: "owner", from: "owner" })
53
+
54
+    // #########################
55
+    // Define parameter types
56
+    // #########################
57
+
58
+    const shoutSchema = z.object({
59
+        title: z.string(),
60
+        body: z.string(),
61
+        from: z.string(),
62
+        id: z.optional(z.string())
63
+    })
64
+    type Shout = z.infer<typeof shoutSchema>
65
+
66
+    type State = {
67
+        shouts: Shout[]
68
+    }
69
+
70
+    // #########################
71
+    // Define endpoints
72
+    // #########################
73
+
74
+    type RJSVM_Endpoints = {
75
+        submit: (data: Shout) => void
76
+        restricted: (data: Shout) => void
77
+    }
78
+
79
+    // #########################
80
+    // Define init state
81
+    // #########################
82
+
83
+    abstract class RJSVM_Base
84
+        extends RJSVM<State, RJSVM_Endpoints>
85
+        implements RJSVM_Interface<RJSVM_Base> {
86
+        owner = ownerWallet.address
87
+
88
+        state: State = {
89
+            shouts: []
90
+        }
91
+    }
92
+
93
+    // #########################
94
+    // Implement logic
95
+    // #########################
96
+
97
+    const RJSVM_Contract: RJSVM_Implementations<RJSVM_Base> = {
98
+        submit: {
99
+            implementation: function (env, shout) {
100
+                this.state.shouts.unshift(shout)
101
+            },
102
+            visibility: 'public',
103
+            fee: 10,
104
+            parameterSchema: shoutSchema
105
+        },
106
+
107
+        restricted: {
108
+            implementation: function (env, shout) {
109
+                this.state.shouts.unshift(shout)
110
+            },
111
+            visibility: 'owner',
112
+            parameterSchema: shoutSchema
113
+        },
114
+    }
115
+
116
+    // #########################
117
+    // Build and connect
118
+    // #########################
119
+
120
+    const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract);
121
+
122
+    const conf: RJSVM_Config = {
123
+        listeningAddress: listeningWallet.address,
124
+        rippleNode: xrpNode
125
+    }
126
+
127
+    rjsvm = new Rjsvm(conf)
128
+    await rjsvm.connect()
129
+}
130
+
131
+describe('RJSVM basic functions', () => {
132
+
133
+    before(async function () {
134
+        this.timeout(10000)
135
+        await setup()
136
+    })
137
+
138
+    after(async () => {
139
+        await rjsvm.disconnect()
140
+    })
141
+
142
+    it('Env contains the payload carrying transaction', function (done) {
143
+        this.timeout(30000)
144
+
145
+        makeTestnetWallet().then(async testWallet => {
146
+            //create a mock RJSVM
147
+            abstract class RJSVM_Base
148
+            extends RJSVM<undefined, { testEndpoint: () => void }>
149
+            implements RJSVM_Interface<RJSVM_Base> {
150
+                owner = ownerWallet.address
151
+                state = undefined
152
+            }
153
+
154
+            //Implementation of the 'test' endpoint
155
+            const RJSVM_Contract: RJSVM_Implementations<RJSVM_Base> = {
156
+                testEndpoint: {
157
+                    implementation: function (env) {
158
+
159
+                        expect(env.Account).to.be.equal(userWallet.address)
160
+                        expect(env.Amount).to.be.equal('1')
161
+                        expect(env.Destination).to.be.equal(testWallet.address)
162
+                        expect(Number(env.Fee)).to.be.greaterThanOrEqual(10)
163
+                        expect(env.LastLedgerSequence).to.be.a('number')
164
+
165
+                        expect(env.Memos).to.be.an('Array')
166
+                        const memo = JSON.parse(DataParser.hex_to_ascii(env.Memos[0].Memo.MemoData))
167
+                        expect(memo.endpoint).to.be.equal('testEndpoint')
168
+
169
+                        expect(env.Sequence).to.be.a('number')
170
+                        expect(env.SigningPubKey).to.be.a('string')
171
+                        expect(env.TransactionType).to.be.equal('Payment')
172
+                        expect(env.TxnSignature).to.be.a('string')
173
+                        expect(env.date).to.be.a('number')
174
+                        expect(env.hash).to.be.a('string')
175
+                        expect(env.inLedger).to.be.a('number')
176
+                        expect(env.ledger_index).to.be.a('number')
177
+
178
+                        runnable.disconnect()
179
+                        done()
180
+                    },
181
+                    visibility: 'public',
182
+                    parameterSchema: z.any()
183
+                },
184
+            }
185
+
186
+            const Rjsvm = RJSVM_Builder.from(RJSVM_Base, RJSVM_Contract)
187
+            const runnable = new Rjsvm({listeningAddress: testWallet.address,rippleNode: xrpNode})
188
+            await runnable.connect()
189
+
190
+            const dw = new Datawriter({
191
+                contractAddress: testWallet.address,
192
+                sendWallet: userWallet,
193
+                receiveAddress: drainWallet.address,
194
+                xrpNode: xrpNode
195
+            })
196
+            dw.callEndpoint('testEndpoint', "")
197
+
198
+        })
199
+    })
200
+
201
+    it('Called endpoint triggers in RJSVM', function (done) {
202
+        this.timeout(30000)
203
+
204
+        const data = { title: "1", body: "2", from: "3" };
205
+        rjsvm.once('submit', (payload) => {
206
+            expect(payload).to.be.an('object')
207
+            expect(payload).to.deep.equal(data)
208
+            done()
209
+        })
210
+        owner_datawriter.callEndpoint('submit', data, 10)
211
+    })
212
+
213
+    it('Calling an endpoint with insufficient fee fails', function (done) {
214
+        this.timeout(30000)
215
+
216
+        const data = { title: "f", body: "f", from: "f" };
217
+        rjsvm.once('error', (err) => {
218
+            expect(err).to.be.instanceOf(InsufficientFeeError)
219
+            done()
220
+        })
221
+        owner_datawriter.callEndpoint('submit', data, 1)
222
+    })
223
+
224
+    it('Restricted endpoint can be called by owner', function (done) {
225
+        this.timeout(30000)
226
+
227
+        const data = { title: "11", body: "22", from: "33" };
228
+        rjsvm.once('restricted', (payload) => {
229
+            expect(payload).to.be.an('object')
230
+            expect(payload).to.deep.equal(data)
231
+            done()
232
+        })
233
+        owner_datawriter.callEndpoint('restricted', data)
234
+    })
235
+
236
+
237
+    it('Restricted endpoint cannot be called by non-owner', function (done) {
238
+        this.timeout(30000)
239
+
240
+        const data = { title: "e", body: "e", from: "e" };
241
+        rjsvm.once('error', (err) => {
242
+            expect(err).to.be.instanceOf(RestrictedAccessError)
243
+            done()
244
+        })
245
+        user_datawriter.callEndpoint('restricted', data)
246
+    })
247
+})

+ 16
- 0
test/tools.ts View File

@@ -0,0 +1,16 @@
1
+type Wallet = {secret: string, address:string }
2
+
3
+export const makeTestnetWallet = () : Promise<Wallet> => fetch('https://faucet.altnet.rippletest.net/accounts', {
4
+    method: 'POST',
5
+    headers: {
6
+        'Accept': 'application/json',
7
+        'Content-Type': 'application/json'
8
+    },
9
+}).then((raw:any) => {
10
+    return raw.json().then(content => {
11
+        return({
12
+            secret: content.account.secret,
13
+            address: content.account.address
14
+        });
15
+    })
16
+});

Loading…
Cancel
Save