12
12
from .keychain import sign_data , Key
13
13
from .tlv import format_tlv
14
14
15
+ from hashlib import sha256
15
16
from web3 import Web3
16
17
17
18
@@ -43,21 +44,25 @@ class TrustedNameSource(IntEnum):
43
44
DNS = 0x05
44
45
45
46
46
- class TrustedNameTag (IntEnum ):
47
+ class FieldTag (IntEnum ):
47
48
STRUCT_TYPE = 0x01
48
49
STRUCT_VERSION = 0x02
49
50
NOT_VALID_AFTER = 0x10
50
51
CHALLENGE = 0x12
51
52
SIGNER_KEY_ID = 0x13
52
53
SIGNER_ALGO = 0x14
53
- SIGNATURE = 0x15
54
- NAME = 0x20
54
+ DER_SIGNATURE = 0x15
55
+ TRUSTED_NAME = 0x20
55
56
COIN_TYPE = 0x21
56
57
ADDRESS = 0x22
57
58
CHAIN_ID = 0x23
58
- NAME_TYPE = 0x70
59
- NAME_SOURCE = 0x71
60
- NFT_ID = 0x72
59
+ TICKER = 0x24
60
+ BLOCKCHAIN_FAMILY = 0x51
61
+ NETWORK_NAME = 0x52
62
+ NETWORK_ICON_HASH = 0x53
63
+ TRUSTED_NAME_TYPE = 0x70
64
+ TRUSTED_NAME_SOURCE = 0x71
65
+ TRUSTED_NAME_NFT_ID = 0x72
61
66
62
67
63
68
class PKIPubKeyUsage (IntEnum ):
@@ -266,22 +271,22 @@ def _provide_trusted_name_common(self, payload: bytes) -> RAPDU:
266
271
# pylint: enable=line-too-long
267
272
268
273
self ._pki_client .send_certificate (PKIPubKeyUsage .PUBKEY_USAGE_COIN_META , bytes .fromhex (cert_apdu ))
269
- payload += format_tlv (TrustedNameTag .STRUCT_TYPE , 3 ) # TrustedName
270
- payload += format_tlv (TrustedNameTag .SIGNER_KEY_ID , 0 ) # test key
271
- payload += format_tlv (TrustedNameTag .SIGNER_ALGO , 1 ) # secp256k1
272
- payload += format_tlv (TrustedNameTag . SIGNATURE ,
274
+ payload += format_tlv (FieldTag .STRUCT_TYPE , 3 ) # TrustedName
275
+ payload += format_tlv (FieldTag .SIGNER_KEY_ID , 0 ) # test key
276
+ payload += format_tlv (FieldTag .SIGNER_ALGO , 1 ) # secp256k1
277
+ payload += format_tlv (FieldTag . DER_SIGNATURE ,
273
278
sign_data (Key .TRUSTED_NAME , payload ))
274
279
chunks = self ._cmd_builder .provide_trusted_name (payload )
275
280
for chunk in chunks [:- 1 ]:
276
281
self ._exchange (chunk )
277
282
return self ._exchange (chunks [- 1 ])
278
283
279
284
def provide_trusted_name_v1 (self , addr : bytes , name : str , challenge : int ) -> RAPDU :
280
- payload = format_tlv (TrustedNameTag .STRUCT_VERSION , 1 )
281
- payload += format_tlv (TrustedNameTag .CHALLENGE , challenge )
282
- payload += format_tlv (TrustedNameTag .COIN_TYPE , 0x3c ) # ETH in slip-44
283
- payload += format_tlv (TrustedNameTag . NAME , name )
284
- payload += format_tlv (TrustedNameTag .ADDRESS , addr )
285
+ payload = format_tlv (FieldTag .STRUCT_VERSION , 1 )
286
+ payload += format_tlv (FieldTag .CHALLENGE , challenge )
287
+ payload += format_tlv (FieldTag .COIN_TYPE , 0x3c ) # ETH in slip-44
288
+ payload += format_tlv (FieldTag . TRUSTED_NAME , name )
289
+ payload += format_tlv (FieldTag .ADDRESS , addr )
285
290
return self ._provide_trusted_name_common (payload )
286
291
287
292
def provide_trusted_name_v2 (self ,
@@ -293,19 +298,19 @@ def provide_trusted_name_v2(self,
293
298
nft_id : Optional [int ] = None ,
294
299
challenge : Optional [int ] = None ,
295
300
not_valid_after : Optional [tuple [int ]] = None ) -> RAPDU :
296
- payload = format_tlv (TrustedNameTag .STRUCT_VERSION , 2 )
297
- payload += format_tlv (TrustedNameTag . NAME , name )
298
- payload += format_tlv (TrustedNameTag .ADDRESS , addr )
299
- payload += format_tlv (TrustedNameTag . NAME_TYPE , name_type )
300
- payload += format_tlv (TrustedNameTag . NAME_SOURCE , name_source )
301
- payload += format_tlv (TrustedNameTag .CHAIN_ID , chain_id )
301
+ payload = format_tlv (FieldTag .STRUCT_VERSION , 2 )
302
+ payload += format_tlv (FieldTag . TRUSTED_NAME , name )
303
+ payload += format_tlv (FieldTag .ADDRESS , addr )
304
+ payload += format_tlv (FieldTag . TRUSTED_NAME_TYPE , name_type )
305
+ payload += format_tlv (FieldTag . TRUSTED_NAME_SOURCE , name_source )
306
+ payload += format_tlv (FieldTag .CHAIN_ID , chain_id )
302
307
if nft_id is not None :
303
- payload += format_tlv (TrustedNameTag . NFT_ID , nft_id )
308
+ payload += format_tlv (FieldTag . TRUSTED_NAME_NFT_ID , nft_id )
304
309
if challenge is not None :
305
- payload += format_tlv (TrustedNameTag .CHALLENGE , challenge )
310
+ payload += format_tlv (FieldTag .CHALLENGE , challenge )
306
311
if not_valid_after is not None :
307
312
assert len (not_valid_after ) == 3
308
- payload += format_tlv (TrustedNameTag .NOT_VALID_AFTER , struct .pack ("BBB" , * not_valid_after ))
313
+ payload += format_tlv (FieldTag .NOT_VALID_AFTER , struct .pack ("BBB" , * not_valid_after ))
309
314
return self ._provide_trusted_name_common (payload )
310
315
311
316
def set_plugin (self ,
@@ -468,3 +473,54 @@ def provide_token_metadata(self,
468
473
decimals ,
469
474
chain_id ,
470
475
sig ))
476
+
477
+ def _prepare_network_info (self ,
478
+ name : str ,
479
+ ticker : str ,
480
+ chain_id : int ,
481
+ icon : Optional [bytes ] = None ) -> bytes :
482
+
483
+ payload = format_tlv (FieldTag .STRUCT_TYPE , 8 )
484
+ payload += format_tlv (FieldTag .STRUCT_VERSION , 1 )
485
+ payload += format_tlv (FieldTag .BLOCKCHAIN_FAMILY , 1 )
486
+ payload += format_tlv (FieldTag .CHAIN_ID , chain_id .to_bytes (8 , 'big' ))
487
+ payload += format_tlv (FieldTag .NETWORK_NAME , name .encode ('utf-8' ))
488
+ payload += format_tlv (FieldTag .TICKER , ticker .encode ('utf-8' ))
489
+ if icon :
490
+ # Network Icon
491
+ payload += format_tlv (FieldTag .NETWORK_ICON_HASH , sha256 (icon ).digest ())
492
+ # Append the data Signature
493
+ payload += format_tlv (FieldTag .DER_SIGNATURE ,
494
+ sign_data (Key .CAL , payload ))
495
+ return payload
496
+
497
+ def provide_network_information (self ,
498
+ name : str ,
499
+ ticker : str ,
500
+ chain_id : int ,
501
+ icon : Optional [bytes ] = None ) -> RAPDU :
502
+
503
+ if self ._pki_client is None :
504
+ print (f"Ledger-PKI Not supported on '{ self ._firmware .name } '" )
505
+ else :
506
+ # pylint: disable=line-too-long
507
+ if self ._firmware == Firmware .NANOSP :
508
+ cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010310040102000015473045022100C15795C2AE41E6FAE6B1362EE1AE216428507D7C1D6939B928559CC7A1F6425C02206139CF2E133DD62F3E00F183E42109C9853AC62B6B70C5079B9A80DBB9D54AB5" # noqa: E501
509
+ elif self ._firmware == Firmware .NANOX :
510
+ cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010215473045022100E3B956F93FBFF0D41908483888F0F75D4714662A692F7A38DC6C41A13294F9370220471991BECB3CA4F43413CADC8FF738A8CC03568BFA832B4DCFE8C469080984E5" # noqa: E501
511
+ elif self ._firmware == Firmware .STAX :
512
+ cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C6405618873401013501041546304402206731FCD3E2432C5CA162381392FD17AD3A41EEF852E1D706F21A656AB165263602204B89FAE8DBAF191E2D79FB00EBA80D613CB7EDF0BE960CB6F6B29D96E1437F5F" # noqa: E501
513
+ elif self ._firmware == Firmware .FLEX :
514
+ cert_apdu = "01010102010211040000000212010013020002140101160400000000200B45524332305F546F6B656E300200063101083201213321024CCA8FAD496AA5040A00A7EB2F5CC3B85376D88BA147A7D7054A99C64056188734010135010515473045022100B59EA8B958AA40578A6FBE9BBFB761020ACD5DBD8AA863C11DA17F42B2AFDE790220186316059EFA58811337D47C7F815F772EA42BBBCEA4AE123D1118C80588F5CB" # noqa: E501
515
+ # pylint: enable=line-too-long
516
+
517
+ self ._pki_client .send_certificate (PKIPubKeyUsage .PUBKEY_USAGE_COIN_META , bytes .fromhex (cert_apdu ))
518
+
519
+ # Add the network info
520
+ payload = self ._prepare_network_info (name , ticker , chain_id , icon )
521
+ chunks = self ._cmd_builder .provide_network_information (payload , icon )
522
+ for chunk in chunks [:- 1 ]:
523
+ response = self ._exchange (chunk )
524
+ assert response .status == StatusWord .OK
525
+ response = self ._exchange (chunks [- 1 ])
526
+ assert response .status == StatusWord .OK
0 commit comments