-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgenerator.py
133 lines (110 loc) · 4.9 KB
/
generator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
import hashlib
import time
import base64
import json
from tonsdk.contract.wallet import Wallets, WalletVersionEnum
from tonsdk.utils import bytes_to_b64str
from nacl.signing import SigningKey
from typing import Optional, List
async def wallet(mnemonic: Optional[List[str]] = None):
"""
This function creates or loads a wallet depending on whether a mnemonic is provided.
- If a mnemonic is provided, it loads the wallet using the mnemonic phrase.
- If no mnemonic is provided, it creates a new wallet.
The function returns the following details:
- Wallet address
- Secret key (first 32 bytes of private key)
- Mnemonic phrase as a string
- Ton address in user-friendly format
- Public key in hexadecimal format
- Private key in hexadecimal format
- State initialization data in base64 format
Args:
- mnemonic (Optional[List[str]]): A list of words representing the mnemonic phrase to load an existing wallet. Defaults to None.
Returns:
- Tuple: Contains wallet address, secret key, mnemonic, user-friendly Ton address, public key, private key, and state_init.
"""
if mnemonic is None:
mnemonic, pub_k, priv_k, wallet = Wallets.create(WalletVersionEnum.v4r2, workchain=0)
else:
mnemonic, pub_k, priv_k, wallet = Wallets.from_mnemonics(mnemonic, WalletVersionEnum.v4r2, workchain=0)
state = wallet.create_state_init()
init = state["state_init"]
address = wallet.address.to_string(is_user_friendly=False)
secret_key = priv_k[:32]
mnemonics = " ".join(mnemonic)
address_ton = wallet.address.to_string(True, True, False)
public_key = pub_k.hex()
private_key = priv_k.hex()
state_init = bytes_to_b64str(init.to_boc(has_idx=False))
return address, secret_key, mnemonics, address_ton, public_key, private_key, state_init
async def proof(manifest_url: str, payload: str, mnemonic: Optional[str] = None):
"""
This function creates a proof by signing a message and returning the proof details in a structured format.
- The proof is generated by hashing the address, domain (manifest URL), timestamp, and payload.
- It then signs the resulting hash using the wallet's private key.
- The final proof contains the signature and other details such as the wallet information, timestamp, and state initialization.
Args:
- manifest_url (str): The URL from the manifest (domain) to include in the proof.
- payload (str): The payload (data) to be included in the proof.
- mnemonic (Optional[str]): A string representing the mnemonic phrase for the wallet. Defaults to None.
Returns:
- str: A JSON string containing the wallet information (mnemonics, Ton address, public/private keys)
and the proof details (signature, timestamp, domain, state init, etc.).
"""
if mnemonic is not None:
phrase = mnemonic.split()
else:
phrase = None
address, secret_key, mnemonics, address_ton, public_key, private_key, state_init = await wallet(phrase)
try:
timestamp = int(time.time())
timestamp_bytes = timestamp.to_bytes(8, 'little')
domain = manifest_url
domain_bytes = domain.encode('utf-8')
domain_len_bytes = len(domain_bytes).to_bytes(4, 'little')
workchain, addr_hash = address.split(':')
workchain_bytes = int(workchain).to_bytes(4, 'big')
address_bytes = workchain_bytes + bytes.fromhex(addr_hash)
msg_bytes = b''.join([
b'ton-proof-item-v2/',
address_bytes,
domain_len_bytes,
domain_bytes,
timestamp_bytes,
payload.encode('utf-8') if payload else b'',
])
msg_hash = hashlib.sha256(msg_bytes).digest()
buffer_bytes = b''.join([
bytes.fromhex('ffff'),
b'ton-connect',
msg_hash
])
key = SigningKey(secret_key)
data = key.sign(hashlib.sha256(buffer_bytes).digest())
signature = base64.b64encode(data.signature).decode('utf-8')
proof = {
"wallet": {
"mnemonics": mnemonics,
"ton_address": address_ton
},
"address": address,
"network": "-239",
"public_key": public_key,
"private_key": private_key,
"proof": {
"name": "ton_proof",
"timestamp": timestamp,
"domain": {
"lengthBytes": len(domain_bytes),
"value": domain
},
"signature": signature,
"payload": payload,
"state_init": state_init
}
}
return json.dumps(proof, indent=4)
except Exception as e:
print(f"CreateTonProof: {e} | {str(e)}")
return None