@@ -100,6 +100,21 @@ def __init__(self, path: str, password: Optional[str] = None, expert: bool = Fal
100100 device .open_path (path .encode ())
101101 self .device = ColdcardDevice (dev = device )
102102
103+ self ._is_edge = None
104+
105+ @property
106+ def is_edge (self ):
107+ """
108+ Cached property, no need to ask device more than once
109+ :return: bool
110+ """
111+ if self ._is_edge is None :
112+ try :
113+ self ._is_edge = self .is_edge_firmware ()
114+ except : pass # silent fail, normal firmware is implied
115+
116+ return self ._is_edge
117+
103118 @coldcard_exception
104119 def get_pubkey_at_path (self , path : str ) -> ExtendedKey :
105120 self .device .check_mitm ()
@@ -132,14 +147,15 @@ def sign_tx(self, tx: PSBT) -> PSBT:
132147
133148 # For multisigs, we may need to do multiple passes if we appear in an input multiple times
134149 passes = 1
135- for psbt_in in tx .inputs :
136- our_keys = 0
137- for key in psbt_in .hd_keypaths .keys ():
138- keypath = psbt_in .hd_keypaths [key ]
139- if keypath .fingerprint == master_fp and key not in psbt_in .partial_sigs :
140- our_keys += 1
141- if our_keys > passes :
142- passes = our_keys
150+ if not self .is_edge :
151+ for psbt_in in tx .inputs :
152+ our_keys = 0
153+ for key in psbt_in .hd_keypaths .keys ():
154+ keypath = psbt_in .hd_keypaths [key ]
155+ if keypath .fingerprint == master_fp and key not in psbt_in .partial_sigs :
156+ our_keys += 1
157+ if our_keys > passes :
158+ passes = our_keys
143159
144160 for _ in range (passes ):
145161 # Get psbt in hex and then make binary
@@ -390,13 +406,27 @@ def toggle_passphrase(self) -> bool:
390406 """
391407 raise UnavailableActionError ('The Coldcard does not support toggling passphrase from the host' )
392408
393- def can_sign_taproot (self ) -> bool :
409+ def firmware_version (self ) -> str :
410+ return self .device .send_recv (CCProtocolPacker .version ()).split ("\n " )[1 ]
411+
412+ def is_edge_firmware (self ):
413+ """
414+ :return: True if this device is running EDGE firmware, False otherwise
394415 """
395- The Coldard does not support Taproot yet.
416+ if self .device .is_simulator :
417+ cmd = "import version; RV.write(str(int(getattr(version, 'is_edge', 0))))"
418+ rv = self .device .send_recv (b'EXEC' + cmd .encode ('utf-8' ), timeout = 60000 , encrypt = False )
419+ return rv == b"1"
420+ else :
421+ _ , ver , _ , _ , _ = self .device .send_recv (CCProtocolPacker .version ()).split ("\n " )
422+ return "X" == self .firmware_version ()[- 1 ]
396423
397- :returns: False, always
424+ def can_sign_taproot (self ) -> bool :
425+ """
426+ Only COLDCARD EDGE support taproot.
427+ :returns: Whether Taproot is supported
398428 """
399- return False
429+ return self . is_edge
400430
401431
402432def enumerate (password : Optional [str ] = None , expert : bool = False , chain : Chain = Chain .MAIN , allow_emulators : bool = True ) -> List [Dict [str , Any ]]:
@@ -422,6 +452,9 @@ def enumerate(password: Optional[str] = None, expert: bool = False, chain: Chain
422452 with handle_errors (common_err_msgs ["enumerate" ], d_data ):
423453 try :
424454 client = ColdcardClient (path )
455+ if client .is_edge :
456+ d_data ['label' ] = 'edge'
457+ d_data ['model' ] = 'edge_' + d_data ['model' ]
425458 d_data ['fingerprint' ] = client .get_master_fingerprint ().hex ()
426459 except RuntimeError as e :
427460 # Skip the simulator if it's not there
0 commit comments