@@ -262,20 +262,39 @@ def verify_payment(payment_header: str, tier: str = "full_scan") -> tuple[bool,
262262
263263
264264def _load_redeemer ():
265- """Decrypt the NRI keystore once, using WALLET_PASSWORD from env."""
265+ """Load the NRI signing account.
266+
267+ Two sources, in priority order:
268+ 1. NRI_PRIVATE_KEY (or WALLET_PASSWORD holding a raw 0x/64-hex key) — sign directly.
269+ 2. Encrypted keystore at NRI_KEYSTORE, decrypted with WALLET_PASSWORD.
270+ """
266271 global _redeemer_acct
267272 if _redeemer_acct is not None :
268273 return _redeemer_acct
269- password = os .environ .get ("WALLET_PASSWORD" )
270- if not password :
271- raise RuntimeError ("WALLET_PASSWORD not set — cannot decrypt NRI keystore" )
272- with open (NRI_KEYSTORE ) as f :
273- keyfile = json .load (f )
274- key = Account .decrypt (keyfile , password )
275- acct = Account .from_key (key )
274+
275+ secret = os .environ .get ("NRI_PRIVATE_KEY" ) or os .environ .get ("WALLET_PASSWORD" )
276+ if not secret :
277+ raise RuntimeError ("no NRI_PRIVATE_KEY / WALLET_PASSWORD set — cannot sign redemptions" )
278+ secret = secret .strip ()
279+
280+ acct = None
281+ # Try: raw private key (64 hex chars, optional 0x prefix)
282+ _candidate = secret if secret .startswith ("0x" ) else "0x" + secret
283+ if len (_candidate ) == 66 :
284+ try :
285+ acct = Account .from_key (_candidate )
286+ except Exception :
287+ acct = None
288+ # Fallback: treat secret as a keystore password
289+ if acct is None :
290+ with open (NRI_KEYSTORE ) as f :
291+ keyfile = json .load (f )
292+ key = Account .decrypt (keyfile , secret )
293+ acct = Account .from_key (key )
294+
276295 if acct .address .lower () != NRI_PAY_TO .lower ():
277296 raise RuntimeError (
278- f"keystore address { acct .address } != NRI_PAY_TO { NRI_PAY_TO } "
297+ f"redeemer address { acct .address } != NRI_PAY_TO { NRI_PAY_TO } "
279298 )
280299 _redeemer_acct = acct
281300 return acct
0 commit comments