@blockbima/xrpl-integration 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mohammed Mwijaa
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # XRPL Integration
2
+
3
+ A lightweight TypeScript wrapper for the XRP Ledger using [xrpl.js](https://github.com/XRPLF/xrpl.js). Implements a singleton pattern for easy integration into any application.
4
+
5
+ ## Features
6
+
7
+ - Singleton client pattern for connection management
8
+ - XRP and IOU token balance queries
9
+ - XRP and IOU token transfers
10
+ - Trustline verification
11
+ - Full TypeScript support with exported types
12
+ - Works with Mainnet, Testnet, and Devnet
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install xrpl-integration
18
+ ```
19
+
20
+ ## Quick Start
21
+
22
+ ```typescript
23
+ import { XRPLClient, NETWORKS } from "xrpl-integration";
24
+ import { Wallet } from "xrpl";
25
+
26
+ // Get singleton instance (defaults to testnet)
27
+ const client = XRPLClient.getInstance(NETWORKS.TESTNET);
28
+
29
+ // Connect to the network
30
+ await client.connect();
31
+
32
+ // Check XRP balance
33
+ const balance = await client.getXRPBalance("rAddress...");
34
+ console.log(`Balance: ${balance.balance} XRP`);
35
+
36
+ // Disconnect when done
37
+ await client.disconnect();
38
+ ```
39
+
40
+ ## API Reference
41
+
42
+ ### Connection
43
+
44
+ ```typescript
45
+ // Get client instance
46
+ const client = XRPLClient.getInstance(networkUrl?: string);
47
+
48
+ // Connect/disconnect
49
+ await client.connect();
50
+ await client.disconnect();
51
+
52
+ // Check connection status
53
+ client.isConnected; // boolean
54
+
55
+ // Reset instance (for switching networks)
56
+ await XRPLClient.resetInstance();
57
+ ```
58
+
59
+ ### Balance Queries
60
+
61
+ ```typescript
62
+ // XRP balance
63
+ const xrpBalance = await client.getXRPBalance(address);
64
+ // Returns: { address, balance, balanceDrops }
65
+
66
+ // IOU token balance
67
+ const iouBalance = await client.getIOUBalance(address, currency, issuer);
68
+ // Returns: { address, currency, issuer, balance }
69
+ ```
70
+
71
+ ### Transfers
72
+
73
+ ```typescript
74
+ // Send XRP
75
+ const result = await client.sendXRP({
76
+ wallet, // xrpl Wallet instance
77
+ destination, // recipient address
78
+ amount, // amount in XRP (not drops)
79
+ destinationTag?, // optional
80
+ memo?, // optional
81
+ });
82
+
83
+ // Send IOU tokens
84
+ const result = await client.sendIOU({
85
+ wallet,
86
+ destination,
87
+ currency, // e.g., "USD"
88
+ issuer, // token issuer address
89
+ amount,
90
+ destinationTag?,
91
+ memo?,
92
+ });
93
+
94
+ // Returns: { success, hash, ledgerIndex, response }
95
+ ```
96
+
97
+ ### Trustlines
98
+
99
+ ```typescript
100
+ // Check specific trustline
101
+ const trustline = await client.checkTrustline(address, currency, issuer);
102
+ // Returns: { exists, currency, issuer, balance, limit, ... }
103
+
104
+ // Get all trustlines for an account
105
+ const trustlines = await client.getAllTrustlines(address);
106
+ ```
107
+
108
+ ### Testnet Utilities
109
+
110
+ ```typescript
111
+ // Fund a wallet on testnet/devnet
112
+ const wallet = await client.fundWallet();
113
+ // Or fund an existing wallet
114
+ const funded = await client.fundWallet(existingWallet);
115
+ ```
116
+
117
+ ## Network Constants
118
+
119
+ ```typescript
120
+ import { NETWORKS } from "xrpl-integration";
121
+
122
+ NETWORKS.MAINNET // wss://xrplcluster.com/
123
+ NETWORKS.MAINNET_RIPPLE // wss://s1.ripple.com/
124
+ NETWORKS.TESTNET // wss://s.altnet.rippletest.net:51233/
125
+ NETWORKS.DEVNET // wss://s.devnet.rippletest.net:51233/
126
+ ```
127
+
128
+ ## Error Handling
129
+
130
+ All methods throw `XRPLClientError` with specific error types:
131
+
132
+ ```typescript
133
+ import { XRPLClientError, XRPLClientErrorType } from "xrpl-integration";
134
+
135
+ try {
136
+ await client.getXRPBalance("invalid");
137
+ } catch (error) {
138
+ if (error instanceof XRPLClientError) {
139
+ switch (error.type) {
140
+ case XRPLClientErrorType.NOT_CONNECTED:
141
+ case XRPLClientErrorType.INVALID_ADDRESS:
142
+ case XRPLClientErrorType.ACCOUNT_NOT_FOUND:
143
+ case XRPLClientErrorType.TRANSACTION_FAILED:
144
+ // Handle specific error
145
+ }
146
+ }
147
+ }
148
+ ```
149
+
150
+ ## License
151
+
152
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=XRPLClient.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XRPLClient.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/XRPLClient.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect, beforeEach } from "@jest/globals";
2
+ import { XRPLClient } from "../client/XRPLClient.js";
3
+ import { NETWORKS, XRPLClientError, XRPLClientErrorType, } from "../types/index.js";
4
+ describe("XRPLClient", () => {
5
+ // Reset singleton before each test
6
+ beforeEach(async () => {
7
+ await XRPLClient.resetInstance();
8
+ });
9
+ describe("Singleton Pattern", () => {
10
+ it("should return the same instance on multiple calls", () => {
11
+ const instance1 = XRPLClient.getInstance();
12
+ const instance2 = XRPLClient.getInstance();
13
+ expect(instance1).toBe(instance2);
14
+ });
15
+ it("should use default testnet URL when no URL provided", () => {
16
+ const client = XRPLClient.getInstance();
17
+ expect(client.network).toBe(NETWORKS.TESTNET);
18
+ });
19
+ it("should use custom URL when provided on first call", () => {
20
+ const client = XRPLClient.getInstance(NETWORKS.MAINNET);
21
+ expect(client.network).toBe(NETWORKS.MAINNET);
22
+ });
23
+ it("should ignore URL on subsequent calls", () => {
24
+ XRPLClient.getInstance(NETWORKS.TESTNET);
25
+ const client2 = XRPLClient.getInstance(NETWORKS.MAINNET);
26
+ expect(client2.network).toBe(NETWORKS.TESTNET);
27
+ });
28
+ it("should reset instance correctly", async () => {
29
+ const client1 = XRPLClient.getInstance(NETWORKS.TESTNET);
30
+ await XRPLClient.resetInstance();
31
+ const client2 = XRPLClient.getInstance(NETWORKS.MAINNET);
32
+ expect(client2.network).toBe(NETWORKS.MAINNET);
33
+ expect(client1).not.toBe(client2);
34
+ });
35
+ it("should expose raw client", () => {
36
+ const client = XRPLClient.getInstance();
37
+ expect(client.rawClient).toBeDefined();
38
+ });
39
+ });
40
+ describe("Connection State", () => {
41
+ it("should start disconnected", () => {
42
+ const client = XRPLClient.getInstance();
43
+ expect(client.isConnected).toBe(false);
44
+ });
45
+ it("should not disconnect if not connected", async () => {
46
+ const client = XRPLClient.getInstance();
47
+ // Should not throw
48
+ await client.disconnect();
49
+ expect(client.isConnected).toBe(false);
50
+ });
51
+ });
52
+ describe("Validation Errors (without connection)", () => {
53
+ it("should throw NOT_CONNECTED for getXRPBalance when not connected", async () => {
54
+ const client = XRPLClient.getInstance();
55
+ await expect(client.getXRPBalance("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).rejects.toMatchObject({
56
+ type: XRPLClientErrorType.NOT_CONNECTED,
57
+ });
58
+ });
59
+ it("should throw NOT_CONNECTED for getIOUBalance when not connected", async () => {
60
+ const client = XRPLClient.getInstance();
61
+ await expect(client.getIOUBalance("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "USD", "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe")).rejects.toMatchObject({
62
+ type: XRPLClientErrorType.NOT_CONNECTED,
63
+ });
64
+ });
65
+ it("should throw NOT_CONNECTED for sendXRP when not connected", async () => {
66
+ const client = XRPLClient.getInstance();
67
+ await expect(client.sendXRP({
68
+ wallet: {},
69
+ destination: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
70
+ amount: "10",
71
+ })).rejects.toMatchObject({
72
+ type: XRPLClientErrorType.NOT_CONNECTED,
73
+ });
74
+ });
75
+ it("should throw NOT_CONNECTED for sendIOU when not connected", async () => {
76
+ const client = XRPLClient.getInstance();
77
+ await expect(client.sendIOU({
78
+ wallet: {},
79
+ destination: "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh",
80
+ currency: "USD",
81
+ issuer: "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe",
82
+ amount: "100",
83
+ })).rejects.toMatchObject({
84
+ type: XRPLClientErrorType.NOT_CONNECTED,
85
+ });
86
+ });
87
+ it("should throw NOT_CONNECTED for checkTrustline when not connected", async () => {
88
+ const client = XRPLClient.getInstance();
89
+ await expect(client.checkTrustline("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh", "USD", "rPT1Sjq2YGrBMTttX4GZHjKu9dyfzbpAYe")).rejects.toMatchObject({
90
+ type: XRPLClientErrorType.NOT_CONNECTED,
91
+ });
92
+ });
93
+ it("should throw NOT_CONNECTED for getAllTrustlines when not connected", async () => {
94
+ const client = XRPLClient.getInstance();
95
+ await expect(client.getAllTrustlines("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).rejects.toMatchObject({
96
+ type: XRPLClientErrorType.NOT_CONNECTED,
97
+ });
98
+ });
99
+ it("should throw NOT_CONNECTED for fundWallet when not connected", async () => {
100
+ const client = XRPLClient.getInstance();
101
+ await expect(client.fundWallet()).rejects.toMatchObject({
102
+ type: XRPLClientErrorType.NOT_CONNECTED,
103
+ });
104
+ });
105
+ });
106
+ describe("XRPLClientError", () => {
107
+ it("should create error with correct properties", () => {
108
+ const error = new XRPLClientError(XRPLClientErrorType.CONNECTION_ERROR, "Test error", { detail: "test" });
109
+ expect(error.type).toBe(XRPLClientErrorType.CONNECTION_ERROR);
110
+ expect(error.message).toBe("Test error");
111
+ expect(error.details).toEqual({ detail: "test" });
112
+ expect(error.name).toBe("XRPLClientError");
113
+ });
114
+ it("should be an instance of Error", () => {
115
+ const error = new XRPLClientError(XRPLClientErrorType.NOT_CONNECTED, "Test");
116
+ expect(error).toBeInstanceOf(Error);
117
+ expect(error).toBeInstanceOf(XRPLClientError);
118
+ });
119
+ });
120
+ });
121
+ //# sourceMappingURL=XRPLClient.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XRPLClient.test.js","sourceRoot":"","sources":["../../src/__tests__/XRPLClient.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,yBAAyB,CAAC;AACrD,OAAO,EACL,QAAQ,EACR,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;IAC1B,mCAAmC;IACnC,UAAU,CAAC,KAAK,IAAI,EAAE;QACpB,MAAM,UAAU,CAAC,aAAa,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;QACjC,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,SAAS,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YAC3C,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;YAC3D,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACxD,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;YAC/C,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,UAAU,CAAC,aAAa,EAAE,CAAC;YACjC,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC/C,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;YAClC,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;QAChC,EAAE,CAAC,2BAA2B,EAAE,GAAG,EAAE;YACnC,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,KAAK,IAAI,EAAE;YACtD,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,mBAAmB;YACnB,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;YAC1B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,wCAAwC,EAAE,GAAG,EAAE;QACtD,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;YAC/E,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,aAAa,CAAC,oCAAoC,CAAC,CAC3D,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iEAAiE,EAAE,KAAK,IAAI,EAAE;YAC/E,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,aAAa,CAClB,oCAAoC,EACpC,KAAK,EACL,oCAAoC,CACrC,CACF,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,OAAO,CAAC;gBACb,MAAM,EAAE,EAAS;gBACjB,WAAW,EAAE,oCAAoC;gBACjD,MAAM,EAAE,IAAI;aACb,CAAC,CACH,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,OAAO,CAAC;gBACb,MAAM,EAAE,EAAS;gBACjB,WAAW,EAAE,oCAAoC;gBACjD,QAAQ,EAAE,KAAK;gBACf,MAAM,EAAE,oCAAoC;gBAC5C,MAAM,EAAE,KAAK;aACd,CAAC,CACH,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,cAAc,CACnB,oCAAoC,EACpC,KAAK,EACL,oCAAoC,CACrC,CACF,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oEAAoE,EAAE,KAAK,IAAI,EAAE;YAClF,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CACV,MAAM,CAAC,gBAAgB,CAAC,oCAAoC,CAAC,CAC9D,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtB,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;YACxC,MAAM,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC;gBACtD,IAAI,EAAE,mBAAmB,CAAC,aAAa;aACxC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,6CAA6C,EAAE,GAAG,EAAE;YACrD,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,gBAAgB,EACpC,YAAY,EACZ,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;YAClD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,aAAa,EACjC,MAAM,CACP,CAAC;YACF,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,103 @@
1
+ import { describe, it, expect } from "@jest/globals";
2
+ import { NETWORKS, XRPLClientError, XRPLClientErrorType, } from "../types/index.js";
3
+ describe("Types", () => {
4
+ describe("NETWORKS", () => {
5
+ it("should have correct mainnet URL", () => {
6
+ expect(NETWORKS.MAINNET).toBe("wss://xrplcluster.com/");
7
+ });
8
+ it("should have correct mainnet ripple URL", () => {
9
+ expect(NETWORKS.MAINNET_RIPPLE).toBe("wss://s1.ripple.com/");
10
+ });
11
+ it("should have correct testnet URL", () => {
12
+ expect(NETWORKS.TESTNET).toBe("wss://s.altnet.rippletest.net:51233/");
13
+ });
14
+ it("should have correct devnet URL", () => {
15
+ expect(NETWORKS.DEVNET).toBe("wss://s.devnet.rippletest.net:51233/");
16
+ });
17
+ it("should be immutable (readonly)", () => {
18
+ // TypeScript enforces this at compile time, but we can verify the values exist
19
+ expect(Object.keys(NETWORKS)).toHaveLength(4);
20
+ });
21
+ });
22
+ describe("XRPLClientErrorType", () => {
23
+ it("should have CONNECTION_ERROR type", () => {
24
+ expect(XRPLClientErrorType.CONNECTION_ERROR).toBe("CONNECTION_ERROR");
25
+ });
26
+ it("should have NOT_CONNECTED type", () => {
27
+ expect(XRPLClientErrorType.NOT_CONNECTED).toBe("NOT_CONNECTED");
28
+ });
29
+ it("should have ACCOUNT_NOT_FOUND type", () => {
30
+ expect(XRPLClientErrorType.ACCOUNT_NOT_FOUND).toBe("ACCOUNT_NOT_FOUND");
31
+ });
32
+ it("should have TRUSTLINE_NOT_FOUND type", () => {
33
+ expect(XRPLClientErrorType.TRUSTLINE_NOT_FOUND).toBe("TRUSTLINE_NOT_FOUND");
34
+ });
35
+ it("should have INSUFFICIENT_BALANCE type", () => {
36
+ expect(XRPLClientErrorType.INSUFFICIENT_BALANCE).toBe("INSUFFICIENT_BALANCE");
37
+ });
38
+ it("should have TRANSACTION_FAILED type", () => {
39
+ expect(XRPLClientErrorType.TRANSACTION_FAILED).toBe("TRANSACTION_FAILED");
40
+ });
41
+ it("should have INVALID_ADDRESS type", () => {
42
+ expect(XRPLClientErrorType.INVALID_ADDRESS).toBe("INVALID_ADDRESS");
43
+ });
44
+ it("should have INVALID_AMOUNT type", () => {
45
+ expect(XRPLClientErrorType.INVALID_AMOUNT).toBe("INVALID_AMOUNT");
46
+ });
47
+ });
48
+ describe("XRPLClientError", () => {
49
+ it("should create error with type and message", () => {
50
+ const error = new XRPLClientError(XRPLClientErrorType.CONNECTION_ERROR, "Failed to connect");
51
+ expect(error).toBeInstanceOf(Error);
52
+ expect(error).toBeInstanceOf(XRPLClientError);
53
+ expect(error.type).toBe(XRPLClientErrorType.CONNECTION_ERROR);
54
+ expect(error.message).toBe("Failed to connect");
55
+ expect(error.name).toBe("XRPLClientError");
56
+ });
57
+ it("should create error with type, message, and details", () => {
58
+ const details = { code: 500, reason: "Network failure" };
59
+ const error = new XRPLClientError(XRPLClientErrorType.CONNECTION_ERROR, "Failed to connect", details);
60
+ expect(error.details).toEqual(details);
61
+ });
62
+ it("should handle undefined details", () => {
63
+ const error = new XRPLClientError(XRPLClientErrorType.NOT_CONNECTED, "Not connected");
64
+ expect(error.details).toBeUndefined();
65
+ });
66
+ it("should be throwable and catchable", () => {
67
+ expect(() => {
68
+ throw new XRPLClientError(XRPLClientErrorType.INVALID_ADDRESS, "Bad address");
69
+ }).toThrow(XRPLClientError);
70
+ });
71
+ it("should preserve prototype chain", () => {
72
+ const error = new XRPLClientError(XRPLClientErrorType.TRANSACTION_FAILED, "TX failed");
73
+ expect(error instanceof XRPLClientError).toBe(true);
74
+ expect(error instanceof Error).toBe(true);
75
+ });
76
+ it("should have correct stack trace", () => {
77
+ const error = new XRPLClientError(XRPLClientErrorType.ACCOUNT_NOT_FOUND, "Account not found");
78
+ expect(error.stack).toBeDefined();
79
+ expect(error.stack).toContain("XRPLClientError");
80
+ });
81
+ it("should work with different error types", () => {
82
+ const errorTypes = Object.values(XRPLClientErrorType);
83
+ errorTypes.forEach((type) => {
84
+ const error = new XRPLClientError(type, `Error of type ${type}`);
85
+ expect(error.type).toBe(type);
86
+ });
87
+ });
88
+ it("should handle complex details objects", () => {
89
+ const complexDetails = {
90
+ nested: {
91
+ deep: {
92
+ value: 123,
93
+ },
94
+ },
95
+ array: [1, 2, 3],
96
+ nullValue: null,
97
+ };
98
+ const error = new XRPLClientError(XRPLClientErrorType.TRANSACTION_FAILED, "Complex error", complexDetails);
99
+ expect(error.details).toEqual(complexDetails);
100
+ });
101
+ });
102
+ });
103
+ //# sourceMappingURL=types.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.test.js","sourceRoot":"","sources":["../../src/__tests__/types.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,QAAQ,EACR,eAAe,EACf,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAE3B,QAAQ,CAAC,OAAO,EAAE,GAAG,EAAE;IACrB,QAAQ,CAAC,UAAU,EAAE,GAAG,EAAE;QACxB,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACvE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,+EAA+E;YAC/E,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;QACnC,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QACxE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,gCAAgC,EAAE,GAAG,EAAE;YACxC,MAAM,CAAC,mBAAmB,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oCAAoC,EAAE,GAAG,EAAE;YAC5C,MAAM,CAAC,mBAAmB,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAC1E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;YAC9C,MAAM,CAAC,mBAAmB,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAClD,qBAAqB,CACtB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,CAAC,mBAAmB,CAAC,oBAAoB,CAAC,CAAC,IAAI,CACnD,sBAAsB,CACvB,CAAC;QACJ,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qCAAqC,EAAE,GAAG,EAAE;YAC7C,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;QAC5E,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;YAC1C,MAAM,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,CAAC,mBAAmB,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACpE,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;QAC/B,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;YACnD,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,gBAAgB,EACpC,mBAAmB,CACpB,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,KAAK,CAAC,CAAC,cAAc,CAAC,eAAe,CAAC,CAAC;YAC9C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC;YAC9D,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;YAChD,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,OAAO,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,iBAAiB,EAAE,CAAC;YACzD,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,gBAAgB,EACpC,mBAAmB,EACnB,OAAO,CACR,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,aAAa,EACjC,eAAe,CAChB,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,aAAa,EAAE,CAAC;QACxC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,MAAM,CAAC,GAAG,EAAE;gBACV,MAAM,IAAI,eAAe,CACvB,mBAAmB,CAAC,eAAe,EACnC,aAAa,CACd,CAAC;YACJ,CAAC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAC9B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,kBAAkB,EACtC,WAAW,CACZ,CAAC;YAEF,MAAM,CAAC,KAAK,YAAY,eAAe,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACpD,MAAM,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;YACzC,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,iBAAiB,EACrC,mBAAmB,CACpB,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;YAClC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC;QACnD,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;YAChD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;YAEtD,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC1B,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,iBAAiB,IAAI,EAAE,CAAC,CAAC;gBACjE,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;YAC/C,MAAM,cAAc,GAAG;gBACrB,MAAM,EAAE;oBACN,IAAI,EAAE;wBACJ,KAAK,EAAE,GAAG;qBACX;iBACF;gBACD,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;gBAChB,SAAS,EAAE,IAAI;aAChB,CAAC;YAEF,MAAM,KAAK,GAAG,IAAI,eAAe,CAC/B,mBAAmB,CAAC,kBAAkB,EACtC,eAAe,EACf,cAAc,CACf,CAAC;YAEF,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAChD,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=utils.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,194 @@
1
+ import { jest, describe, it, expect } from "@jest/globals";
2
+ import { validateAddress, isValidAddress, convertXRPToDrops, convertDropsToXRP, validateAmount, formatCurrencyCode, encodeCurrencyCode, createMemo, decodeMemo, } from "../utils/index.js";
3
+ import { XRPLClientError, XRPLClientErrorType } from "../types/index.js";
4
+ // Mock xrpl module
5
+ jest.mock("xrpl", () => ({
6
+ isValidClassicAddress: jest.fn((address) => {
7
+ return /^r[1-9A-HJ-NP-Za-km-z]{24,34}$/.test(address);
8
+ }),
9
+ xrpToDrops: jest.fn((xrp) => {
10
+ const num = typeof xrp === "string" ? parseFloat(xrp) : xrp;
11
+ if (isNaN(num)) {
12
+ throw new Error("Invalid XRP amount");
13
+ }
14
+ return String(Math.floor(num * 1_000_000));
15
+ }),
16
+ dropsToXrp: jest.fn((drops) => {
17
+ const num = typeof drops === "string" ? parseInt(drops, 10) : drops;
18
+ if (isNaN(num)) {
19
+ throw new Error("Invalid drops amount");
20
+ }
21
+ return num / 1_000_000;
22
+ }),
23
+ }));
24
+ describe("Utils", () => {
25
+ describe("validateAddress", () => {
26
+ it("should return true for valid addresses", () => {
27
+ const validAddress = "rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh";
28
+ expect(validateAddress(validAddress)).toBe(true);
29
+ });
30
+ it("should throw XRPLClientError for invalid addresses", () => {
31
+ const invalidAddress = "invalid";
32
+ expect(() => validateAddress(invalidAddress)).toThrow(XRPLClientError);
33
+ expect(() => validateAddress(invalidAddress)).toThrow(/Invalid XRP Ledger address/);
34
+ });
35
+ it("should throw error with correct error type", () => {
36
+ try {
37
+ validateAddress("bad");
38
+ }
39
+ catch (error) {
40
+ expect(error).toBeInstanceOf(XRPLClientError);
41
+ expect(error.type).toBe(XRPLClientErrorType.INVALID_ADDRESS);
42
+ }
43
+ });
44
+ });
45
+ describe("isValidAddress", () => {
46
+ it("should return true for valid addresses", () => {
47
+ expect(isValidAddress("rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh")).toBe(true);
48
+ });
49
+ it("should return false for invalid addresses", () => {
50
+ expect(isValidAddress("invalid")).toBe(false);
51
+ expect(isValidAddress("")).toBe(false);
52
+ expect(isValidAddress("r")).toBe(false);
53
+ });
54
+ });
55
+ describe("convertXRPToDrops", () => {
56
+ it("should convert XRP to drops correctly", () => {
57
+ expect(convertXRPToDrops("1")).toBe("1000000");
58
+ expect(convertXRPToDrops("10")).toBe("10000000");
59
+ expect(convertXRPToDrops("0.5")).toBe("500000");
60
+ expect(convertXRPToDrops("0.000001")).toBe("1");
61
+ });
62
+ it("should throw XRPLClientError for invalid amounts", () => {
63
+ expect(() => convertXRPToDrops("invalid")).toThrow(XRPLClientError);
64
+ expect(() => convertXRPToDrops("invalid")).toThrow(/Invalid XRP amount/);
65
+ });
66
+ it("should throw error with correct error type", () => {
67
+ try {
68
+ convertXRPToDrops("not-a-number");
69
+ }
70
+ catch (error) {
71
+ expect(error).toBeInstanceOf(XRPLClientError);
72
+ expect(error.type).toBe(XRPLClientErrorType.INVALID_AMOUNT);
73
+ }
74
+ });
75
+ });
76
+ describe("convertDropsToXRP", () => {
77
+ it("should convert drops to XRP correctly", () => {
78
+ expect(convertDropsToXRP("1000000")).toBe("1");
79
+ expect(convertDropsToXRP("10000000")).toBe("10");
80
+ expect(convertDropsToXRP("500000")).toBe("0.5");
81
+ expect(convertDropsToXRP(1000000)).toBe("1");
82
+ });
83
+ it("should throw XRPLClientError for invalid amounts", () => {
84
+ expect(() => convertDropsToXRP("invalid")).toThrow(XRPLClientError);
85
+ expect(() => convertDropsToXRP("invalid")).toThrow(/Invalid drops amount/);
86
+ });
87
+ it("should throw error with correct error type", () => {
88
+ try {
89
+ convertDropsToXRP("not-a-number");
90
+ }
91
+ catch (error) {
92
+ expect(error).toBeInstanceOf(XRPLClientError);
93
+ expect(error.type).toBe(XRPLClientErrorType.INVALID_AMOUNT);
94
+ }
95
+ });
96
+ });
97
+ describe("validateAmount", () => {
98
+ it("should return true for valid positive amounts", () => {
99
+ expect(validateAmount("1")).toBe(true);
100
+ expect(validateAmount("0.5")).toBe(true);
101
+ expect(validateAmount("100.123")).toBe(true);
102
+ });
103
+ it("should throw XRPLClientError for invalid amounts", () => {
104
+ expect(() => validateAmount("0")).toThrow(XRPLClientError);
105
+ expect(() => validateAmount("-1")).toThrow(XRPLClientError);
106
+ expect(() => validateAmount("invalid")).toThrow(XRPLClientError);
107
+ expect(() => validateAmount("")).toThrow(XRPLClientError);
108
+ });
109
+ it("should throw error with correct error type and message", () => {
110
+ try {
111
+ validateAmount("-5");
112
+ }
113
+ catch (error) {
114
+ expect(error).toBeInstanceOf(XRPLClientError);
115
+ expect(error.type).toBe(XRPLClientErrorType.INVALID_AMOUNT);
116
+ expect(error.message).toContain("Must be a positive number");
117
+ }
118
+ });
119
+ });
120
+ describe("formatCurrencyCode", () => {
121
+ it("should return standard 3-character codes as-is", () => {
122
+ expect(formatCurrencyCode("USD")).toBe("USD");
123
+ expect(formatCurrencyCode("EUR")).toBe("EUR");
124
+ expect(formatCurrencyCode("XRP")).toBe("XRP");
125
+ });
126
+ it("should decode hex currency codes to readable strings", () => {
127
+ // "TEST" encoded as hex with padding
128
+ const hexCode = "5445535400000000000000000000000000000000";
129
+ expect(formatCurrencyCode(hexCode)).toBe("TEST");
130
+ });
131
+ it("should return hex code if decoding fails or is non-printable", () => {
132
+ // Non-printable characters
133
+ const nonPrintableHex = "0000000000000000000000000000000000000001";
134
+ expect(formatCurrencyCode(nonPrintableHex)).toBe(nonPrintableHex);
135
+ });
136
+ it("should handle edge cases", () => {
137
+ expect(formatCurrencyCode("")).toBe("");
138
+ expect(formatCurrencyCode("AB")).toBe("AB");
139
+ });
140
+ });
141
+ describe("encodeCurrencyCode", () => {
142
+ it("should return standard 3-character codes in uppercase", () => {
143
+ expect(encodeCurrencyCode("USD")).toBe("USD");
144
+ expect(encodeCurrencyCode("usd")).toBe("USD");
145
+ expect(encodeCurrencyCode("Eur")).toBe("EUR");
146
+ });
147
+ it("should return already hex-encoded codes as-is", () => {
148
+ const hexCode = "5445535400000000000000000000000000000000";
149
+ expect(encodeCurrencyCode(hexCode)).toBe(hexCode.toUpperCase());
150
+ });
151
+ it("should encode longer currency names as hex", () => {
152
+ const encoded = encodeCurrencyCode("TEST");
153
+ expect(encoded).toHaveLength(40);
154
+ expect(encoded).toMatch(/^[0-9A-F]+$/);
155
+ });
156
+ it("should handle special characters", () => {
157
+ const encoded = encodeCurrencyCode("LP Token");
158
+ expect(encoded).toHaveLength(40);
159
+ });
160
+ });
161
+ describe("createMemo", () => {
162
+ it("should create memo array with hex-encoded data", () => {
163
+ const memo = createMemo("Hello");
164
+ expect(memo).toHaveLength(1);
165
+ expect(memo[0]).toHaveProperty("Memo");
166
+ expect(memo[0]?.Memo).toHaveProperty("MemoData");
167
+ // "Hello" in hex
168
+ expect(memo[0]?.Memo.MemoData).toBe("48656C6C6F");
169
+ });
170
+ it("should handle empty strings", () => {
171
+ const memo = createMemo("");
172
+ expect(memo[0]?.Memo.MemoData).toBe("");
173
+ });
174
+ it("should handle unicode characters", () => {
175
+ const memo = createMemo("🚀");
176
+ expect(memo[0]?.Memo.MemoData).toBeTruthy();
177
+ });
178
+ });
179
+ describe("decodeMemo", () => {
180
+ it("should decode hex memo data to string", () => {
181
+ // "Hello" in hex
182
+ expect(decodeMemo("48656C6C6F")).toBe("Hello");
183
+ });
184
+ it("should handle non-hex input gracefully", () => {
185
+ // Buffer.from with 'hex' encoding returns empty buffer for invalid hex
186
+ const result = decodeMemo("zzzz");
187
+ expect(typeof result).toBe("string");
188
+ });
189
+ it("should handle empty strings", () => {
190
+ expect(decodeMemo("")).toBe("");
191
+ });
192
+ });
193
+ });
194
+ //# sourceMappingURL=utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.test.js","sourceRoot":"","sources":["../../src/__tests__/utils.test.ts"],"names":[],"mappings":"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"}