privacycash-x402 1.0.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 +21 -0
- package/README.md +139 -0
- package/dist/examples/client-example.d.ts +13 -0
- package/dist/examples/client-example.d.ts.map +1 -0
- package/dist/examples/client-example.js +108 -0
- package/dist/examples/client-example.js.map +1 -0
- package/dist/examples/server-example.d.ts +13 -0
- package/dist/examples/server-example.d.ts.map +1 -0
- package/dist/examples/server-example.js +104 -0
- package/dist/examples/server-example.js.map +1 -0
- package/dist/src/client/index.d.ts +89 -0
- package/dist/src/client/index.d.ts.map +1 -0
- package/dist/src/client/index.js +259 -0
- package/dist/src/client/index.js.map +1 -0
- package/dist/src/config.d.ts +10 -0
- package/dist/src/config.d.ts.map +1 -0
- package/dist/src/config.js +16 -0
- package/dist/src/config.js.map +1 -0
- package/dist/src/errors/index.d.ts +81 -0
- package/dist/src/errors/index.d.ts.map +1 -0
- package/dist/src/errors/index.js +110 -0
- package/dist/src/errors/index.js.map +1 -0
- package/dist/src/index.d.ts +10 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +47 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/models/keypair.d.ts +27 -0
- package/dist/src/models/keypair.d.ts.map +1 -0
- package/dist/src/models/keypair.js +48 -0
- package/dist/src/models/keypair.js.map +1 -0
- package/dist/src/models/utxo.d.ts +50 -0
- package/dist/src/models/utxo.d.ts.map +1 -0
- package/dist/src/models/utxo.js +86 -0
- package/dist/src/models/utxo.js.map +1 -0
- package/dist/src/server/index.d.ts +67 -0
- package/dist/src/server/index.d.ts.map +1 -0
- package/dist/src/server/index.js +266 -0
- package/dist/src/server/index.js.map +1 -0
- package/dist/src/types/index.d.ts +67 -0
- package/dist/src/types/index.d.ts.map +1 -0
- package/dist/src/types/index.js +3 -0
- package/dist/src/types/index.js.map +1 -0
- package/dist/src/utils/constants.d.ts +29 -0
- package/dist/src/utils/constants.d.ts.map +1 -0
- package/dist/src/utils/constants.js +65 -0
- package/dist/src/utils/constants.js.map +1 -0
- package/dist/src/utils/encryption.d.ts +108 -0
- package/dist/src/utils/encryption.d.ts.map +1 -0
- package/dist/src/utils/encryption.js +420 -0
- package/dist/src/utils/encryption.js.map +1 -0
- package/dist/src/utils/logger.d.ts +10 -0
- package/dist/src/utils/logger.d.ts.map +1 -0
- package/dist/src/utils/logger.js +40 -0
- package/dist/src/utils/logger.js.map +1 -0
- package/dist/src/utils/utils.d.ts +65 -0
- package/dist/src/utils/utils.d.ts.map +1 -0
- package/dist/src/utils/utils.js +214 -0
- package/dist/src/utils/utils.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rohan Singla
|
|
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,139 @@
|
|
|
1
|
+
# p402 ( Private x402 SDK )
|
|
2
|
+
|
|
3
|
+
A privacy-preserving payment SDK for Solana implementing the HTTP 402 Payment Required protocol using [Privacy Cash](https://privacycash.org).
|
|
4
|
+
|
|
5
|
+
## What is This?
|
|
6
|
+
|
|
7
|
+
This SDK enables **private API monetization** on Solana. Users pay for API access through a privacy pool - the server receives payment but cannot link it to the user's identity.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
User deposits SOL → Privacy Pool → Anonymous payment → API Access
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Quick Start
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Install
|
|
17
|
+
npm install
|
|
18
|
+
|
|
19
|
+
# Terminal 1: Start server
|
|
20
|
+
npm run example:server
|
|
21
|
+
|
|
22
|
+
# Terminal 2: Run client
|
|
23
|
+
npm run example:client
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## How It Works
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
Client Server
|
|
30
|
+
│ │
|
|
31
|
+
├─── GET /api/premium ─────────────►│
|
|
32
|
+
│◄── 402 + Payment Quote ───────────┤
|
|
33
|
+
│ │
|
|
34
|
+
│ [Deposit to Privacy Pool] │
|
|
35
|
+
│ [Generate ZK Payment Proof] │
|
|
36
|
+
│ │
|
|
37
|
+
├─── GET /api + Payment Headers ───►│
|
|
38
|
+
│ [Verify] │
|
|
39
|
+
│ [Check Balance] │
|
|
40
|
+
│ [Prevent Double-Spend]│
|
|
41
|
+
│◄────── 200 + Premium Content ─────┤
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Usage
|
|
45
|
+
|
|
46
|
+
### Server
|
|
47
|
+
|
|
48
|
+
```typescript
|
|
49
|
+
import express from 'express';
|
|
50
|
+
import { X402PaymentServer } from 'privacycash-x402';
|
|
51
|
+
|
|
52
|
+
const server = new X402PaymentServer({
|
|
53
|
+
merchantWallet: 'YOUR_WALLET_ADDRESS',
|
|
54
|
+
rpcUrl: 'https://api.mainnet-beta.solana.com',
|
|
55
|
+
apiPrice: 10_000_000, // 0.01 SOL
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
const app = express();
|
|
59
|
+
app.get('/premium', server.middleware(), (req, res) => {
|
|
60
|
+
res.json({ data: 'Premium content!' });
|
|
61
|
+
});
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Client
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
import { Keypair } from '@solana/web3.js';
|
|
68
|
+
import { X402PaymentClient } from 'privacycash-x402';
|
|
69
|
+
|
|
70
|
+
const client = new X402PaymentClient({
|
|
71
|
+
rpcUrl: 'https://api.mainnet-beta.solana.com',
|
|
72
|
+
keypair: Keypair.fromSecretKey(yourKeypair),
|
|
73
|
+
mockMode: false, // Set true for testing without real SOL
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await client.initialize();
|
|
77
|
+
const result = await client.payForAccess('https://api.example.com/premium');
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Environment Variables
|
|
81
|
+
|
|
82
|
+
| Variable | Description | Default |
|
|
83
|
+
|----------|-------------|---------|
|
|
84
|
+
| `MERCHANT_WALLET` | Wallet to receive payments | - |
|
|
85
|
+
| `API_PRICE` | Price in lamports | `10000000` |
|
|
86
|
+
| `RPC_URL` | Solana RPC endpoint | devnet |
|
|
87
|
+
| `WALLET_KEYPAIR` | Client keypair (JSON array) | - |
|
|
88
|
+
| `MOCK_MODE` | Enable mock mode | `true` |
|
|
89
|
+
|
|
90
|
+
## Project Structure
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
src/
|
|
94
|
+
├── index.ts # Main exports
|
|
95
|
+
├── server/index.ts # X402PaymentServer
|
|
96
|
+
├── client/index.ts # X402PaymentClient
|
|
97
|
+
├── types/index.ts # TypeScript types
|
|
98
|
+
├── errors/index.ts # Error classes
|
|
99
|
+
└── utils/ # Encryption, constants
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Privacy Guarantees
|
|
103
|
+
|
|
104
|
+
- **Unlinkable**: Deposits and payments cannot be connected on-chain
|
|
105
|
+
- **Anonymous**: Server cannot identify who made the deposit
|
|
106
|
+
- **Zero-Knowledge**: Payment validity proven without revealing identity
|
|
107
|
+
- **Double-Spend Protected**: Each commitment can only be used once
|
|
108
|
+
|
|
109
|
+
## Primary Use Cases
|
|
110
|
+
|
|
111
|
+
| User Type | Example | Why p402? |
|
|
112
|
+
|-----------|---------|-----------|
|
|
113
|
+
| **Backend Services** | AI API paying for data APIs | Privacy between service providers |
|
|
114
|
+
| **CLI Tools** | Payment tools for developers | Programmatic private payments |
|
|
115
|
+
| **Bots/Automation** | Trading bots, monitoring services | Automated payments without linking activity |
|
|
116
|
+
| **B2B Integrations** | Company A's service paying Company B's API | Hide business relationships on-chain |
|
|
117
|
+
| **Privacy-first Businesses** | VPN providers, privacy tools | Users who specifically want unlinkable payments |
|
|
118
|
+
|
|
119
|
+
**Note:** This SDK requires full keypair access and is designed for server-side/CLI usage.
|
|
120
|
+
|
|
121
|
+
## Limitations
|
|
122
|
+
|
|
123
|
+
- **Mainnet Only**: Privacy Cash is deployed only on Solana mainnet
|
|
124
|
+
- **Mock Mode**: Use `mockMode: true` for development/demos without real SOL
|
|
125
|
+
- **Balance Proof**: Current implementation uses client-reported balance proofs (see Upcoming Updates)
|
|
126
|
+
|
|
127
|
+
### Security Note
|
|
128
|
+
|
|
129
|
+
Production deployments should await ZK proof integration.
|
|
130
|
+
|
|
131
|
+
### Roadmap
|
|
132
|
+
|
|
133
|
+
- [ ] ZK balance proof generation via Privacy Cash SDK
|
|
134
|
+
- [ ] Server-side proof verification against on-chain state
|
|
135
|
+
- [ ] Mainnet launch with full cryptographic guarantees
|
|
136
|
+
|
|
137
|
+
## License
|
|
138
|
+
|
|
139
|
+
MIT
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Cash x402 Client Example
|
|
3
|
+
*
|
|
4
|
+
* Make sure the server is running first: npm run example:server
|
|
5
|
+
*
|
|
6
|
+
* Environment variables:
|
|
7
|
+
* - WALLET_KEYPAIR: JSON array of keypair bytes (required)
|
|
8
|
+
* - RPC_URL: Solana RPC URL (default: devnet)
|
|
9
|
+
* - SERVER_URL: x402 server URL (default: http://localhost:3001)
|
|
10
|
+
* - MOCK_MODE: Set to "false" to use real Privacy Cash (requires mainnet)
|
|
11
|
+
*/
|
|
12
|
+
import 'dotenv/config';
|
|
13
|
+
//# sourceMappingURL=client-example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-example.d.ts","sourceRoot":"","sources":["../../examples/client-example.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,eAAe,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Privacy Cash x402 Client Example
|
|
4
|
+
*
|
|
5
|
+
* Make sure the server is running first: npm run example:server
|
|
6
|
+
*
|
|
7
|
+
* Environment variables:
|
|
8
|
+
* - WALLET_KEYPAIR: JSON array of keypair bytes (required)
|
|
9
|
+
* - RPC_URL: Solana RPC URL (default: devnet)
|
|
10
|
+
* - SERVER_URL: x402 server URL (default: http://localhost:3001)
|
|
11
|
+
* - MOCK_MODE: Set to "false" to use real Privacy Cash (requires mainnet)
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
require("dotenv/config");
|
|
15
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
16
|
+
const src_1 = require("../src");
|
|
17
|
+
// Load config from environment
|
|
18
|
+
const RPC_URL = process.env.RPC_URL || 'https://api.devnet.solana.com';
|
|
19
|
+
const SERVER_URL = process.env.SERVER_URL || 'http://localhost:3001';
|
|
20
|
+
const MOCK_MODE = process.env.MOCK_MODE !== 'false'; // Default to mock mode
|
|
21
|
+
/**
|
|
22
|
+
* Load keypair from environment
|
|
23
|
+
*/
|
|
24
|
+
function loadKeypair() {
|
|
25
|
+
if (!process.env.WALLET_KEYPAIR) {
|
|
26
|
+
console.error('Error: WALLET_KEYPAIR environment variable is required');
|
|
27
|
+
console.error('Then add to .env: WALLET_KEYPAIR=[...contents of wallet.json...]');
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
const keypairBytes = new Uint8Array(JSON.parse(process.env.WALLET_KEYPAIR));
|
|
32
|
+
return web3_js_1.Keypair.fromSecretKey(keypairBytes);
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
console.error('Error: Failed to parse WALLET_KEYPAIR');
|
|
36
|
+
console.error('Make sure it is a valid JSON array of 64 bytes');
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Main demo function
|
|
42
|
+
*/
|
|
43
|
+
async function main() {
|
|
44
|
+
console.log('\nPrivacy Cash x402 Client Demo\n');
|
|
45
|
+
console.log('==============================\n');
|
|
46
|
+
// Load keypair
|
|
47
|
+
const keypair = loadKeypair();
|
|
48
|
+
console.log(`Wallet: ${keypair.publicKey.toBase58()}`);
|
|
49
|
+
// Check wallet balance (skip in mock mode)
|
|
50
|
+
if (!MOCK_MODE) {
|
|
51
|
+
const connection = new web3_js_1.Connection(RPC_URL, 'confirmed');
|
|
52
|
+
const balance = await connection.getBalance(keypair.publicKey);
|
|
53
|
+
console.log(`Wallet SOL balance: ${balance / web3_js_1.LAMPORTS_PER_SOL} SOL`);
|
|
54
|
+
if (balance < 0.02 * web3_js_1.LAMPORTS_PER_SOL) {
|
|
55
|
+
console.log('\nWarning: Low SOL balance.');
|
|
56
|
+
console.log(`Address: ${keypair.publicKey.toBase58()}\n`);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Create x402 client
|
|
60
|
+
const client = new src_1.X402PaymentClient({
|
|
61
|
+
rpcUrl: RPC_URL,
|
|
62
|
+
keypair,
|
|
63
|
+
mockMode: MOCK_MODE,
|
|
64
|
+
});
|
|
65
|
+
if (MOCK_MODE) {
|
|
66
|
+
console.log('\n[MOCK MODE] Simulating p402 - no real transactions');
|
|
67
|
+
console.log('Set MOCK_MODE=false in .env to use real Privacy Cash (mainnet only)\n');
|
|
68
|
+
}
|
|
69
|
+
// Initialize client
|
|
70
|
+
console.log('\nInitializing client...');
|
|
71
|
+
await client.initialize();
|
|
72
|
+
// Try to access premium endpoint
|
|
73
|
+
console.log(`\nAccessing premium endpoint at ${SERVER_URL}/premium...`);
|
|
74
|
+
try {
|
|
75
|
+
const result = await client.payForAccess(`${SERVER_URL}/premium`);
|
|
76
|
+
if (result.success) {
|
|
77
|
+
console.log('\nPremium Content Unlocked!');
|
|
78
|
+
console.log('========================');
|
|
79
|
+
console.log(result.data);
|
|
80
|
+
if (result.paymentDetails) {
|
|
81
|
+
console.log('\nPayment Details:');
|
|
82
|
+
console.log(` Note Hash: ${result.paymentDetails.noteHash?.substring(0, 20)}...`);
|
|
83
|
+
console.log(` Verified: ${result.paymentDetails.verified}`);
|
|
84
|
+
}
|
|
85
|
+
console.log('\nPrivacy Achieved:');
|
|
86
|
+
console.log(' Your deposit is mixed with others in the pool');
|
|
87
|
+
console.log(' Server receives payment but cannot link it to your wallet');
|
|
88
|
+
console.log(' On-chain observers see anonymous deposit/withdrawal');
|
|
89
|
+
console.log(' Zero-knowledge proofs verify payment validity');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
catch (error) {
|
|
93
|
+
console.error('\nPayment failed:', error);
|
|
94
|
+
if (error instanceof Error) {
|
|
95
|
+
if (error.message.includes('insufficient funds')) {
|
|
96
|
+
console.log('\nTip: You need SOL in your wallet to deposit into the privacy pool');
|
|
97
|
+
console.log(`Get devnet SOL: https://faucet.solana.com/`);
|
|
98
|
+
console.log(`Your address: ${keypair.publicKey.toBase58()}`);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
// Run the demo
|
|
104
|
+
main().catch((err) => {
|
|
105
|
+
console.error('Demo failed:', err);
|
|
106
|
+
process.exit(1);
|
|
107
|
+
});
|
|
108
|
+
//# sourceMappingURL=client-example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client-example.js","sourceRoot":"","sources":["../../examples/client-example.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAEH,yBAAuB;AACvB,6CAAwE;AACxE,gCAA2C;AAE3C,+BAA+B;AAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,+BAA+B,CAAC;AACvE,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,uBAAuB,CAAC;AACrE,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,KAAK,OAAO,CAAC,CAAC,uBAAuB;AAE5E;;GAEG;AACH,SAAS,WAAW;IAClB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,KAAK,CAAC,kEAAkE,CAAC,CAAC;QAClF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;QAC5E,OAAO,iBAAO,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACvD,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,IAAI;IACjB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,eAAe;IACf,MAAM,OAAO,GAAG,WAAW,EAAE,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,WAAW,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEvD,2CAA2C;IAC3C,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,UAAU,GAAG,IAAI,oBAAU,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,uBAAuB,OAAO,GAAG,0BAAgB,MAAM,CAAC,CAAC;QAErE,IAAI,OAAO,GAAG,IAAI,GAAG,0BAAgB,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,MAAM,MAAM,GAAG,IAAI,uBAAiB,CAAC;QACnC,MAAM,EAAE,OAAO;QACf,OAAO;QACP,QAAQ,EAAE,SAAS;KACpB,CAAC,CAAC;IAEH,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,CAAC,GAAG,CAAC,sDAAsD,CAAC,CAAC;QACpE,OAAO,CAAC,GAAG,CAAC,uEAAuE,CAAC,CAAC;IACvF,CAAC;IAED,oBAAoB;IACpB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IACxC,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC;IAE1B,iCAAiC;IACjC,OAAO,CAAC,GAAG,CAAC,mCAAmC,UAAU,aAAa,CAAC,CAAC;IAExE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,GAAG,UAAU,UAAU,CAAC,CAAC;QAElE,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;YACnB,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAEzB,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;gBAClC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC;gBACnF,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/D,CAAC;YAED,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;YAC/D,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;YAC3E,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;YACrE,OAAO,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;QAE1C,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC;gBACjD,OAAO,CAAC,GAAG,CAAC,qEAAqE,CAAC,CAAC;gBACnF,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;gBAC1D,OAAO,CAAC,GAAG,CAAC,iBAAiB,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;YAC/D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC;AAED,eAAe;AACf,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IACnB,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;IACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy Cash x402 Server Example
|
|
3
|
+
*
|
|
4
|
+
* Start this server, then run client-example.ts in another terminal
|
|
5
|
+
*
|
|
6
|
+
* Environment variables:
|
|
7
|
+
* - MERCHANT_WALLET: Your Solana wallet address for receiving payments
|
|
8
|
+
* - MERCHANT_KEYPAIR: JSON array of keypair bytes (for withdrawals)
|
|
9
|
+
* - API_PRICE: Price in lamports (default: 10000000 = 0.01 SOL)
|
|
10
|
+
* - RPC_URL: Solana RPC URL (default: devnet)
|
|
11
|
+
*/
|
|
12
|
+
import 'dotenv/config';
|
|
13
|
+
//# sourceMappingURL=server-example.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-example.d.ts","sourceRoot":"","sources":["../../examples/server-example.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,eAAe,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Privacy Cash x402 Server Example
|
|
4
|
+
*
|
|
5
|
+
* Start this server, then run client-example.ts in another terminal
|
|
6
|
+
*
|
|
7
|
+
* Environment variables:
|
|
8
|
+
* - MERCHANT_WALLET: Your Solana wallet address for receiving payments
|
|
9
|
+
* - MERCHANT_KEYPAIR: JSON array of keypair bytes (for withdrawals)
|
|
10
|
+
* - API_PRICE: Price in lamports (default: 10000000 = 0.01 SOL)
|
|
11
|
+
* - RPC_URL: Solana RPC URL (default: devnet)
|
|
12
|
+
*/
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
require("dotenv/config");
|
|
18
|
+
const express_1 = __importDefault(require("express"));
|
|
19
|
+
const server_1 = require("../src/server");
|
|
20
|
+
// Load config from environment
|
|
21
|
+
const MERCHANT_WALLET = process.env.MERCHANT_WALLET || '';
|
|
22
|
+
const API_PRICE = parseInt(process.env.API_PRICE || '10000000'); // 0.01 SOL
|
|
23
|
+
const RPC_URL = process.env.RPC_URL || 'https://api.devnet.solana.com';
|
|
24
|
+
// Parse merchant keypair if provided
|
|
25
|
+
let merchantKeypair;
|
|
26
|
+
if (process.env.MERCHANT_KEYPAIR) {
|
|
27
|
+
try {
|
|
28
|
+
merchantKeypair = new Uint8Array(JSON.parse(process.env.MERCHANT_KEYPAIR));
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
console.warn('Failed to parse MERCHANT_KEYPAIR, withdrawals will be simulated');
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
// Create server
|
|
35
|
+
const paymentServer = new server_1.X402PaymentServer({
|
|
36
|
+
merchantWallet: MERCHANT_WALLET,
|
|
37
|
+
rpcUrl: RPC_URL,
|
|
38
|
+
apiPrice: API_PRICE,
|
|
39
|
+
merchantKeypair,
|
|
40
|
+
});
|
|
41
|
+
// Create Express app
|
|
42
|
+
const app = (0, express_1.default)();
|
|
43
|
+
app.use(express_1.default.json());
|
|
44
|
+
// Health check endpoint
|
|
45
|
+
app.get('/health', (req, res) => {
|
|
46
|
+
const stats = paymentServer.getStats();
|
|
47
|
+
res.json({
|
|
48
|
+
status: 'healthy',
|
|
49
|
+
service: 'Privacy Cash x402 Server',
|
|
50
|
+
network: RPC_URL.includes('devnet') ? 'devnet' : 'mainnet-beta',
|
|
51
|
+
stats,
|
|
52
|
+
});
|
|
53
|
+
});
|
|
54
|
+
// Premium endpoint - protected by x402 payment
|
|
55
|
+
app.get('/premium', paymentServer.middleware(), (req, res) => {
|
|
56
|
+
res.json({
|
|
57
|
+
success: true,
|
|
58
|
+
data: 'Premium content unlocked! This data is protected by Privacy Cash.',
|
|
59
|
+
message: 'Your payment was verified privately. No one can link this to your deposit.',
|
|
60
|
+
privacyGuarantees: [
|
|
61
|
+
'Your wallet address is hidden from this transaction',
|
|
62
|
+
'Payment amount is mixed with others in the pool',
|
|
63
|
+
'Zero-knowledge proofs verify validity without revealing identity',
|
|
64
|
+
'On-chain observers cannot link deposit to withdrawal',
|
|
65
|
+
],
|
|
66
|
+
});
|
|
67
|
+
});
|
|
68
|
+
// Admin stats endpoint
|
|
69
|
+
app.get('/admin/stats', (req, res) => {
|
|
70
|
+
const stats = paymentServer.getStats();
|
|
71
|
+
res.json({
|
|
72
|
+
totalPaymentsReceived: stats.usedCommitments,
|
|
73
|
+
pendingWithdrawals: stats.pendingPayments,
|
|
74
|
+
totalPendingRevenue: stats.totalPendingAmount,
|
|
75
|
+
uptime: process.uptime(),
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
// Start server
|
|
79
|
+
const PORT = parseInt(process.env.PORT || '3001');
|
|
80
|
+
app.listen(PORT, () => {
|
|
81
|
+
console.log('\nPrivacy Cash x402 Server Running');
|
|
82
|
+
console.log('=====================================');
|
|
83
|
+
console.log(`URL: http://localhost:${PORT}`);
|
|
84
|
+
console.log(`Network: ${RPC_URL.includes('devnet') ? 'devnet' : 'mainnet-beta'}`);
|
|
85
|
+
console.log(`Merchant: ${MERCHANT_WALLET}`);
|
|
86
|
+
console.log(`API Price: ${API_PRICE / 1e9} SOL`);
|
|
87
|
+
console.log('\nPrivacy Features:');
|
|
88
|
+
console.log(' Zero-knowledge payment verification');
|
|
89
|
+
console.log(' Unlinkable deposits and withdrawals');
|
|
90
|
+
console.log(' Anonymous sender privacy');
|
|
91
|
+
console.log(' Double-spend protection');
|
|
92
|
+
console.log('\nEndpoints:');
|
|
93
|
+
console.log(' GET /premium - Protected content (requires payment)');
|
|
94
|
+
console.log(' GET /health - Health check');
|
|
95
|
+
console.log(' GET /admin/stats - Server statistics');
|
|
96
|
+
console.log('\nReady to accept private payments!\n');
|
|
97
|
+
});
|
|
98
|
+
// Cleanup on exit
|
|
99
|
+
process.on('SIGINT', () => {
|
|
100
|
+
console.log('\nShutting down...');
|
|
101
|
+
paymentServer.stop();
|
|
102
|
+
process.exit(0);
|
|
103
|
+
});
|
|
104
|
+
//# sourceMappingURL=server-example.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-example.js","sourceRoot":"","sources":["../../examples/server-example.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;;;;AAEH,yBAAuB;AACvB,sDAAqD;AACrD,0CAAkD;AAElD,+BAA+B;AAC/B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE,CAAC;AAC1D,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,UAAU,CAAC,CAAC,CAAC,WAAW;AAC5E,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,+BAA+B,CAAC;AAEvE,qCAAqC;AACrC,IAAI,eAAuC,CAAC;AAC5C,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAC;IACjC,IAAI,CAAC;QACH,eAAe,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,IAAI,CAAC,iEAAiE,CAAC,CAAC;IAClF,CAAC;AACH,CAAC;AAED,gBAAgB;AAChB,MAAM,aAAa,GAAG,IAAI,0BAAiB,CAAC;IAC1C,cAAc,EAAE,eAAe;IAC/B,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,SAAS;IACnB,eAAe;CAChB,CAAC,CAAC;AAEH,qBAAqB;AACrB,MAAM,GAAG,GAAG,IAAA,iBAAO,GAAE,CAAC;AACtB,GAAG,CAAC,GAAG,CAAC,iBAAO,CAAC,IAAI,EAAE,CAAC,CAAC;AAExB,wBAAwB;AACxB,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACjD,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;IACvC,GAAG,CAAC,IAAI,CAAC;QACP,MAAM,EAAE,SAAS;QACjB,OAAO,EAAE,0BAA0B;QACnC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc;QAC/D,KAAK;KACN,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,+CAA+C;AAC/C,GAAG,CAAC,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,UAAU,EAAE,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IAC9E,GAAG,CAAC,IAAI,CAAC;QACP,OAAO,EAAE,IAAI;QACb,IAAI,EAAE,mEAAmE;QACzE,OAAO,EAAE,4EAA4E;QACrF,iBAAiB,EAAE;YACjB,qDAAqD;YACrD,iDAAiD;YACjD,kEAAkE;YAClE,sDAAsD;SACvD;KACF,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,uBAAuB;AACvB,GAAG,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,GAAY,EAAE,GAAa,EAAE,EAAE;IACtD,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,EAAE,CAAC;IACvC,GAAG,CAAC,IAAI,CAAC;QACP,qBAAqB,EAAE,KAAK,CAAC,eAAe;QAC5C,kBAAkB,EAAE,KAAK,CAAC,eAAe;QACzC,mBAAmB,EAAE,KAAK,CAAC,kBAAkB;QAC7C,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE;KACzB,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,eAAe;AACf,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,CAAC;AAElD,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;IACpB,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;IAClD,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC;IAC7C,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,cAAc,EAAE,CAAC,CAAC;IAClF,OAAO,CAAC,GAAG,CAAC,aAAa,eAAe,EAAE,CAAC,CAAC;IAC5C,OAAO,CAAC,GAAG,CAAC,cAAc,SAAS,GAAG,GAAG,MAAM,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;IAC3C,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;IAC7E,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;AACvD,CAAC,CAAC,CAAC;AAEH,kBAAkB;AAClB,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE;IACxB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAClC,aAAa,CAAC,IAAI,EAAE,CAAC;IACrB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { PrivacyCash } from 'privacycash';
|
|
2
|
+
import { X402ClientConfig, PaymentQuote, PrivateBalance, PaymentResult } from '../types';
|
|
3
|
+
import { EncryptionService } from '../utils/encryption';
|
|
4
|
+
/**
|
|
5
|
+
* X402 Payment Client for Privacy Cash
|
|
6
|
+
* Handles private payments for API access using Privacy Cash protocol
|
|
7
|
+
*
|
|
8
|
+
* Supports mock mode for demos without real transactions
|
|
9
|
+
*/
|
|
10
|
+
export declare class X402PaymentClient {
|
|
11
|
+
private config;
|
|
12
|
+
private connection;
|
|
13
|
+
private keypair;
|
|
14
|
+
private client;
|
|
15
|
+
private encryptionService;
|
|
16
|
+
private initialized;
|
|
17
|
+
private network;
|
|
18
|
+
private mockMode;
|
|
19
|
+
private mockBalance;
|
|
20
|
+
constructor(config: X402ClientConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Initialize the client - must be called before other operations
|
|
23
|
+
*/
|
|
24
|
+
initialize(): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Get current private balance
|
|
27
|
+
*/
|
|
28
|
+
getPrivateBalance(): Promise<PrivateBalance>;
|
|
29
|
+
/**
|
|
30
|
+
* Deposit SOL into Privacy Cash pool
|
|
31
|
+
*/
|
|
32
|
+
deposit(lamports: number): Promise<{
|
|
33
|
+
tx: string;
|
|
34
|
+
}>;
|
|
35
|
+
/**
|
|
36
|
+
* Generate payment headers for a quote
|
|
37
|
+
* Returns headers to include in request to protected endpoint
|
|
38
|
+
*/
|
|
39
|
+
generatePayment(quote: PaymentQuote): Promise<{
|
|
40
|
+
'X-Payment': string;
|
|
41
|
+
'X-Privacy-Commitment': string;
|
|
42
|
+
'X-Wallet-Address': string;
|
|
43
|
+
}>;
|
|
44
|
+
/**
|
|
45
|
+
* Full payment flow: request quote, ensure balance, pay, return response
|
|
46
|
+
*/
|
|
47
|
+
payForAccess(url: string): Promise<PaymentResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Generate balance proof for server verification
|
|
50
|
+
*/
|
|
51
|
+
private generateBalanceProof;
|
|
52
|
+
/**
|
|
53
|
+
* Generate unique commitment for this payment
|
|
54
|
+
*/
|
|
55
|
+
private generateCommitment;
|
|
56
|
+
/**
|
|
57
|
+
* Hash the commitment for x402 header
|
|
58
|
+
*/
|
|
59
|
+
private hashNote;
|
|
60
|
+
/**
|
|
61
|
+
* Ensure client is initialized
|
|
62
|
+
*/
|
|
63
|
+
private ensureInitialized;
|
|
64
|
+
/**
|
|
65
|
+
* Generate mock transaction ID
|
|
66
|
+
*/
|
|
67
|
+
private generateMockTxId;
|
|
68
|
+
/**
|
|
69
|
+
* Sleep helper
|
|
70
|
+
*/
|
|
71
|
+
private sleep;
|
|
72
|
+
/**
|
|
73
|
+
* Check if running in mock mode
|
|
74
|
+
*/
|
|
75
|
+
isMockMode(): boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Get the underlying Privacy Cash client (for advanced usage)
|
|
78
|
+
*/
|
|
79
|
+
getPrivacyCashClient(): PrivacyCash | null;
|
|
80
|
+
/**
|
|
81
|
+
* Get the encryption service (for advanced usage)
|
|
82
|
+
*/
|
|
83
|
+
getEncryptionService(): EncryptionService | null;
|
|
84
|
+
/**
|
|
85
|
+
* Get the public key
|
|
86
|
+
*/
|
|
87
|
+
getPublicKey(): import("@solana/web3.js").PublicKey;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/client/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG1C,OAAO,EACL,gBAAgB,EAChB,YAAY,EAEZ,cAAc,EACd,aAAa,EAGd,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;;;;GAKG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAmB;IACjC,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,OAAO,CAAU;IACzB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,iBAAiB,CAAkC;IAC3D,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,OAAO,CAAgB;IAC/B,OAAO,CAAC,QAAQ,CAAU;IAC1B,OAAO,CAAC,WAAW,CAAa;gBAEpB,MAAM,EAAE,gBAAgB;IAQpC;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAqCjC;;OAEG;IACG,iBAAiB,IAAI,OAAO,CAAC,cAAc,CAAC;IAiBlD;;OAEG;IACG,OAAO,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC;IAuBxD;;;OAGG;IACG,eAAe,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;QAClD,WAAW,EAAE,MAAM,CAAC;QACpB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IA6CF;;OAEG;IACG,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,CAAC;IAwDvD;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAS5B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAK1B;;OAEG;IACH,OAAO,CAAC,QAAQ;IAIhB;;OAEG;IACH,OAAO,CAAC,iBAAiB;IASzB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAIxB;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;OAEG;IACH,UAAU,IAAI,OAAO;IAIrB;;OAEG;IACH,oBAAoB,IAAI,WAAW,GAAG,IAAI;IAI1C;;OAEG;IACH,oBAAoB,IAAI,iBAAiB,GAAG,IAAI;IAIhD;;OAEG;IACH,YAAY;CAGb"}
|