1111
1212REPO_ROOT = Path (__file__ ).resolve ().parents [1 ]
1313CIRCUITS_DIR = REPO_ROOT / "circuits"
14+ NETWORKS_PATH = REPO_ROOT / "NETWORKS.json"
1415DEFAULT_ZKEY_PATH = CIRCUITS_DIR / "null_proof_final.zkey"
1516DEFAULT_WASM_PATH = CIRCUITS_DIR / "null_proof_js" / "null_proof.wasm"
1617DEFAULT_VK_PATH = CIRCUITS_DIR / "vk.json"
18+ NETWORKS = json .loads (NETWORKS_PATH .read_text (encoding = "utf8" ))
19+ SUPPORTED_NETWORKS = NETWORKS ["supportedNetworks" ]
1720
18- PROGRAM_ID = Pubkey .from_string ("2stas3cZYnBiWpndcTXQDGLXwfQ7kjEYYrW52DsUAcxF" )
21+ PROGRAM_ID = Pubkey .from_string (NETWORKS [ "canonicalProgramId" ] )
1922TOKEN_PROGRAM_ID = Pubkey .from_string ("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" )
2023SYSTEM_PROGRAM_ID = Pubkey .from_string ("11111111111111111111111111111111" )
2124VAULT_SEED = b"merkle_vault"
@@ -47,14 +50,43 @@ def coerce_bytes32(value) -> bytes:
4750 return raw
4851
4952
53+ def list_supported_networks ():
54+ return list (SUPPORTED_NETWORKS .keys ())
55+
56+
57+ def resolve_network_config (network = None , rpc_url = None , wallet_path = None ):
58+ selected_network = network or os .environ .get ("DARK_NULL_NETWORK" ) or NETWORKS ["defaultNetwork" ]
59+ definition = SUPPORTED_NETWORKS .get (selected_network )
60+ if definition is None :
61+ known_networks = ", " .join (list_supported_networks ())
62+ raise ValueError (f"Unknown network: { selected_network } . Expected one of { known_networks } " )
63+
64+ return {
65+ "network" : selected_network ,
66+ "label" : definition ["label" ],
67+ "cluster" : definition ["cluster" ],
68+ "anchor_cluster" : definition ["anchorCluster" ],
69+ "rpc_url" : rpc_url or os .environ .get ("DARK_NULL_RPC_URL" ) or definition ["rpcUrl" ],
70+ "ws_url" : definition .get ("wsUrl" ),
71+ "wallet_path" : wallet_path or os .environ .get ("DARK_NULL_WALLET_PATH" ),
72+ "program_id" : NETWORKS ["canonicalProgramId" ],
73+ "manifest_key" : definition ["manifestKey" ],
74+ }
75+
76+
5077class DarkClient :
51- def __init__ (self , snarkjs_path = None , zkey_path = None , wasm_path = None , vk_path = None ):
78+ def __init__ (self , snarkjs_path = None , zkey_path = None , wasm_path = None , vk_path = None , network = None , rpc_url = None , wallet_path = None ):
79+ self .network_config = resolve_network_config (network = network , rpc_url = rpc_url , wallet_path = wallet_path )
80+ self .program_id = Pubkey .from_string (self .network_config ["program_id" ])
81+ self .rpc_url = self .network_config ["rpc_url" ]
82+ self .wallet_path = self .network_config ["wallet_path" ]
5283 self .snarkjs_path = snarkjs_path or os .environ .get ("DARK_NULL_SNARKJS" )
5384 self .zkey_path = Path (zkey_path ) if zkey_path else Path (os .environ .get ("DARK_NULL_ZKEY_PATH" , DEFAULT_ZKEY_PATH ))
5485 self .wasm_path = Path (wasm_path ) if wasm_path else Path (os .environ .get ("DARK_NULL_WASM_PATH" , DEFAULT_WASM_PATH ))
5586 self .vk_path = Path (vk_path ) if vk_path else Path (os .environ .get ("DARK_NULL_VK_PATH" , DEFAULT_VK_PATH ))
5687
57- def derive_vault_pda (self , program_id = PROGRAM_ID ):
88+ def derive_vault_pda (self , program_id = None ):
89+ program_id = program_id or self .program_id
5890 return Pubkey .find_program_address ([VAULT_SEED ], program_id )[0 ]
5991
6092 def build_proof_inputs (self , amount , blinding , nullifier_secret , root , path_elements , path_indices ):
@@ -137,7 +169,8 @@ def verify_proof_locally(self, proof, public_signals):
137169 )
138170 return True
139171
140- def build_initialize_instruction (self , user , vault = None , program_id = PROGRAM_ID ):
172+ def build_initialize_instruction (self , user , vault = None , program_id = None ):
173+ program_id = program_id or self .program_id
141174 vault = vault or self .derive_vault_pda (program_id )
142175 return Instruction (
143176 program_id ,
@@ -149,7 +182,8 @@ def build_initialize_instruction(self, user, vault=None, program_id=PROGRAM_ID):
149182 ],
150183 )
151184
152- def build_update_root_instruction (self , signer , new_root , vault = None , program_id = PROGRAM_ID ):
185+ def build_update_root_instruction (self , signer , new_root , vault = None , program_id = None ):
186+ program_id = program_id or self .program_id
153187 vault = vault or self .derive_vault_pda (program_id )
154188 data = bytearray (anchor_discriminator ("update_root" ))
155189 data .extend (coerce_bytes32 (new_root ))
@@ -173,8 +207,9 @@ def build_deposit_wsol_and_whisper_instruction(
173207 ephemeral_pubkey ,
174208 view_tag ,
175209 vault = None ,
176- program_id = PROGRAM_ID ,
210+ program_id = None ,
177211 ):
212+ program_id = program_id or self .program_id
178213 vault = vault or self .derive_vault_pda (program_id )
179214 data = bytearray (anchor_discriminator ("deposit_wsol_and_whisper" ))
180215 data .extend (int (amount ).to_bytes (8 , "little" ))
@@ -203,8 +238,9 @@ def build_prepare_phantom_withdraw_instruction(
203238 amount ,
204239 proof_bundle ,
205240 vault = None ,
206- program_id = PROGRAM_ID ,
241+ program_id = None ,
207242 ):
243+ program_id = program_id or self .program_id
208244 vault = vault or self .derive_vault_pda (program_id )
209245 proof_a = bytes (proof_bundle ["proof_a" ])
210246 proof_b = bytes (proof_bundle ["proof_b" ])
@@ -253,8 +289,9 @@ def build_burn_and_whisper_instruction(
253289 ephemeral_pubkey ,
254290 view_tag ,
255291 vault = None ,
256- program_id = PROGRAM_ID ,
292+ program_id = None ,
257293 ):
294+ program_id = program_id or self .program_id
258295 vault = vault or self .derive_vault_pda (program_id )
259296 data = bytearray (anchor_discriminator ("burn_and_whisper" ))
260297 data .extend (int (amount ).to_bytes (8 , "little" ))
0 commit comments