dhali-js 2.1.0 → 3.0.3

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.
@@ -29,4 +29,4 @@ jobs:
29
29
  run: npm test
30
30
 
31
31
  - name: Run lint
32
- run: npx tsc src/dhali/*.js --allowJs --checkJs --noEmit --moduleResolution node --module commonjs --target esnext
32
+ run: npx tsc src/dhali/*.js --allowJs --checkJs --noEmit --moduleResolution node --module commonjs --target esnext --skipLibCheck
package/README.md CHANGED
@@ -16,6 +16,9 @@ Includes support for **Machine-to-Machine (M2M) payments** using seamless off-ch
16
16
  npm install dhali-js
17
17
  ```
18
18
 
19
+ > [!TIP]
20
+ > The examples below use CommonJS (`require`). Because they use `await`, the code is wrapped in an `async function main() { ... }` which is called immediately. To run these, simply save them to a `.js` file and run `node document.js`.
21
+
19
22
  ---
20
23
 
21
24
  ## Quick Start: Machine-to-Machine Payments
@@ -28,69 +31,87 @@ Uses `xrpl.js` for local signing.
28
31
  const { Client, Wallet } = require('xrpl')
29
32
  const { DhaliChannelManager, ChannelNotFound, Currency } = require('dhali-js')
30
33
 
31
- const seed = "sXXX..."
32
- const wallet = Wallet.fromSeed(seed)
33
- const client = new Client("wss://s.altnet.rippletest.net:51233")
34
- await client.connect()
35
-
36
- const currency = new Currency("XRP", 6)
37
-
38
- // Use Factory
39
- const manager = DhaliChannelManager.xrpl(wallet, client, "XRPL.TESTNET", currency)
40
-
41
- // Generate Claim
42
- let token;
43
- try {
44
- token = await manager.getAuthToken();
45
- } catch (error) {
46
- if (error.name === "ChannelNotFound") {
47
- await manager.deposit(1000000); // Deposit 1 XRP
48
- token = await manager.getAuthToken();
49
- } else {
50
- throw error;
34
+ async function main() {
35
+ const seed = "sXXX..."
36
+ const wallet = Wallet.fromSeed(seed)
37
+ const client = new Client("wss://s.altnet.rippletest.net:51233")
38
+ await client.connect()
39
+
40
+ const currency = new Currency("XRPL.TESTNET", "XRP", 6)
41
+
42
+ // Use Factory
43
+ const manager = DhaliChannelManager.xrpl(wallet, client, currency)
44
+
45
+ // Generate Claim
46
+ const amount = Math.floor(1.0 * Math.pow(10, currency.scale)); // 1 XRP
47
+ let token;
48
+ try {
49
+ token = await manager.getAuthToken();
50
+ } catch (error) {
51
+ if (error.name === "ChannelNotFound") {
52
+ await manager.deposit(amount);
53
+ token = await manager.getAuthToken();
54
+ } else {
55
+ throw error;
56
+ }
51
57
  }
58
+ console.log('XRPL Token:', token);
52
59
  }
53
- console.log('XRPL Token:', token);
60
+
61
+ main();
54
62
  ```
55
63
 
56
64
  ### 2. Ethereum (EVM)
57
65
 
58
- Uses `ethers` (v6) for EIP-712 signing.
66
+ Uses `viem` for EIP-712 signing.
59
67
 
60
68
  ```js
61
- const { ethers } = require('ethers')
69
+ const { createWalletClient, createPublicClient, http } = require('viem')
70
+ const { privateKeyToAccount } = require('viem/accounts')
71
+ const { mainnet, sepolia } = require('viem/chains')
62
72
  const { DhaliChannelManager, getAvailableDhaliCurrencies } = require('dhali-js')
63
73
 
64
- // 1. Setup Signer
65
- const provider = new ethers.JsonRpcProvider("https://rpc.ankr.com/eth_sepolia")
66
- const signer = new ethers.Wallet("0x...", provider)
67
-
68
- // 2. Fetch Available Currencies
69
- const configs = await getAvailableDhaliCurrencies()
70
- const sepoliaUsdc = configs["SEPOLIA"]["USDC"]
71
-
72
- // 3. Instantiate Manager with Dynamic Config
73
- const manager = DhaliChannelManager.evm(
74
- signer,
75
- provider,
76
- "SEPOLIA",
77
- sepoliaUsdc.currency
78
- )
79
-
80
- // 4. Generate Claim
81
- // 4. Generate Claim
82
- let token;
83
- try {
84
- token = await manager.getAuthToken(1000000); // 1.00 USDC
85
- } catch (error) {
86
- if (error.name === "ChannelNotFound") {
87
- await manager.deposit(1000000); // Deposit 1.00 USDC
88
- token = await manager.getAuthToken(1000000);
89
- } else {
90
- throw error;
74
+ async function main() {
75
+ // 1. Setup Clients
76
+ const account = privateKeyToAccount('0x...')
77
+ const publicClient = createPublicClient({
78
+ chain: sepolia,
79
+ transport: http()
80
+ })
81
+ const walletClient = createWalletClient({
82
+ account,
83
+ chain: sepolia,
84
+ transport: http()
85
+ })
86
+
87
+ // 2. Fetch Available Currencies
88
+ const currencies = await getAvailableDhaliCurrencies()
89
+ const sepoliaUsdc = currencies.find(c => c.network === "SEPOLIA" && c.code === "USDC")
90
+
91
+ // 3. Instantiate Manager with Dynamic Config
92
+ const manager = DhaliChannelManager.evm(
93
+ walletClient,
94
+ publicClient,
95
+ sepoliaUsdc
96
+ )
97
+
98
+ // 4. Generate Claim
99
+ const amount = Math.floor(0.1 * Math.pow(10, sepoliaUsdc.scale)); // 0.10 USDC
100
+ let token;
101
+ try {
102
+ token = await manager.getAuthToken(amount);
103
+ } catch (error) {
104
+ if (error.name === "ChannelNotFound") {
105
+ await manager.deposit(amount);
106
+ token = await manager.getAuthToken(amount);
107
+ } else {
108
+ throw error;
109
+ }
91
110
  }
111
+ console.log('EVM Token:', token);
92
112
  }
93
- console.log('EVM Token:', token);
113
+
114
+ main();
94
115
  ```
95
116
 
96
117
  ---
@@ -104,26 +125,64 @@ const url = `https://xrplcluster.dhali.io?payment-claim=${token}`
104
125
  const response = await fetch(url, { method: 'POST', body: ... })
105
126
  ```
106
127
 
128
+ ## Standardized x402 Payments
129
+
130
+ For APIs that follow the x402 standard, you may need to wrap your auth token with the payment requirement (retrieved from the `payment-required` header of a 402 response).
131
+
132
+ ```js
133
+ const { wrapAsX402PaymentPayload } = require('dhali-js');
134
+
135
+ async function main() {
136
+ // 1. Get your token as usual
137
+ const token = await manager.getAuthToken();
138
+
139
+ // 2. Get the payment requirement from the 'payment-required' header of a 402 response
140
+ const paymentRequirement = response.headers.get("payment-required");
141
+
142
+ // 3. Wrap into an x402 payload
143
+ const x402Payload = wrapAsX402PaymentPayload(token, paymentRequirement);
144
+
145
+ // 4. Use 'x402Payload' in the 'Payment' header
146
+ }
147
+
148
+ main();
149
+ ```
150
+
107
151
  ---
108
152
 
109
153
  ## API Reference
110
154
 
111
- ### `DhaliChannelManager`
155
+ ### `DhaliChannelManager` (Factory)
156
+
157
+ * `.xrpl(wallet, client, currency)`: Returns `DhaliXrplChannelManager`.
158
+ * `.evm(walletClient, publicClient, currency)`: Returns `DhaliEthChannelManager`.
112
159
 
113
- * `.xrpl(wallet, client, protocol, currency)`: Returns `DhaliXrplChannelManager`.
114
- * `.evm(signer, provider, protocol, currency)`: Returns `DhaliEthChannelManager`.
160
+ ### `DhaliEthChannelManager` & `DhaliXrplChannelManager`
161
+
162
+ Both managers provide the following core methods:
163
+
164
+ * `async deposit(amount)`: Deposits funds into a payment channel. For EVM/XRPL, `amount` is in base units (wei/drops, etc). If no channel exists, it creates one; if it exists, it funds it.
165
+ * `async getAuthToken(amount = null)`: Generates a base64-encoded payment claim. If `amount` is provided, the claim is authorized up to that value. Defaults to total channel capacity if `amount` is `null`.
115
166
 
116
167
  ### `getAvailableDhaliCurrencies()`
117
168
 
118
- Returns a Promise resolving to:
169
+ Returns a Promise resolving to an array of `Currency` objects:
119
170
  ```js
120
- {
121
- "SEPOLIA": {
122
- "USDC": { currency: ..., destinationAddress: ... },
123
- ...
124
- },
171
+ [
172
+ { network: "SEPOLIA", code: "USDC", scale: 6, tokenAddress: "..." },
125
173
  ...
126
- }
174
+ ]
127
175
  ```
128
176
 
177
+ ---
178
+
179
+ ## Utilities
180
+
181
+ ### `wrapAsX402PaymentPayload(token, paymentRequirement)`
182
+
183
+ Wraps an auth token and a payment requirement (retrieved from a 402 response header) into a base64-encoded x402-compliant payload.
184
+
185
+ * **`token`**: The base64-encoded claim generated by `getAuthToken()`.
186
+ * **`paymentRequirement`**: The base64-encoded requirement string from the `payment-required` header.
187
+
129
188
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dhali-js",
3
- "version": "2.1.0",
3
+ "version": "3.0.3",
4
4
  "description": "A JavaScript library for managing XRPL payment channels and generating auth tokens for Dhali APIs",
5
5
  "main": "src/index.js",
6
6
  "type": "commonjs",
@@ -16,8 +16,8 @@
16
16
  ],
17
17
  "license": "MIT",
18
18
  "dependencies": {
19
- "ethers": "^6.0.0",
20
19
  "ripple-keypairs": "^2.0.0",
20
+ "viem": "^2.23.5",
21
21
  "xrpl": "^4.0.0"
22
22
  },
23
23
  "devDependencies": {
@@ -1,5 +1,6 @@
1
1
  class Currency {
2
- constructor(code, scale, tokenAddress = null) {
2
+ constructor(network, code, scale, tokenAddress = null) {
3
+ this.network = network;
3
4
  this.code = code;
4
5
  this.scale = scale;
5
6
  this.tokenAddress = tokenAddress;
@@ -5,30 +5,27 @@ const DhaliChannelManager = {
5
5
  /**
6
6
  * @param {import("xrpl").Wallet} wallet
7
7
  * @param {import("xrpl").Client} client
8
- * @param {string} protocol
9
8
  * @param {import("./Currency")} currency
10
9
  * @param {typeof fetch} [httpClient] - Injected HTTP client
11
10
  * @param {object} [publicConfig]
12
11
  * @returns {DhaliXrplChannelManager}
13
12
  */
14
- xrpl: (wallet, client, protocol, currency, httpClient, publicConfig) => {
15
- return new DhaliXrplChannelManager(wallet, client, protocol, currency, httpClient, publicConfig);
13
+ xrpl: (wallet, client, currency, httpClient, publicConfig) => {
14
+ return new DhaliXrplChannelManager(wallet, client, currency, httpClient, publicConfig);
16
15
  },
17
16
 
18
17
  /**
19
- * @param {import("ethers").Signer} signer
20
- * @param {import("ethers").Provider} provider
21
- * @param {string} protocol
18
+ * @param {import("viem").WalletClient} walletClient
19
+ * @param {import("viem").PublicClient} publicClient
22
20
  * @param {import("./Currency")} currency
23
21
  * @param {typeof fetch} [httpClient] - Injected HTTP client
24
22
  * @param {object} [publicConfig]
25
23
  * @returns {DhaliEthChannelManager}
26
24
  */
27
- evm: (signer, provider, protocol, currency, httpClient, publicConfig) => {
25
+ evm: (walletClient, publicClient, currency, httpClient, publicConfig) => {
28
26
  return new DhaliEthChannelManager(
29
- signer,
30
- provider,
31
- protocol,
27
+ walletClient,
28
+ publicClient,
32
29
  currency,
33
30
  httpClient,
34
31
  publicConfig