iwa 0.0.1a5__py3-none-any.whl → 0.0.2__py3-none-any.whl

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.
iwa/core/chain/models.py CHANGED
@@ -78,6 +78,15 @@ class Gnosis(SupportedChain):
78
78
  if not self.rpcs and secrets.gnosis_rpc:
79
79
  self.rpcs = secrets.gnosis_rpc.get_secret_value().split(",")
80
80
 
81
+ # Defensive: ensure no comma-separated strings in list
82
+ new_rpcs = []
83
+ for rpc in self.rpcs:
84
+ if "," in rpc:
85
+ new_rpcs.extend([r.strip() for r in rpc.split(",") if r.strip()])
86
+ else:
87
+ new_rpcs.append(rpc)
88
+ self.rpcs = new_rpcs
89
+
81
90
 
82
91
  @singleton
83
92
  class Ethereum(SupportedChain):
@@ -98,6 +107,15 @@ class Ethereum(SupportedChain):
98
107
  if not self.rpcs and secrets.ethereum_rpc:
99
108
  self.rpcs = secrets.ethereum_rpc.get_secret_value().split(",")
100
109
 
110
+ # Defensive: ensure no comma-separated strings in list
111
+ new_rpcs = []
112
+ for rpc in self.rpcs:
113
+ if "," in rpc:
114
+ new_rpcs.extend([r.strip() for r in rpc.split(",") if r.strip()])
115
+ else:
116
+ new_rpcs.append(rpc)
117
+ self.rpcs = new_rpcs
118
+
101
119
 
102
120
  @singleton
103
121
  class Base(SupportedChain):
@@ -118,6 +136,15 @@ class Base(SupportedChain):
118
136
  if not self.rpcs and secrets.base_rpc:
119
137
  self.rpcs = secrets.base_rpc.get_secret_value().split(",")
120
138
 
139
+ # Defensive: ensure no comma-separated strings in list
140
+ new_rpcs = []
141
+ for rpc in self.rpcs:
142
+ if "," in rpc:
143
+ new_rpcs.extend([r.strip() for r in rpc.split(",") if r.strip()])
144
+ else:
145
+ new_rpcs.append(rpc)
146
+ self.rpcs = new_rpcs
147
+
121
148
 
122
149
  @singleton
123
150
  class SupportedChains:
iwa/core/constants.py CHANGED
@@ -16,7 +16,7 @@ WALLET_PATH = DATA_DIR / "wallet.json"
16
16
  BACKUP_DIR = DATA_DIR / "backup"
17
17
  TENDERLY_CONFIG_PATH = Path("tenderly.yaml")
18
18
 
19
- ABI_PATH = PROJECT_ROOT / "src" / "iwa" / "core" / "contracts" / "abis"
19
+ ABI_PATH = Path(__file__).parent / "contracts" / "abis"
20
20
 
21
21
  # Standard Ethereum addresses
22
22
  ZERO_ADDRESS = EthereumAddress("0x0000000000000000000000000000000000000000")
iwa/core/pricing.py CHANGED
@@ -45,7 +45,13 @@ class PriceService:
45
45
  if datetime.now() - entry["timestamp"] < self.cache_ttl:
46
46
  return entry["price"]
47
47
 
48
- # Fetch from API with 2 retries
48
+ price = self._fetch_price_from_api(token_id, vs_currency)
49
+ if price is not None:
50
+ self.cache[cache_key] = {"price": price, "timestamp": datetime.now()}
51
+ return price
52
+
53
+ def _fetch_price_from_api(self, token_id: str, vs_currency: str) -> Optional[float]:
54
+ """Fetch price from API with retries and key fallback."""
49
55
  max_retries = 2
50
56
  for attempt in range(max_retries + 1):
51
57
  try:
@@ -57,9 +63,16 @@ class PriceService:
57
63
 
58
64
  response = requests.get(url, params=params, headers=headers, timeout=10)
59
65
 
66
+ if response.status_code == 401 and self.api_key:
67
+ logger.warning("CoinGecko API key invalid (401). Retrying without key...")
68
+ self.api_key = None
69
+ headers.pop("x-cg-demo-api-key", None)
70
+ response = requests.get(url, params=params, headers=headers, timeout=10)
71
+
60
72
  if response.status_code == 429:
61
73
  logger.warning(
62
- f"CoinGecko rate limit reached (429) for {token_id}. Attempt {attempt + 1}/{max_retries + 1}"
74
+ f"CoinGecko rate limit reached (429) for {token_id}. "
75
+ f"Attempt {attempt + 1}/{max_retries + 1}"
63
76
  )
64
77
  if attempt < max_retries:
65
78
  time.sleep(2 * (attempt + 1))
@@ -67,25 +80,19 @@ class PriceService:
67
80
  return None
68
81
 
69
82
  response.raise_for_status()
70
-
71
83
  data = response.json()
84
+
72
85
  if token_id in data and vs_currency in data[token_id]:
73
- price = float(data[token_id][vs_currency])
86
+ return float(data[token_id][vs_currency])
74
87
 
75
- # Update cache
76
- self.cache[cache_key] = {"price": price, "timestamp": datetime.now()}
77
- return price
78
- else:
79
- logger.warning(
80
- f"Price for {token_id} in {vs_currency} not found in response: {data}"
81
- )
82
- # Don't cache None, might be a temporary hiccup
83
- return None
88
+ logger.warning(
89
+ f"Price for {token_id} in {vs_currency} not found in response: {data}"
90
+ )
91
+ return None
84
92
 
85
93
  except Exception as e:
86
94
  logger.error(f"Failed to fetch price for {token_id} (Attempt {attempt + 1}): {e}")
87
95
  if attempt < max_retries:
88
96
  time.sleep(1)
89
97
  continue
90
- return None
91
98
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: iwa
3
- Version: 0.0.1a5
3
+ Version: 0.0.2
4
4
  Summary: A secure, modular, and plugin-based framework for crypto agents and ops
5
5
  Requires-Python: <4.0,>=3.12
6
6
  Description-Content-Type: text/markdown
@@ -2,7 +2,7 @@ iwa/__init__.py,sha256=vu12UytYNREtMRvIWp6AfV1GgUe53XWwCMhYyqKAPgo,19
2
2
  iwa/__main__.py,sha256=eJU5Uxeu9Y7shWg5dt5Mcq0pMC4wFVNWjeYGKSf4Apw,88
3
3
  iwa/core/__init__.py,sha256=GJv4LJOXeZ3hgGvbt5I6omkoFkP2A9qhHjpDlOep9ik,24
4
4
  iwa/core/cli.py,sha256=iUZ3VBUwjYLp_m8UxvMrIsIDxUs2n5a6zVElLiDfSwo,7507
5
- iwa/core/constants.py,sha256=JBjGyxpAdsn8mBOWHljllmAw45oGNgi8qqkH_vYkcrg,982
5
+ iwa/core/constants.py,sha256=En-1uT5Anv0_NCSMdQjTGvjqiNAWfbSb_kGlH4Ct0Ag,966
6
6
  iwa/core/db.py,sha256=WI-mP0tQAmwFPeEi9w7RCa_Mcf_zBfd_7JcbHJwU1aU,10377
7
7
  iwa/core/ipfs.py,sha256=aHjq_pflgwDVHl8g5EMQv0q2RAmMs-a0pOTVsj_L5xE,4980
8
8
  iwa/core/keys.py,sha256=ckacVZxm_02V9hlmHIxz-CkxjXdGHqvGGAXfO6EeHCw,22365
@@ -10,7 +10,7 @@ iwa/core/mnemonic.py,sha256=LiG1VmpydQoHQ0pHUJ1OIlrWJry47VSMnOqPM_Yk-O8,12930
10
10
  iwa/core/models.py,sha256=kBQ0cBe6uFmL2QfW7mjKiMFeZxhT-FRN-RyK3Ko0vE8,12849
11
11
  iwa/core/monitor.py,sha256=OmhKVMkfhvtxig3wDUL6iGwBIClTx0YUqMncCao4SqI,7953
12
12
  iwa/core/plugins.py,sha256=FLvOG4S397fKi0aTH1fWBEtexn4yvGv_QzGWqFrhSKE,1102
13
- iwa/core/pricing.py,sha256=yC_zMT30KBZStLvQ0OEm6KmL6jn_B3kP2iBOVc5avU4,3211
13
+ iwa/core/pricing.py,sha256=5D2WAaDRuY1iOmj9fwgh_etnjjU6wdJmIgwoy8DbA2E,3614
14
14
  iwa/core/secrets.py,sha256=U7DZKrwKuSOFV00Ij3ISrrO1cWn_t1GBW_0PyAqjcD4,2588
15
15
  iwa/core/tables.py,sha256=y7Cg67PAGHYVMVyAjbo_CQ9t2iz7UXE-OTuUHRyFRTo,2021
16
16
  iwa/core/test.py,sha256=gey0dql5eajo1itOhgkSrgfyGWue2eSfpr0xzX3vc38,643
@@ -22,7 +22,7 @@ iwa/core/chain/__init__.py,sha256=XJMmn0ed-_aVkY2iEMKpuTxPgIKBd41dexSVmEZTa-o,16
22
22
  iwa/core/chain/errors.py,sha256=9SEbhxZ-qASPkzt-DoI51qq0GRJVqRgqgL720gO7a64,1275
23
23
  iwa/core/chain/interface.py,sha256=3tyMvnOZCTTvM0Y3YgxuN6zlXyJ1EIZUoyVosGtsUI8,20228
24
24
  iwa/core/chain/manager.py,sha256=cFEzh6pK5OyVhjhpeMAqhc9RnRDQR1DjIGiGKp-FXBI,1159
25
- iwa/core/chain/models.py,sha256=ZVhzde2yHS50qYKkgpeWzFRtjnp2HiFU_D10SrD8RYI,4035
25
+ iwa/core/chain/models.py,sha256=h3-vygtsAHaY1-JSqTujr0JYs7OpzBfYTRsh-vOoEV4,4962
26
26
  iwa/core/chain/rate_limiter.py,sha256=gU7TmWdH9D_wbXKT1X7mIgoIUCWVuebgvRhxiyLGAmI,6613
27
27
  iwa/core/contracts/__init__.py,sha256=P5GFY_pnuI02teqVY2U0t98bn1_SSPAbcAzRMpCdTi4,34
28
28
  iwa/core/contracts/contract.py,sha256=ERWViqZNqhsmf-tKVxn5XfQTJ8S_1MXVk0Tjq8davd0,11228
@@ -149,7 +149,7 @@ iwa/web/tests/test_web_endpoints.py,sha256=vZUGmrudkQHA8gBmSyO8i2SgZpsr1He-YRm2J
149
149
  iwa/web/tests/test_web_olas.py,sha256=oN__4nUT_H_j-_ALEqSp-si5xMbY0Bcxhvhuhxsg4Q8,16292
150
150
  iwa/web/tests/test_web_swap.py,sha256=7A4gBJFL01kIXPtW1E1J17SCsVc_0DmUn-R8kKrnnVA,2974
151
151
  iwa/web/tests/test_web_swap_coverage.py,sha256=zGNrzlhZ_vWDCvWmLcoUwFgqxnrp_ACbo49AtWBS_Kw,5584
152
- iwa-0.0.1a5.dist-info/licenses/LICENSE,sha256=eIubm_IlBHPYRQlLNZKbBNKhJUUP3JH0A2miZUhAVfI,1078
152
+ iwa-0.0.2.dist-info/licenses/LICENSE,sha256=eIubm_IlBHPYRQlLNZKbBNKhJUUP3JH0A2miZUhAVfI,1078
153
153
  tests/legacy_cow.py,sha256=oOkZvIxL70ReEoD9oHQbOD5GpjIr6AGNHcOCgfPlerU,8389
154
154
  tests/legacy_safe.py,sha256=AssM2g13E74dNGODu_H0Q0y412lgqsrYnEzI97nm_Ts,2972
155
155
  tests/legacy_transaction_retry_logic.py,sha256=D9RqZ7DBu61Xr2djBAodU2p9UE939LL-DnQXswX5iQk,1497
@@ -199,8 +199,8 @@ tests/test_ui_coverage.py,sha256=N-7uhPlKOXCKyS32VjwG3JQRnAS1PoAJxR-InaOZtCQ,242
199
199
  tests/test_utils.py,sha256=vkP49rYNI8BRzLpWR3WnKdDr8upeZjZcs7Rx0pjbQMo,1292
200
200
  tests/test_workers.py,sha256=MInwdkFY5LdmFB3o1odIaSD7AQZb3263hNafO1De5PE,2793
201
201
  tools/verify_drain.py,sha256=1On4GmXWETA-CHfFjd7qAqIQuSgKIaEomKKXM7S8wfk,6881
202
- iwa-0.0.1a5.dist-info/METADATA,sha256=QoKlrod8k2js2_pYay2mKrH7dPLq9pwT0Hwg0IJjbFs,7296
203
- iwa-0.0.1a5.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
204
- iwa-0.0.1a5.dist-info/entry_points.txt,sha256=nwB6kscrfA7M00pYmL2j-sBH6eF6h2ga9IK1BZxdiyQ,241
205
- iwa-0.0.1a5.dist-info/top_level.txt,sha256=kedS9cRUbm4JE2wYeabIXilhHjN8KCw0IGbqqqsw0Bs,16
206
- iwa-0.0.1a5.dist-info/RECORD,,
202
+ iwa-0.0.2.dist-info/METADATA,sha256=LI8zcRvzlRmevpeYLa1O5KdZbF6GX5L-Xp7QLUcgSI8,7294
203
+ iwa-0.0.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
204
+ iwa-0.0.2.dist-info/entry_points.txt,sha256=nwB6kscrfA7M00pYmL2j-sBH6eF6h2ga9IK1BZxdiyQ,241
205
+ iwa-0.0.2.dist-info/top_level.txt,sha256=kedS9cRUbm4JE2wYeabIXilhHjN8KCw0IGbqqqsw0Bs,16
206
+ iwa-0.0.2.dist-info/RECORD,,
File without changes