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.
- package/.github/workflows/tests.yaml +1 -1
- package/README.md +120 -61
- package/package.json +2 -2
- package/src/dhali/Currency.js +2 -1
- package/src/dhali/DhaliChannelManager.js +7 -10
- package/src/dhali/DhaliEthChannelManager.js +314 -300
- package/src/dhali/DhaliXrplChannelManager.js +6 -8
- package/src/dhali/configUtils.js +5 -13
- package/src/dhali/utils.js +8 -0
- package/src/index.js +1 -1
- package/tests/DhaliChannelManager.test.js +25 -3
- package/tests/DhaliEthChannelManager.test.js +116 -50
|
@@ -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
|
-
|
|
32
|
-
const
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
token
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
60
|
+
|
|
61
|
+
main();
|
|
54
62
|
```
|
|
55
63
|
|
|
56
64
|
### 2. Ethereum (EVM)
|
|
57
65
|
|
|
58
|
-
Uses `
|
|
66
|
+
Uses `viem` for EIP-712 signing.
|
|
59
67
|
|
|
60
68
|
```js
|
|
61
|
-
const {
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
-
|
|
114
|
-
|
|
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": "
|
|
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": {
|
package/src/dhali/Currency.js
CHANGED
|
@@ -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,
|
|
15
|
-
return new DhaliXrplChannelManager(wallet, client,
|
|
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("
|
|
20
|
-
* @param {import("
|
|
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: (
|
|
25
|
+
evm: (walletClient, publicClient, currency, httpClient, publicConfig) => {
|
|
28
26
|
return new DhaliEthChannelManager(
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
protocol,
|
|
27
|
+
walletClient,
|
|
28
|
+
publicClient,
|
|
32
29
|
currency,
|
|
33
30
|
httpClient,
|
|
34
31
|
publicConfig
|