nova-privacy-sdk 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.
Files changed (69) hide show
  1. package/.github/workflows/npm-publish.yml +55 -0
  2. package/PUBLISH.md +122 -0
  3. package/README.md +177 -0
  4. package/__tests__/e2e.test.ts +56 -0
  5. package/__tests__/e2espl.test.ts +73 -0
  6. package/__tests__/encryption.test.ts +1635 -0
  7. package/circuit2/transaction2.wasm +0 -0
  8. package/circuit2/transaction2.zkey +0 -0
  9. package/dist/config.d.ts +9 -0
  10. package/dist/config.js +12 -0
  11. package/dist/deposit.d.ts +18 -0
  12. package/dist/deposit.js +392 -0
  13. package/dist/depositSPL.d.ts +20 -0
  14. package/dist/depositSPL.js +448 -0
  15. package/dist/exportUtils.d.ts +11 -0
  16. package/dist/exportUtils.js +11 -0
  17. package/dist/getUtxos.d.ts +29 -0
  18. package/dist/getUtxos.js +294 -0
  19. package/dist/getUtxosSPL.d.ts +33 -0
  20. package/dist/getUtxosSPL.js +395 -0
  21. package/dist/index.d.ts +125 -0
  22. package/dist/index.js +302 -0
  23. package/dist/models/keypair.d.ts +26 -0
  24. package/dist/models/keypair.js +43 -0
  25. package/dist/models/utxo.d.ts +49 -0
  26. package/dist/models/utxo.js +85 -0
  27. package/dist/utils/address_lookup_table.d.ts +9 -0
  28. package/dist/utils/address_lookup_table.js +45 -0
  29. package/dist/utils/constants.d.ts +31 -0
  30. package/dist/utils/constants.js +62 -0
  31. package/dist/utils/encryption.d.ts +107 -0
  32. package/dist/utils/encryption.js +376 -0
  33. package/dist/utils/logger.d.ts +9 -0
  34. package/dist/utils/logger.js +35 -0
  35. package/dist/utils/merkle_tree.d.ts +92 -0
  36. package/dist/utils/merkle_tree.js +186 -0
  37. package/dist/utils/node-shim.d.ts +5 -0
  38. package/dist/utils/node-shim.js +5 -0
  39. package/dist/utils/prover.d.ts +36 -0
  40. package/dist/utils/prover.js +147 -0
  41. package/dist/utils/utils.d.ts +69 -0
  42. package/dist/utils/utils.js +182 -0
  43. package/dist/withdraw.d.ts +21 -0
  44. package/dist/withdraw.js +270 -0
  45. package/dist/withdrawSPL.d.ts +23 -0
  46. package/dist/withdrawSPL.js +306 -0
  47. package/package.json +77 -0
  48. package/setup-git.sh +51 -0
  49. package/setup-github.sh +36 -0
  50. package/src/config.ts +22 -0
  51. package/src/deposit.ts +487 -0
  52. package/src/depositSPL.ts +567 -0
  53. package/src/exportUtils.ts +13 -0
  54. package/src/getUtxos.ts +396 -0
  55. package/src/getUtxosSPL.ts +528 -0
  56. package/src/index.ts +350 -0
  57. package/src/models/keypair.ts +52 -0
  58. package/src/models/utxo.ts +106 -0
  59. package/src/utils/address_lookup_table.ts +78 -0
  60. package/src/utils/constants.ts +84 -0
  61. package/src/utils/encryption.ts +464 -0
  62. package/src/utils/logger.ts +42 -0
  63. package/src/utils/merkle_tree.ts +207 -0
  64. package/src/utils/node-shim.ts +6 -0
  65. package/src/utils/prover.ts +222 -0
  66. package/src/utils/utils.ts +242 -0
  67. package/src/withdraw.ts +332 -0
  68. package/src/withdrawSPL.ts +394 -0
  69. package/tsconfig.json +28 -0
@@ -0,0 +1,55 @@
1
+ name: Publish to npm when version changes
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - master
8
+ paths:
9
+ - "package.json"
10
+
11
+ permissions:
12
+ id-token: write
13
+ contents: read
14
+
15
+ jobs:
16
+ publish:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - name: Checkout repository
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Setup Node.js
24
+ uses: actions/setup-node@v4
25
+ with:
26
+ node-version: 24
27
+ registry-url: https://registry.npmjs.org/
28
+
29
+ - name: Get current package version
30
+ id: pkg
31
+ run: echo "version=$(node -p 'require(\"./package.json\").version')" >> $GITHUB_OUTPUT
32
+
33
+ - name: Check if version already exists on npm
34
+ id: check
35
+ run: |
36
+ PKG_NAME=$(node -p 'require("./package.json").name')
37
+ PUBLISHED=$(npm view $PKG_NAME versions --json | grep -o "\"${{ steps.pkg.outputs.version }}\"" || true)
38
+ if [ -n "$PUBLISHED" ]; then
39
+ echo "exists=true" >> $GITHUB_OUTPUT
40
+ echo "Version ${{ steps.pkg.outputs.version }} already exists on npm. Skipping publish."
41
+ else
42
+ echo "exists=false" >> $GITHUB_OUTPUT
43
+ fi
44
+
45
+ - name: Install dependencies
46
+ run: npm install
47
+
48
+ - name: Build source
49
+ run: npm run build || echo "No build script defined."
50
+
51
+ - name: Publish to npm
52
+ if: steps.check.outputs.exists == 'false'
53
+ run: |
54
+ echo "Publishing version ${{ steps.pkg.outputs.version }}..."
55
+ npm publish --access public
package/PUBLISH.md ADDED
@@ -0,0 +1,122 @@
1
+ # Publishing Nova Privacy SDK to GitHub and npm
2
+
3
+ ## Step 1: Create GitHub Repository
4
+
5
+ 1. Go to GitHub and create a new repository named `nova-privacy-sdk`
6
+ 2. **DO NOT** initialize with README, .gitignore, or license (we already have these)
7
+
8
+ ## Step 2: Update Repository URL in package.json
9
+
10
+ Update the repository URL in `package.json`:
11
+
12
+ ```json
13
+ "repository": "https://github.com/YOUR_USERNAME/nova-privacy-sdk"
14
+ ```
15
+
16
+ Replace `YOUR_USERNAME` with your GitHub username.
17
+
18
+ ## Step 3: Initialize Git and Push to GitHub
19
+
20
+ ```bash
21
+ # Initialize git (if not already initialized)
22
+ git init
23
+
24
+ # Add all files
25
+ git add .
26
+
27
+ # Create initial commit
28
+ git commit -m "Initial commit: Nova Privacy SDK fork"
29
+
30
+ # Add your GitHub repository as remote
31
+ git remote add origin https://github.com/YOUR_USERNAME/nova-privacy-sdk.git
32
+
33
+ # Push to GitHub
34
+ git branch -M main
35
+ git push -u origin main
36
+ ```
37
+
38
+ ## Step 4: Verify npm Account
39
+
40
+ Make sure you have an npm account and are logged in:
41
+
42
+ ```bash
43
+ # Check if logged in
44
+ npm whoami
45
+
46
+ # If not logged in, login
47
+ npm login
48
+ ```
49
+
50
+ ## Step 5: Verify Package Name Availability
51
+
52
+ Check if `nova-privacy-sdk` is available:
53
+
54
+ ```bash
55
+ npm view nova-privacy-sdk
56
+ ```
57
+
58
+ If it returns 404, the name is available. If it exists, you may need to choose a different name or use a scoped package like `@your-org/nova-privacy-sdk`.
59
+
60
+ ## Step 6: Build and Publish to npm
61
+
62
+ ```bash
63
+ # Build the project
64
+ npm run build
65
+
66
+ # Dry run to see what would be published (recommended first)
67
+ npm publish --dry-run
68
+
69
+ # Publish to npm
70
+ npm publish
71
+
72
+ # For scoped packages (if needed), use:
73
+ # npm publish --access public
74
+ ```
75
+
76
+ ## Step 7: Verify Installation
77
+
78
+ After publishing, verify the package can be installed:
79
+
80
+ ```bash
81
+ npm install nova-privacy-sdk
82
+ ```
83
+
84
+ ## Versioning
85
+
86
+ For future updates:
87
+
88
+ ```bash
89
+ # Update version
90
+ npm version patch # 1.0.0 -> 1.0.1
91
+ npm version minor # 1.0.0 -> 1.1.0
92
+ npm version major # 1.0.0 -> 2.0.0
93
+
94
+ # Then publish
95
+ npm publish
96
+ ```
97
+
98
+ ## Important Notes
99
+
100
+ 1. **README.md** - Already includes credits to Privacy Cash and link to https://www.privacycash.org/
101
+ 2. **Package name** - Using `nova-privacy-sdk` which is SEO-friendly and descriptive
102
+ 3. **Version** - Starting at 1.0.0
103
+ 4. **Repository** - Update the GitHub URL in package.json before pushing
104
+
105
+ ## SEO Keywords Included
106
+
107
+ The package includes these keywords in package.json:
108
+ - solana
109
+ - privacy
110
+ - zk
111
+ - zero-knowledge
112
+ - private-transactions
113
+ - cryptocurrency
114
+ - blockchain
115
+ - sdk
116
+ - nova
117
+ - privacy-cash
118
+ - private-withdraw
119
+ - private-send
120
+ - solana-privacy
121
+
122
+ These will help users find the package when searching npm for privacy-related Solana SDKs.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # Nova Privacy SDK
2
+
3
+ SDK for Nova Privacy - Private cryptocurrency transactions on Solana. Enable private deposits, withdrawals, and transfers for SOL and SPL tokens (including NOVA token).
4
+
5
+ ## 🔗 Fork Information
6
+
7
+ This SDK is a **fork of the Privacy Cash SDK**.
8
+
9
+ **Original Project:** [Privacy Cash](https://www.privacycash.org/)
10
+ **Original Repository:** [Privacy-Cash/privacy-cash-sdk](https://github.com/Privacy-Cash/privacy-cash-sdk)
11
+
12
+ We extend our gratitude to the Privacy Cash team for their excellent work. This fork includes:
13
+ - Support for Nova Privacy program (`SHLD11qQaY6h2N3ozXUWJEJitk1zGm9tvvAC7rjxpsp`)
14
+ - NOVA token support with dedicated tree address
15
+ - Custom SOL and NOVA tree configurations
16
+ - Enhanced private transaction capabilities
17
+
18
+ ## 🚀 Features
19
+
20
+ - **Private SOL Transactions** - Deposit and withdraw SOL privately
21
+ - **Private SPL Token Transactions** - Support for NOVA, USDC, USDT, and other SPL tokens
22
+ - **Zero-Knowledge Proofs** - Leverages zk-SNARKs for privacy
23
+ - **Mainnet Ready** - Fully configured for Solana mainnet
24
+ - **TypeScript Support** - Full TypeScript definitions included
25
+
26
+ ## 📦 Installation
27
+
28
+ ```bash
29
+ npm install nova-privacy-sdk
30
+ ```
31
+
32
+ or
33
+
34
+ ```bash
35
+ yarn add nova-privacy-sdk
36
+ ```
37
+
38
+ ## 🔧 Quick Start
39
+
40
+ ```typescript
41
+ import { PrivacyCash } from 'nova-privacy-sdk';
42
+ import { Keypair } from '@solana/web3.js';
43
+
44
+ // Initialize client
45
+ const client = new PrivacyCash({
46
+ RPC_url: 'https://api.mainnet-beta.solana.com',
47
+ owner: yourPrivateKey // Keypair, number[], Uint8Array, or base58 string
48
+ });
49
+
50
+ // Deposit SOL privately
51
+ const depositResult = await client.deposit({
52
+ lamports: 0.1 * 1_000_000_000 // 0.1 SOL
53
+ });
54
+
55
+ // Check private balance
56
+ const balance = await client.getPrivateBalance();
57
+ console.log('Private balance:', balance.lamports / 1_000_000_000, 'SOL');
58
+
59
+ // Withdraw SOL privately
60
+ const withdrawResult = await client.withdraw({
61
+ lamports: 0.05 * 1_000_000_000, // 0.05 SOL
62
+ recipientAddress: '9BWSPeFXTyQTPiPNWjWoaN6biqjktTmzMzqDpkEnova'
63
+ });
64
+
65
+ // Deposit NOVA token
66
+ const novaMint = new PublicKey('3SkFJRqMPTKZLqKK1MmY2mvAm711FGAtJ9ZbL6r1coin');
67
+ await client.depositSPL({
68
+ mintAddress: novaMint,
69
+ amount: 100 // 100 NOVA tokens
70
+ });
71
+ ```
72
+
73
+ ## 📚 API Reference
74
+
75
+ ### SOL Transactions
76
+
77
+ - `deposit({ lamports })` - Deposit SOL to private balance
78
+ - `withdraw({ lamports, recipientAddress? })` - Withdraw SOL from private balance
79
+ - `getPrivateBalance()` - Get current private SOL balance
80
+
81
+ ### SPL Token Transactions
82
+
83
+ - `depositSPL({ mintAddress, amount, base_units })` - Deposit SPL tokens privately
84
+ - `withdrawSPL({ mintAddress, amount, base_units, recipientAddress? })` - Withdraw SPL tokens privately
85
+ - `getPrivateBalanceSpl(mintAddress)` - Get private balance for a specific SPL token
86
+
87
+ ### Utility Functions
88
+
89
+ - `clearCache()` - Clear cached UTXO data
90
+ - `setLogger(logger)` - Set custom logger function
91
+
92
+ ## ⚙️ Configuration
93
+
94
+ The SDK uses environment variables for configuration. Create a `.env` file:
95
+
96
+ ```env
97
+ # Your forked program ID
98
+ NEXT_PUBLIC_PROGRAM_ID=SHLD11qQaY6h2N3ozXUWJEJitk1zGm9tvvAC7rjxpsp
99
+
100
+ # RPC URL (optional, defaults to public mainnet)
101
+ RPC_URL=https://api.mainnet-beta.solana.com
102
+
103
+ # Tree addresses (optional, defaults configured)
104
+ # NEXT_PUBLIC_SOL_TREE=DUnk81NBY7gUYRekT7GAwTU7jvabiVVwcMKZkRDs3dW9 (legacy)
105
+ NEXT_PUBLIC_NOVASOL_TREE=FZfbN2fY3aj7hTwh87dKMfuVwpaEipY3TuGpmYJnsWcG (active for SOL)
106
+ # NEXT_PUBLIC_NOVA_TREE=9CJ8jwAXJ7GrYtrMmD4gXBpTC59DMX7a91yMVpz25enZ
107
+ # NEXT_PUBLIC_NOVA_MINT=3SkFJRqMPTKZLqKK1MmY2mvAm711FGAtJ9ZbL6r1coin
108
+ ```
109
+
110
+ ## 🌳 Supported Tokens
111
+
112
+ - **SOL** - Native Solana token
113
+ - **NOVA** - Nova Privacy token (`3SkFJRqMPTKZLqKK1MmY2mvAm711FGAtJ9ZbL6r1coin`)
114
+ - **USDC** - USD Coin
115
+ - **USDT** - Tether USD
116
+ - **ZEC** - Zcash token
117
+ - **ORE** - Ore token
118
+
119
+ ## 🔒 Privacy Features
120
+
121
+ - **UTXO Model** - Uses unspent transaction outputs for privacy
122
+ - **Zero-Knowledge Proofs** - Proves transaction validity without revealing details
123
+ - **Encrypted Outputs** - All transaction outputs are encrypted
124
+ - **No Linkability** - Transactions cannot be linked to sender or receiver
125
+
126
+ ## 📖 Examples
127
+
128
+ Check the `/example` folder for complete working examples:
129
+
130
+ ```bash
131
+ cd example
132
+ npm install
133
+ cp ../.env_sample .env
134
+ # Edit .env with your configuration
135
+ npx ts-node index.ts
136
+ ```
137
+
138
+ ## 🧪 Testing
139
+
140
+ ```bash
141
+ # Run unit tests
142
+ npm test
143
+
144
+ # Run end-to-end tests (requires .env with PRIVATE_KEY and RPC_URL)
145
+ npm run teste2e
146
+ ```
147
+
148
+ ## 📋 Requirements
149
+
150
+ - Node.js version 24 or above
151
+ - Solana wallet with sufficient balance for transaction fees
152
+
153
+ ## ⚠️ Disclaimer
154
+
155
+ This SDK has been forked from Privacy Cash and modified for Nova Privacy. While based on audited code from Privacy Cash, please fully test before using in production and be aware of inherent software risks.
156
+
157
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
158
+
159
+ ## 🙏 Credits
160
+
161
+ This SDK is a fork of the [Privacy Cash SDK](https://github.com/Privacy-Cash/privacy-cash-sdk).
162
+
163
+ **Privacy Cash** - [https://www.privacycash.org/](https://www.privacycash.org/)
164
+
165
+ Original Privacy Cash SDK was audited by Zigtur. We extend our gratitude to the Privacy Cash team for their excellent work on the original SDK.
166
+
167
+ ## 📝 License
168
+
169
+ ISC
170
+
171
+ ## 🤝 Contributing
172
+
173
+ Contributions are welcome! Please feel free to submit a Pull Request.
174
+
175
+ ## 📧 Support
176
+
177
+ For issues and questions, please open an issue on the [GitHub repository](https://github.com/NovaShieldWallet/nova-privacy-shield).
@@ -0,0 +1,56 @@
1
+ import { describe, it, expect, vi, beforeAll, beforeEach, type Mock } from "vitest";
2
+ import dotenv from 'dotenv';
3
+ import { PrivacyCash } from "../src";
4
+ import { LAMPORTS_PER_SOL } from "@solana/web3.js";
5
+ dotenv.config();
6
+ const TEST_AMOUNT = 0.01
7
+
8
+ describe('e2e test', async () => {
9
+ if (!process.env.PRIVATE_KEY) {
10
+ throw new Error('missing PRIVATE_KEY in .env')
11
+ }
12
+ if (!process.env.RPC_URL) {
13
+ throw new Error('missing RPC_URL in .env')
14
+ }
15
+
16
+ let client = new PrivacyCash({
17
+ RPC_url: process.env.RPC_URL,
18
+ owner: process.env.PRIVATE_KEY
19
+ })
20
+ let balance_original = await client.getPrivateBalance()
21
+
22
+ // deposit
23
+ await client.deposit({
24
+ lamports: TEST_AMOUNT * LAMPORTS_PER_SOL
25
+ })
26
+ let balance_after_deposit = await client.getPrivateBalance()
27
+
28
+ // withdraw wrong amount
29
+ it(`show throw error if withdraw amount less than 0.01`, async () => {
30
+ await expect(client.withdraw({
31
+ lamports: 0.005 * LAMPORTS_PER_SOL
32
+ })).rejects.toThrow()
33
+ })
34
+
35
+ // withdraw
36
+ let withdrawRes = await client.withdraw({
37
+ lamports: TEST_AMOUNT * LAMPORTS_PER_SOL
38
+ })
39
+ let balance_after_withdraw = await client.getPrivateBalance()
40
+
41
+ it('balance is a number', () => {
42
+ expect(balance_original.lamports).to.be.a('number')
43
+ })
44
+
45
+ it(`balance should be increased ${TEST_AMOUNT} sol`, () => {
46
+ expect(balance_after_deposit.lamports).equal(balance_after_withdraw.lamports + TEST_AMOUNT * LAMPORTS_PER_SOL)
47
+ })
48
+
49
+ it('should keep balance unchanged after depositing and withdrawing the same amount', () => {
50
+ expect(balance_original.lamports).equal(balance_after_withdraw.lamports)
51
+ })
52
+
53
+ it(`withdraw real amount plus fee should be ${TEST_AMOUNT * LAMPORTS_PER_SOL}`, () => {
54
+ expect(withdrawRes.amount_in_lamports + withdrawRes.fee_in_lamports).equal(TEST_AMOUNT * LAMPORTS_PER_SOL)
55
+ })
56
+ })
@@ -0,0 +1,73 @@
1
+ import { describe, it, expect, vi, beforeAll, beforeEach, type Mock } from "vitest";
2
+ import dotenv from 'dotenv';
3
+ import { PrivacyCash } from "../src";
4
+ import { getAccount, getAssociatedTokenAddress } from "@solana/spl-token";
5
+ import { FEE_RECIPIENT, USDC_MINT } from "../src/utils/constants";
6
+ import { Connection } from "@solana/web3.js";
7
+ dotenv.config();
8
+ const TEST_AMOUNT = 2
9
+ const units_per_token = 1_000_000
10
+ describe('e2e test', async () => {
11
+ if (!process.env.PRIVATE_KEY) {
12
+ throw new Error('missing PRIVATE_KEY in .env')
13
+ }
14
+ if (!process.env.RPC_URL) {
15
+ throw new Error('missing RPC_URL in .env')
16
+ }
17
+
18
+ const connection = new Connection(process.env.RPC_URL)
19
+ let fee_recipient_ata = await getAssociatedTokenAddress(USDC_MINT, FEE_RECIPIENT, true)
20
+ let feeRecipientAccount = await getAccount(connection, fee_recipient_ata)
21
+ let feeRecipientBalance_before = feeRecipientAccount.amount
22
+
23
+ let client = new PrivacyCash({
24
+ RPC_url: process.env.RPC_URL,
25
+ owner: process.env.PRIVATE_KEY
26
+ })
27
+ let balance_original = await client.getPrivateBalanceUSDC()
28
+
29
+ // deposit
30
+ await client.depositUSDC({
31
+ base_units: TEST_AMOUNT * units_per_token
32
+ })
33
+ let balance_after_deposit = await client.getPrivateBalanceUSDC()
34
+
35
+ // withdraw wrong amount
36
+ it(`show throw error if withdraw amount less than 1`, async () => {
37
+ await expect(client.withdrawUSDC({
38
+ base_units: 0.9 * units_per_token
39
+ })).rejects.toThrow()
40
+ })
41
+
42
+ // withdraw
43
+ let withdrawRes = await client.withdrawUSDC({
44
+ base_units: TEST_AMOUNT * units_per_token
45
+ })
46
+
47
+ await new Promise(r => setTimeout(r, 10_000));
48
+
49
+ feeRecipientAccount = await getAccount(connection, fee_recipient_ata)
50
+ let feeRecipientBalance_after = feeRecipientAccount.amount
51
+
52
+ let balance_after_withdraw = await client.getPrivateBalanceUSDC()
53
+
54
+ it('balance is a number', () => {
55
+ expect(balance_original.base_units).to.be.a('number')
56
+ })
57
+
58
+ it(`balance should be increased ${TEST_AMOUNT} USDC`, () => {
59
+ expect(balance_after_deposit.base_units).equal(balance_after_withdraw.base_units + TEST_AMOUNT * units_per_token)
60
+ })
61
+
62
+ it('should keep balance unchanged after depositing and withdrawing the same amount', () => {
63
+ expect(balance_original.base_units).equal(balance_after_withdraw.base_units)
64
+ })
65
+
66
+ it(`withdraw real amount plus fee should be ${TEST_AMOUNT * units_per_token}`, () => {
67
+ expect(withdrawRes.base_units + withdrawRes.fee_base_units).equal(TEST_AMOUNT * units_per_token)
68
+ })
69
+
70
+ it('fee recipient amount should be inceased by the withdraw fee', () => {
71
+ expect(withdrawRes.fee_base_units).equal(Number(feeRecipientBalance_after - feeRecipientBalance_before))
72
+ })
73
+ })