Skip to content

Commit e563eec

Browse files
v14.3.2 (#49)
1 parent ecf7462 commit e563eec

File tree

5 files changed

+60
-29
lines changed

5 files changed

+60
-29
lines changed

.coverage

0 Bytes
Binary file not shown.

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,10 @@ config = {
887887
- `limit_order` - Calculate making_amount and taking_amount for limit orders
888888
- Params: `usd_amount`, `input_price_usd`, `input_decimals`, `output_price_usd`, `output_decimals`, `price_change_percentage`
889889
- Returns: `making_amount`, `taking_amount` (use these for privy_trigger)
890-
- `price_change_percentage`: Use "-0.5" for 0.5% lower (buy the dip), "10" for 10% higher (sell high)
890+
- `price_change_percentage`: How much MORE output you want than current market. ALWAYS POSITIVE for limit orders:
891+
- "0.5" = get 0.5% more output (buy the dip - wait for output token to drop)
892+
- "5" = get 5% more output (sell high - wait for input token to rise)
893+
- "0" = current market price (fills immediately)
891894

892895
- `limit_order_info` - Calculate trigger price and USD values for displaying order info
893896
- Params: `making_amount`, `taking_amount`, `input_price_usd`, `output_price_usd`, `input_decimals`, `output_decimals`
@@ -920,13 +923,13 @@ User: "limit buy BONK when price drops 0.5% with $10 of SOL"
920923
- input_decimals=9
921924
- output_price_usd="0.00001" (BONK)
922925
- output_decimals=5
923-
- price_change_percentage="-0.5"
926+
- price_change_percentage="0.5" # Want 0.5% MORE BONK than current market
924927
925928
Returns:
926929
- making_amount="71428571" (SOL in lamports)
927-
- taking_amount="100502512562" (BONK in smallest units)
930+
- taking_amount="100500000000" (BONK - 0.5% more than current would give)
928931
929-
3. privy_trigger with those exact amounts
932+
3. privy_trigger with those exact amounts - order waits until you can get 0.5% more BONK
930933
```
931934

932935
## 🧩 Plugin Development

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "sakit"
3-
version = "14.3.1"
3+
version = "14.3.2"
44
description = "Solana Agent Kit"
55
authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
66
license = "MIT"

sakit/token_math.py

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,14 +179,23 @@ def calculate_limit_order_amounts(
179179
"""
180180
Calculate both making_amount and taking_amount for a limit order.
181181
182+
The price_change_percentage indicates how much MORE output you want than current market:
183+
- Positive = you want MORE output tokens (order waits for better price)
184+
Example: 0.5 = get 0.5% more output tokens (buy the dip)
185+
Example: 5 = get 5% more output tokens (sell high)
186+
- Zero = current market price (will fill immediately if liquidity available)
187+
- Negative = accept LESS output (will fill immediately, rare use case)
188+
189+
For "buy the dip 0.5%" → use 0.5 (you want 0.5% more tokens)
190+
For "sell high 5%" → use 5 (you want 5% more of the output token)
191+
182192
Args:
183193
input_usd_amount: USD value of input token to spend
184194
input_price_usd: Current price of input token in USD
185195
input_decimals: Decimals of input token
186196
output_price_usd: Current price of output token in USD
187197
output_decimals: Decimals of output token
188-
price_change_percentage: Target price change for output token
189-
(e.g., "-0.5" for 0.5% lower = buy the dip)
198+
price_change_percentage: How much MORE output you want (positive = wait for better price)
190199
191200
Returns:
192201
Dict with making_amount, taking_amount (both in smallest units)
@@ -195,15 +204,23 @@ def calculate_limit_order_amounts(
195204
input_human = usd_to_token_amount(input_usd_amount, input_price_usd)
196205
making_amount = human_to_smallest_units(input_human, input_decimals)
197206

198-
# Calculate target output price with percentage change
199-
target_output_price = apply_percentage_change(
200-
output_price_usd, price_change_percentage
207+
# Apply percentage change to get the adjusted USD value
208+
# Positive percentage = you want MORE output (input worth more, or output cheaper)
209+
# We ADD the percentage to the input USD value to get more output tokens
210+
pct = Decimal(str(price_change_percentage))
211+
adjusted_usd = Decimal(str(input_usd_amount)) * (
212+
Decimal("1") + pct / Decimal("100")
201213
)
202214

203-
# Calculate output token amount at target price
204-
output_human = usd_to_token_amount(input_usd_amount, target_output_price)
215+
# Calculate output token amount at current price for the adjusted USD value
216+
output_human = usd_to_token_amount(str(adjusted_usd), output_price_usd)
205217
taking_amount = human_to_smallest_units(output_human, output_decimals)
206218

219+
# Calculate what the target output price would be (for display purposes)
220+
# trigger_price = input_usd / output_tokens
221+
# If we're asking for more output, the effective output price we're paying is lower
222+
target_output_price = str(Decimal(str(input_usd_amount)) / Decimal(output_human))
223+
207224
return {
208225
"making_amount": making_amount,
209226
"taking_amount": taking_amount,
@@ -377,7 +394,14 @@ def get_schema(self) -> Dict[str, Any]:
377394
},
378395
"price_change_percentage": {
379396
"type": "string",
380-
"description": "Price change percentage for limit order (for 'limit_order'). E.g., '-0.5' for 0.5% lower (buy dip), '10' for 10% higher (sell high). Pass '0' for current price.",
397+
"description": (
398+
"How much MORE output you want compared to current market (for 'limit_order'). "
399+
"ALWAYS POSITIVE for limit orders that wait for better prices: "
400+
"e.g., '0.5' = get 0.5%% more output (buy the dip), "
401+
"'5' = get 5%% more output (sell high). "
402+
"Pass '0' for current market price (will fill immediately). "
403+
"Negative values mean accepting LESS than market (rare, fills immediately)."
404+
),
381405
},
382406
"making_amount": {
383407
"type": "string",

tests/test_token_math_tool.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -244,40 +244,43 @@ def test_limit_order_at_current_price(self):
244244
assert result["taking_amount"] == "100000000000"
245245

246246
def test_limit_order_buy_the_dip(self):
247-
"""Should calculate limit order for buying at lower price."""
247+
"""Should calculate limit order for buying the dip (get more output by waiting)."""
248248
result = calculate_limit_order_amounts(
249249
input_usd_amount="10",
250250
input_price_usd="140", # SOL
251251
input_decimals=9,
252252
output_price_usd="0.00001", # BONK
253253
output_decimals=5,
254-
price_change_percentage="-0.5", # Buy when 0.5% lower
254+
price_change_percentage="0.5", # Want 0.5% MORE output (buy the dip)
255255
)
256256
# making_amount unchanged
257257
assert result["making_amount"] == "71428571"
258-
# taking_amount: at 0.995 price, get MORE tokens
259-
# $10 / $0.00000995 * 10^5 = 100,502,512,562 (rounded down)
258+
# taking_amount: with +0.5%, we're asking for MORE output (1.005x)
259+
# $10 * 1.005 / $0.00001 * 10^5 = 100,500,000,000
260260
taking = int(result["taking_amount"])
261261
assert taking > 100000000000 # More than at current price
262262
assert taking < 101000000000 # But not too much more
263263

264264
def test_limit_order_sell_high(self):
265-
"""Should calculate limit order for selling at higher price."""
265+
"""Should calculate limit order for selling at higher price (get more output)."""
266266
result = calculate_limit_order_amounts(
267267
input_usd_amount="10",
268268
input_price_usd="0.00001", # BONK
269269
input_decimals=5,
270270
output_price_usd="140", # SOL
271271
output_decimals=9,
272-
price_change_percentage="10", # Sell when SOL is 10% higher
272+
price_change_percentage="5", # Want 5% MORE output (sell high)
273273
)
274-
# At 10% higher SOL price ($154), get LESS SOL for same USD
274+
# making: $10 / $0.00001 * 10^5 = 100,000,000,000
275275
making = int(result["making_amount"])
276-
# $10 / $0.00001 * 10^5 = 100,000,000,000
277276
assert making == 100000000000
278-
# taking: $10 / $154 * 10^9 = 64,935,064 (less SOL)
277+
# taking: $10 * 1.05 / $140 * 10^9 = 75,000,000 (5% more SOL than current)
279278
taking = int(result["taking_amount"])
280-
assert taking < 71428571 # Less than at current price
279+
# Current would be $10 / $140 * 10^9 = 71,428,571
280+
assert (
281+
taking > 71428571
282+
) # More than at current price (we're asking for premium)
283+
assert taking < 80000000 # Reasonable upper bound
281284

282285

283286
class TestCalculateLimitOrderInfo:
@@ -1084,7 +1087,7 @@ async def test_scenario_swap_2_dollars_of_sol(self, math_tool):
10841087
async def test_scenario_limit_buy_bonk_with_10_dollars_sol(self, math_tool):
10851088
"""
10861089
Scenario: "limit buy BONK when price drops 0.5% with $10 of SOL"
1087-
From the agent config example.
1090+
User wants 0.5% MORE BONK than current market (buy the dip).
10881091
"""
10891092
# From Birdeye: SOL price=$140, decimals=9, BONK price=$0.00001, decimals=5
10901093
result = await math_tool.execute(
@@ -1098,7 +1101,7 @@ async def test_scenario_limit_buy_bonk_with_10_dollars_sol(self, math_tool):
10981101
input_decimals=9,
10991102
output_price_usd="0.00001", # BONK
11001103
output_decimals=5,
1101-
price_change_percentage="-0.5", # 0.5% lower
1104+
price_change_percentage="0.5", # Want 0.5% MORE output (buy the dip)
11021105
)
11031106
assert result["status"] == "success"
11041107

@@ -1108,12 +1111,13 @@ async def test_scenario_limit_buy_bonk_with_10_dollars_sol(self, math_tool):
11081111
assert making == 71428571
11091112

11101113
# Verify taking_amount (BONK to receive)
1111-
# Target price = $0.00001 * 0.995 = $0.00000995
1112-
# $10 / $0.00000995 = 1,005,025.125... BONK
1113-
# In smallest units: 1,005,025.125 * 100,000 = 100,502,512,562
1114+
# With +0.5%, we want 0.5% more BONK
1115+
# Current: $10 / $0.00001 = 1,000,000 BONK
1116+
# With +0.5%: 1,000,000 * 1.005 = 1,005,000 BONK
1117+
# In smallest units: 1,005,000 * 100,000 = 100,500,000,000
11141118
taking = int(result["taking_amount"])
11151119
# Should be around 100.5 billion (12 digits)
1116-
assert len(str(taking)) == 12 # Verify digit count matches agent example
1120+
assert len(str(taking)) == 12 # Verify digit count
11171121
assert taking > 100000000000 # More than at current price
11181122

11191123
@pytest.mark.asyncio

0 commit comments

Comments
 (0)