oli-python 2.0.4__tar.gz → 2.0.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oli-python
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Python SDK for interacting with the Open Labels Initiative; A standard, registry and trust layer for EVM address labels.
5
5
  Home-page: https://github.com/openlabelsinitiative/oli-python
6
6
  Author: Lorenz Lehmann
@@ -32,6 +32,8 @@ Dynamic: summary
32
32
 
33
33
  This SDK lets you read, write, validate, and revoke address labels within the **OLI Label Pool** and compute confidence scores based on attesters' relationships within the **OLI Label Trust**.
34
34
 
35
+ [Video Walkthrough](https://x.com/open_labels/status/1994353238699651328)
36
+
35
37
  ## Installation
36
38
 
37
39
  ```bash
@@ -4,6 +4,8 @@
4
4
 
5
5
  This SDK lets you read, write, validate, and revoke address labels within the **OLI Label Pool** and compute confidence scores based on attesters' relationships within the **OLI Label Trust**.
6
6
 
7
+ [Video Walkthrough](https://x.com/open_labels/status/1994353238699651328)
8
+
7
9
  ## Installation
8
10
 
9
11
  ```bash
@@ -41,12 +41,15 @@ class OffchainAttestations:
41
41
  else:
42
42
  print("Warning: OLI tag definitions not loaded, skipping tag formatting and validation. Please upgrade to the latest OLI version and ensure internet connectivity at initialization.")
43
43
 
44
+ # Merge chain_id (CAIP2) & address to CAIP10 format
45
+ caip10 = f"{chain_id}:{address}"
46
+
44
47
  # Encode the label data
45
- data = self.oli.utils_other.encode_label_data(chain_id, tags)
48
+ data = self.oli.utils_other.encode_label_data(caip10, tags)
46
49
 
47
50
  # Build the attestation
48
51
  attestation = self.build_offchain_attestation(
49
- recipient=address,
52
+ recipient="0x0000000000000000000000000000000000000001", # use 0x...1 to track python tooling was used
50
53
  schema=self.oli.oli_label_pool_schema,
51
54
  data=data,
52
55
  ref_uid=ref_uid
@@ -108,12 +111,15 @@ class OffchainAttestations:
108
111
  else:
109
112
  print("Warning: OLI tag definitions not loaded, skipping tag formatting and validation. Please upgrade to the latest OLI version and ensure internet connectivity at initialization.")
110
113
 
114
+ # Merge chain_id (CAIP2) & address to CAIP10 format
115
+ caip10 = f"{chain_id}:{address}"
116
+
111
117
  # Encode the label data
112
- data = self.oli.utils_other.encode_label_data(chain_id, tags)
113
-
118
+ data = self.oli.utils_other.encode_label_data(caip10, tags)
119
+
114
120
  # Build the attestation
115
121
  attestation = self.build_offchain_attestation(
116
- recipient=address,
122
+ recipient="0x0000000000000000000000000000000000000001", # use 0x...1 to track python tooling was used
117
123
  schema=self.oli.oli_label_pool_schema,
118
124
  data=data,
119
125
  ref_uid=ref_uid
@@ -164,10 +170,9 @@ class OffchainAttestations:
164
170
  data = self.oli.utils_other.encode_list_data(owner_name, attesters, attestations)
165
171
 
166
172
  # Build the attestation
167
- recipient = "0x0000000000000000000000000000000000000000"
168
173
  ref_uid = "0x0000000000000000000000000000000000000000000000000000000000000000"
169
174
  attestation = self.build_offchain_attestation(
170
- recipient=recipient,
175
+ recipient="0x0000000000000000000000000000000000000001", # use 0x...1 to track python tooling was used
171
176
  schema=self.oli.oli_label_trust_schema,
172
177
  data=data,
173
178
  ref_uid=ref_uid
@@ -18,7 +18,7 @@ class OnchainAttestations:
18
18
  chain_id (str): Chain ID in CAIP-2 format where the address/contract resides
19
19
  tags (dict): OLI compliant tags as a dict information (name, version, etc.)
20
20
  ref_uid (str): Reference UID
21
- gas_limit (int): Gas limit for the transaction. If set to -1, the function will estimate the gas limit.
21
+ gas_limit (int): Gas limit for the transaction. If set to -1, the function will estimate the gas limit
22
22
 
23
23
  Returns:
24
24
  str: Transaction hash
@@ -36,14 +36,17 @@ class OnchainAttestations:
36
36
  else:
37
37
  print("Warning: OLI tag definitions not loaded, skipping tag formatting and validation. Please upgrade to the latest OLI version and ensure internet connectivity at initialization.")
38
38
 
39
+ # Prepare CAIP10 format for the address
40
+ caip10 = f"{chain_id}:{address}"
41
+
39
42
  # Encode the label data
40
- data = self.oli.utils_other.encode_label_data(chain_id, tags)
43
+ data = self.oli.utils_other.encode_label_data(caip10, tags)
41
44
 
42
45
  # Create the attestation
43
46
  function = self.oli.eas.functions.attest({
44
47
  'schema': self.oli.w3.to_bytes(hexstr=self.oli.oli_label_pool_schema),
45
48
  'data': {
46
- 'recipient': self.oli.w3.to_checksum_address(address),
49
+ 'recipient': "0x0000000000000000000000000000000000000001", # use 0x...1 to track python tooling was used
47
50
  'expirationTime': 0,
48
51
  'revocable': True,
49
52
  'refUID': self.oli.w3.to_bytes(hexstr=ref_uid),
@@ -128,10 +131,13 @@ class OnchainAttestations:
128
131
  else:
129
132
  self.oli.validator.validate_ref_uid(label['ref_uid'])
130
133
 
134
+ # Merge chain_id (CAIP2) & address to CAIP10 format
135
+ caip10 = f"{label['chain_id']}:{label['address']}"
136
+
131
137
  # ABI encode data for each attestation
132
- data = self.oli.utils_other.encode_label_data(label['chain_id'], label['tags'])
138
+ data = self.oli.utils_other.encode_label_data(caip10, label['tags'])
133
139
  full_data.append({
134
- 'recipient': self.oli.w3.to_checksum_address(label['address']),
140
+ 'recipient': "0x0000000000000000000000000000000000000001", # use 0x...1 to track python tooling was used
135
141
  'expirationTime': 0,
136
142
  'revocable': True,
137
143
  'refUID': self.oli.w3.to_bytes(hexstr=label['ref_uid']),
@@ -206,7 +212,7 @@ class OnchainAttestations:
206
212
  function = self.oli.eas.functions.attest({
207
213
  'schema': self.oli.w3.to_bytes(hexstr=self.oli.oli_label_trust_schema),
208
214
  'data': {
209
- 'recipient': "0x0000000000000000000000000000000000000000", # Trust lists are not tied to a specific address
215
+ 'recipient': "0x0000000000000000000000000000000000000001", # Trust lists are not tied to a specific address, use 0x...1 to track python tooling was used
210
216
  'expirationTime': 0, # never expires
211
217
  'revocable': True, # can be revoked
212
218
  'refUID': "0x0000000000000000000000000000000000000000000000000000000000000000", # no ref UID for trust lists
@@ -13,12 +13,12 @@ class UtilsOther:
13
13
  """
14
14
  self.oli = oli_client
15
15
 
16
- def encode_label_data(self, chain_id: str, tags_json: dict) -> str:
16
+ def encode_label_data(self, caip10: str, tags_json: dict) -> str:
17
17
  """
18
18
  Encode label data in the OLI format.
19
19
 
20
20
  Args:
21
- chain_id (str): Chain ID in CAIP-2 format of the label (e.g. 'eip155:8453')
21
+ caip10 (str): address and chain_id in caip10 format (e.g. 'eip155:8453:0x3Ae5F83668B75328446c649B6ab342aC46D73B3c')
22
22
  tags_json (dict): Dictionary of tag data following the OLI format
23
23
 
24
24
  Returns:
@@ -27,9 +27,15 @@ class UtilsOther:
27
27
  # Convert dict to JSON string if needed
28
28
  if isinstance(tags_json, dict):
29
29
  tags_json = json.dumps(tags_json)
30
+
31
+ # Convert address to checksum if possible
32
+ try:
33
+ caip10 = caip10[:caip10.rfind(":")+1] + self.oli.w3.to_checksum_address(caip10.split(":")[-1])
34
+ except:
35
+ pass
30
36
 
31
37
  # ABI encode the data
32
- encoded_data = encode(['string', 'string'], [chain_id, tags_json])
38
+ encoded_data = encode(['string', 'string'], [caip10, tags_json])
33
39
  return f"0x{encoded_data.hex()}"
34
40
 
35
41
  def encode_list_data(self, owner: str, trusted: list, untrusted: list) -> str:
@@ -7,28 +7,23 @@ class UtilsValidator:
7
7
  oli_client: The OLI client instance
8
8
  """
9
9
  self.oli = oli_client
10
- self.allowed_prefixes = [
11
- 'eip155:', # Ethereum and EVM-compatible chains
12
- 'solana:', # Solana
13
- 'tron:', # TRON
14
- 'stellar:', # Stellar
15
- 'bip122:', # Bitcoin
16
- 'SN_MAIN' # Starknet
17
- ]
18
10
  # URLs for helpful resources
19
11
  self.url_1_label_schema = "https://github.com/openlabelsinitiative/OLI/tree/main/1_label_schema"
20
12
  self.url_2_label_pool = "https://github.com/openlabelsinitiative/OLI/tree/main/2_label_pool"
21
13
  self.url_3_label_trust = "https://github.com/openlabelsinitiative/OLI/tree/main/3_label_trust"
22
14
  self.url_tag_definitions = "https://github.com/openlabelsinitiative/OLI/blob/main/1_label_schema/tags/tag_definitions.yml"
23
15
  self.url_caip2_format = "https://docs.portalhq.io/resources/chain-id-formatting"
16
+ self.url_caip10_format = "https://github.com/ChainAgnostic/CAIPs/blob/main/CAIPs/caip-10.md"
24
17
 
25
18
  def fix_simple_tags_formatting(self, tags: dict) -> dict:
26
19
  """
27
20
  Fix basic formatting in the tags dictionary. This includes:
28
21
  - Ensuring all tag_ids are lowercase
29
- - Booling values are converted from strings to booleans
30
22
  - Removing leading/trailing whitespace from string values
31
- - Checksum address (string(42)) tags
23
+ - Converting boolean values from strings/integers to booleans
24
+ (accepts: 'true'/'t'/'1'/1 for True, 'false'/'f'/'0'/0 for False, case-insensitive)
25
+ - Converting integer values from strings to integers
26
+ - Checksumming address (string(42)) tags
32
27
 
33
28
  Args:
34
29
  tags (dict): Dictionary of tags
@@ -39,17 +34,49 @@ class UtilsValidator:
39
34
  # Convert tag_ids to lowercase
40
35
  tags = {k.lower(): v for k, v in tags.items()}
41
36
 
42
- # Strip whitespaces, then turn boolean values from strings to booleans
37
+ # Strip whitespaces from strings
43
38
  for k, v in tags.items():
44
39
  if isinstance(v, str):
45
40
  tags[k] = v.strip()
46
- if tags[k] == 'true':
47
- tags[k] = True
48
- elif tags[k] == 'false':
49
- tags[k] = False
50
41
  elif isinstance(v, list):
51
42
  tags[k] = [i.strip() if isinstance(i, str) else i for i in v]
52
43
 
44
+ # Turn boolean strings to booleans based on schema
45
+ if self.oli.tag_definitions is not None:
46
+ boolean_keys = [
47
+ key
48
+ for key, value in self.oli.tag_definitions.items()
49
+ if value.get("schema", {}).get("type") == "boolean"
50
+ ]
51
+ for k, v in tags.items():
52
+ if k in boolean_keys:
53
+ if isinstance(v, str):
54
+ v_lower = v.lower()
55
+ if v_lower in ('true', 't', '1'):
56
+ tags[k] = True
57
+ elif v_lower in ('false', 'f', '0'):
58
+ tags[k] = False
59
+ elif isinstance(v, int):
60
+ if v == 1:
61
+ tags[k] = True
62
+ elif v == 0:
63
+ tags[k] = False
64
+
65
+ # Turn integer strings to integers based on schema
66
+ if self.oli.tag_definitions is not None:
67
+ integer_keys = [
68
+ key
69
+ for key, value in self.oli.tag_definitions.items()
70
+ if value.get("schema", {}).get("type") == "integer"
71
+ ]
72
+ for k, v in tags.items():
73
+ if k in integer_keys and isinstance(v, str):
74
+ if v.isdigit():
75
+ try:
76
+ tags[k] = int(v)
77
+ except ValueError:
78
+ pass
79
+
53
80
  # Checksum address tags
54
81
  for k, v in tags.items():
55
82
  if k in self.oli.tag_definitions and 'minLength' in self.oli.tag_definitions[k]['schema']:
@@ -63,7 +90,7 @@ class UtilsValidator:
63
90
  Validates if the label is compliant with the OLI Label Schema. See OLI Github documentation for more details: https://github.com/openlabelsinitiative/OLI/tree/main/1_label_schema
64
91
 
65
92
  Args:
66
- address (str): Address to check
93
+ address (str): Address that is labelled to check
67
94
  chain_id (str): Chain ID to check
68
95
  tags (dict): Tags to check
69
96
  ref_uid (str): Reference UID to check
@@ -73,7 +100,7 @@ class UtilsValidator:
73
100
  bool: True if the label is correct, False otherwise
74
101
  """
75
102
  # basic checks
76
- self.validate_address(address)
103
+ self.validate_address_to_be_labelled(address)
77
104
  self.validate_chain_id(chain_id)
78
105
  self.validate_tags(tags, auto_fix=auto_fix)
79
106
  self.validate_ref_uid(ref_uid)
@@ -111,25 +138,25 @@ class UtilsValidator:
111
138
  Returns:
112
139
  bool: True if correct, False otherwise
113
140
  """
114
- # Check if the chain_id starts with any of the allowed prefixes
115
- for prefix in self.allowed_prefixes:
116
- if chain_id.startswith(prefix):
117
- # For eip155, further validate that the rest is a number or 'any'
118
- if prefix == 'eip155:':
119
- rest = chain_id[len(prefix):]
120
- if rest.isdigit():
121
- return True
122
- elif rest == 'any':
123
- print("Please ensure the label is accurate and consistent across all EVM chains before setting chain_id = 'eip155:any'.")
124
- return True
125
- else:
126
- print(f"Invalid eip155 chain_id format: {chain_id}")
127
- raise ValueError("For eip155 chains, format must be 'eip155:' followed by a number or 'any'")
128
- return True
141
+ # Check if the chain_id has one ":" in it which is not at the start or end
142
+ if ":" in chain_id and chain_id.count(":") == 1 and chain_id.find(":") != 0 and chain_id.find(":") != len(chain_id)-1:
143
+ prefix = chain_id[:chain_id.find(":")+1].lower()
144
+ # For eip155, further validate that the rest is a number or 'any'
145
+ if prefix == 'eip155:':
146
+ rest = chain_id[len(prefix):]
147
+ if rest.isdigit():
148
+ return True
149
+ elif rest == 'any':
150
+ print("Please ensure the label is accurate and consistent across all EVM chains before setting chain_id = 'eip155:any'.")
151
+ return True
152
+ else:
153
+ print(f"Invalid eip155 chain_id format: {chain_id}")
154
+ raise ValueError("For eip155 chains, format must be 'eip155:' followed by a number or 'any'")
155
+ return True
129
156
 
130
157
  # If we get here, the chain_id didn't match any allowed format
131
158
  print(f"Unsupported chain ID format: {chain_id}")
132
- raise ValueError(f"Chain ID must be in CAIP-2 format (e.g., Base -> 'eip155:8453'), see this guide on CAIP-2: {self.url_caip2_format}")
159
+ raise ValueError(f"Chain ID must be in CAIP-2 format (e.g., Base -> 'eip155:8453' or Starknet -> 'starknet:SN_MAIN'), see this guide on CAIP-2: {self.url_caip2_format}")
133
160
 
134
161
  def validate_address(self, address: str) -> bool:
135
162
  """
@@ -147,6 +174,24 @@ class UtilsValidator:
147
174
  print(address)
148
175
  raise ValueError("Address must be a valid Ethereum address in hex format")
149
176
 
177
+ def validate_address_to_be_labelled(self, address: str) -> bool:
178
+ """
179
+ Validates if address to be labelled is within CAIP10 limits
180
+
181
+ Args:
182
+ address (str): Address to check
183
+
184
+ Returns:
185
+ bool: True if correct, False otherwise
186
+ """
187
+ if len(address) > 66 or len(address) == 0:
188
+ print(f"Unexpected address length ({len(address)}): '{address}'")
189
+ raise ValueError(f"Address to be labelled exceeds maximum length of 66 characters or is empty. See this guide on CAIP-10 address limitations: {self.url_caip10_format}")
190
+ if ":" in address:
191
+ print(f"Address to be labelled must not contain ':' character: '{address}'")
192
+ raise ValueError(f"Address to be labelled must not contain ':' character. See this guide on CAIP-10 address limitations: {self.url_caip10_format}")
193
+ return True
194
+
150
195
  def validate_tags(self, tags: dict, auto_fix: bool=False) -> bool:
151
196
  """
152
197
  Check if tags are in the correct format.
@@ -82,7 +82,7 @@ class OLI:
82
82
  self.source_address = None # for Label Trust
83
83
 
84
84
  # Label Pool Schema for OLI Label Pool
85
- self.oli_label_pool_schema = '0xb763e62d940bed6f527dd82418e146a904e62a297b8fa765c9b3e1f0bc6fdd68'
85
+ self.oli_label_pool_schema = '0xcff83309b59685fdae9dad7c63d969150676d51d8eeda66799d1c4898b84556a' # v2.0.0 of EAS schema
86
86
 
87
87
  # Label Trust Schema for OLI Label Trust
88
88
  self.oli_label_trust_schema = '0x6d780a85bfad501090cd82868a0c773c09beafda609d54888a65c106898c363d'
@@ -11,6 +11,7 @@ class API:
11
11
  """
12
12
  self.oli = oli_client
13
13
  self.api_url = "https://api.openlabelsinitiative.org"
14
+ self.api_url = "http://0.0.0.0:8080" # testing
14
15
  self.api_key = api_key
15
16
 
16
17
  ### OLI Tags and Value Sets maintained in Github ###
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oli-python
3
- Version: 2.0.4
3
+ Version: 2.0.6
4
4
  Summary: Python SDK for interacting with the Open Labels Initiative; A standard, registry and trust layer for EVM address labels.
5
5
  Home-page: https://github.com/openlabelsinitiative/oli-python
6
6
  Author: Lorenz Lehmann
@@ -32,6 +32,8 @@ Dynamic: summary
32
32
 
33
33
  This SDK lets you read, write, validate, and revoke address labels within the **OLI Label Pool** and compute confidence scores based on attesters' relationships within the **OLI Label Trust**.
34
34
 
35
+ [Video Walkthrough](https://x.com/open_labels/status/1994353238699651328)
36
+
35
37
  ## Installation
36
38
 
37
39
  ```bash
@@ -5,7 +5,7 @@ with open("README.md", "r", encoding="utf-8") as fh:
5
5
 
6
6
  setup(
7
7
  name="oli-python",
8
- version="2.0.4",
8
+ version="2.0.6",
9
9
  author="Lorenz Lehmann",
10
10
  author_email="lorenz@growthepie.com",
11
11
  description="Python SDK for interacting with the Open Labels Initiative; A standard, registry and trust layer for EVM address labels.",
File without changes
File without changes
File without changes
File without changes