dhali-js 2.0.0 → 3.0.1
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 +118 -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 +313 -300
- package/src/dhali/DhaliXrplChannelManager.js +5 -7
- package/src/dhali/configUtils.js +5 -13
- package/src/dhali/utils.js +44 -0
- package/src/index.js +4 -2
- package/tests/DhaliChannelManager.test.js +3 -3
- package/tests/DhaliEthChannelManager.test.js +76 -49
- package/tests/utils.test.js +70 -0
|
@@ -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,85 @@ 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
|
-
|
|
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
|
+
let token;
|
|
47
|
+
try {
|
|
48
|
+
token = await manager.getAuthToken();
|
|
49
|
+
} catch (error) {
|
|
50
|
+
if (error.name === "ChannelNotFound") {
|
|
51
|
+
await manager.deposit(1000000); // Deposit 1 XRP
|
|
52
|
+
token = await manager.getAuthToken();
|
|
53
|
+
} else {
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
51
56
|
}
|
|
57
|
+
console.log('XRPL Token:', token);
|
|
52
58
|
}
|
|
53
|
-
|
|
59
|
+
|
|
60
|
+
main();
|
|
54
61
|
```
|
|
55
62
|
|
|
56
63
|
### 2. Ethereum (EVM)
|
|
57
64
|
|
|
58
|
-
Uses `
|
|
65
|
+
Uses `viem` for EIP-712 signing.
|
|
59
66
|
|
|
60
67
|
```js
|
|
61
|
-
const {
|
|
68
|
+
const { createWalletClient, createPublicClient, http } = require('viem')
|
|
69
|
+
const { privateKeyToAccount } = require('viem/accounts')
|
|
70
|
+
const { mainnet, sepolia } = require('viem/chains')
|
|
62
71
|
const { DhaliChannelManager, getAvailableDhaliCurrencies } = require('dhali-js')
|
|
63
72
|
|
|
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
|
-
|
|
73
|
+
async function main() {
|
|
74
|
+
// 1. Setup Clients
|
|
75
|
+
const account = privateKeyToAccount('0x...')
|
|
76
|
+
const publicClient = createPublicClient({
|
|
77
|
+
chain: sepolia,
|
|
78
|
+
transport: http()
|
|
79
|
+
})
|
|
80
|
+
const walletClient = createWalletClient({
|
|
81
|
+
account,
|
|
82
|
+
chain: sepolia,
|
|
83
|
+
transport: http()
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
// 2. Fetch Available Currencies
|
|
87
|
+
const currencies = await getAvailableDhaliCurrencies()
|
|
88
|
+
const sepoliaUsdc = currencies.find(c => c.network === "SEPOLIA" && c.code === "USDC")
|
|
89
|
+
|
|
90
|
+
// 3. Instantiate Manager with Dynamic Config
|
|
91
|
+
const manager = DhaliChannelManager.evm(
|
|
92
|
+
walletClient,
|
|
93
|
+
publicClient,
|
|
94
|
+
sepoliaUsdc
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// 4. Generate Claim
|
|
98
|
+
let token;
|
|
99
|
+
try {
|
|
100
|
+
token = await manager.getAuthToken(1000000); // 1.00 USDC
|
|
101
|
+
} catch (error) {
|
|
102
|
+
if (error.name === "ChannelNotFound") {
|
|
103
|
+
await manager.deposit(1000000); // Deposit 1.00 USDC
|
|
104
|
+
token = await manager.getAuthToken(1000000);
|
|
105
|
+
} else {
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
91
108
|
}
|
|
109
|
+
console.log('EVM Token:', token);
|
|
92
110
|
}
|
|
93
|
-
|
|
111
|
+
|
|
112
|
+
main();
|
|
94
113
|
```
|
|
95
114
|
|
|
96
115
|
---
|
|
@@ -104,26 +123,64 @@ const url = `https://xrplcluster.dhali.io?payment-claim=${token}`
|
|
|
104
123
|
const response = await fetch(url, { method: 'POST', body: ... })
|
|
105
124
|
```
|
|
106
125
|
|
|
126
|
+
## Standardized x402 Payments
|
|
127
|
+
|
|
128
|
+
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).
|
|
129
|
+
|
|
130
|
+
```js
|
|
131
|
+
const { wrapAsX402PaymentPayload } = require('dhali-js');
|
|
132
|
+
|
|
133
|
+
async function main() {
|
|
134
|
+
// 1. Get your token as usual
|
|
135
|
+
const token = await manager.getAuthToken();
|
|
136
|
+
|
|
137
|
+
// 2. Get the payment requirement from the 'payment-required' header of a 402 response
|
|
138
|
+
const paymentRequirement = response.headers.get("payment-required");
|
|
139
|
+
|
|
140
|
+
// 3. Wrap into an x402 payload
|
|
141
|
+
const x402Payload = wrapAsX402PaymentPayload(token, paymentRequirement);
|
|
142
|
+
|
|
143
|
+
// 4. Use 'x402Payload' in the 'Payment' header
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
main();
|
|
147
|
+
```
|
|
148
|
+
|
|
107
149
|
---
|
|
108
150
|
|
|
109
151
|
## API Reference
|
|
110
152
|
|
|
111
|
-
### `DhaliChannelManager`
|
|
153
|
+
### `DhaliChannelManager` (Factory)
|
|
154
|
+
|
|
155
|
+
* `.xrpl(wallet, client, currency)`: Returns `DhaliXrplChannelManager`.
|
|
156
|
+
* `.evm(walletClient, publicClient, currency)`: Returns `DhaliEthChannelManager`.
|
|
112
157
|
|
|
113
|
-
|
|
114
|
-
|
|
158
|
+
### `DhaliEthChannelManager` & `DhaliXrplChannelManager`
|
|
159
|
+
|
|
160
|
+
Both managers provide the following core methods:
|
|
161
|
+
|
|
162
|
+
* `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.
|
|
163
|
+
* `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
164
|
|
|
116
165
|
### `getAvailableDhaliCurrencies()`
|
|
117
166
|
|
|
118
|
-
Returns a Promise resolving to:
|
|
167
|
+
Returns a Promise resolving to an array of `Currency` objects:
|
|
119
168
|
```js
|
|
120
|
-
|
|
121
|
-
"SEPOLIA":
|
|
122
|
-
"USDC": { currency: ..., destinationAddress: ... },
|
|
123
|
-
...
|
|
124
|
-
},
|
|
169
|
+
[
|
|
170
|
+
{ network: "SEPOLIA", code: "USDC", scale: 6, tokenAddress: "..." },
|
|
125
171
|
...
|
|
126
|
-
|
|
172
|
+
]
|
|
127
173
|
```
|
|
128
174
|
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Utilities
|
|
178
|
+
|
|
179
|
+
### `wrapAsX402PaymentPayload(token, paymentRequirement)`
|
|
180
|
+
|
|
181
|
+
Wraps an auth token and a payment requirement (retrieved from a 402 response header) into a base64-encoded x402-compliant payload.
|
|
182
|
+
|
|
183
|
+
* **`token`**: The base64-encoded claim generated by `getAuthToken()`.
|
|
184
|
+
* **`paymentRequirement`**: The base64-encoded requirement string from the `payment-required` header.
|
|
185
|
+
|
|
129
186
|
---
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dhali-js",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
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
|