|
| 1 | +--- |
| 2 | +title: Spot Buy |
| 3 | +--- |
| 4 | + |
| 5 | +The `spotBuy` action enables Vincent Apps to execute buy orders on Hyperliquid's spot market using a Vincent User's HyperCore spot balance. |
| 6 | + |
| 7 | +## Prerequisites |
| 8 | + |
| 9 | +Before executing the `spotBuy` action, the following conditions must be met: |
| 10 | + |
| 11 | +- **Spot Balance on HyperCore**: The Vincent User Agent Wallet must have sufficient balance for the quote asset in their HyperCore spot balance to cover the purchase amount. The quote asset is the second asset in the trading pair (e.g., USDC in "PURR/USDC"). |
| 12 | +- **Order Parameters**: You must provide a valid trading pair symbol (e.g., "PURR/USDC"), price, and size according to Hyperliquid's trading rules. |
| 13 | + |
| 14 | +<Info> |
| 15 | + To learn more about executing Vincent Abilities, see the [Executing |
| 16 | + Abilities](/ability/explaining-abilities) guide. |
| 17 | +</Info> |
| 18 | + |
| 19 | +## Executing the `precheck` Function |
| 20 | + |
| 21 | +The `precheck` function validates some prerequisites for executing a spot buy, without actually performing the operation. |
| 22 | + |
| 23 | +For the `spotBuy` action, the `precheck` function will validate the following: |
| 24 | + |
| 25 | +- The trading pair symbol is a valid Hyperliquid trading pair (e.g., "PURR/USDC"). |
| 26 | +- The Vincent User Agent Wallet has sufficient balance for the quote asset in their HyperCore spot balance to cover the purchase amount. The quote asset is the second asset in the trading pair (e.g., USDC in "PURR/USDC"). |
| 27 | + |
| 28 | +<Tabs> |
| 29 | + <Tab title="Parameters"> |
| 30 | + The `precheck` function requires the following parameters: |
| 31 | + |
| 32 | + ```typescript |
| 33 | + import { HyperliquidAction } from '@lit-protocol/vincent-ability-hyperliquid'; |
| 34 | + |
| 35 | + { |
| 36 | + /** |
| 37 | + * The action to perform (must be HyperliquidAction.SPOT_BUY) |
| 38 | + */ |
| 39 | + action: HyperliquidAction.SPOT_BUY; |
| 40 | + /** |
| 41 | + * Whether to use Hyperliquid testnet (optional, defaults to false) |
| 42 | + */ |
| 43 | + useTestnet?: boolean; |
| 44 | + /** |
| 45 | + * Spot buy parameters |
| 46 | + */ |
| 47 | + spot: { |
| 48 | + /** |
| 49 | + * The trading pair symbol (e.g., "PURR/USDC", "ETH/USDC") |
| 50 | + */ |
| 51 | + symbol: string; |
| 52 | + /** |
| 53 | + * The limit price for the buy order. |
| 54 | + * Must follow Hyperliquid's spot price rules: |
| 55 | + * - Max 5 significant figures |
| 56 | + * - Max (8 - szDecimals) decimal places |
| 57 | + * https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#spot-price-examples |
| 58 | + */ |
| 59 | + price: string; |
| 60 | + /** |
| 61 | + * The size (amount of tokens) to buy. |
| 62 | + * Must be rounded to the token's szDecimals. |
| 63 | + * https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#spot-price-examples |
| 64 | + */ |
| 65 | + size: string; |
| 66 | + }; |
| 67 | + } |
| 68 | + ``` |
| 69 | + |
| 70 | + </Tab> |
| 71 | + |
| 72 | + <Tab title="Implementation"> |
| 73 | + To execute `precheck`, you'll need to: |
| 74 | + |
| 75 | + - Create an instance of the `VincentAbilityClient` using the `getVincentAbilityClient` function (imported from `@lit-protocol/vincent-app-sdk/abilityClient`) |
| 76 | + - Pass in the Ability's `bundledVincentAbility` object (imported from `@lit-protocol/vincent-ability-hyperliquid`) |
| 77 | + - Pass in the `ethersSigner` you'll be using to sign the request to Lit with your Delegatee private key |
| 78 | + - Use the `VincentAbilityClient` instance to call the `precheck` function |
| 79 | + |
| 80 | + ```typescript |
| 81 | + import { getVincentAbilityClient } from '@lit-protocol/vincent-app-sdk/abilityClient'; |
| 82 | + import { bundledVincentAbility, HyperliquidAction } from '@lit-protocol/vincent-ability-hyperliquid'; |
| 83 | + import { ethers } from 'ethers'; |
| 84 | + |
| 85 | + // Your delegatee signer (one of the delegatee signers for the Vincent App) |
| 86 | + const delegateeSigner = new ethers.Wallet('YOUR_DELEGATEE_PRIVATE_KEY', provider); |
| 87 | + |
| 88 | + // Create ability client |
| 89 | + const hyperliquidAbilityClient = getVincentAbilityClient({ |
| 90 | + bundledVincentAbility, |
| 91 | + ethersSigner: delegateeSigner, |
| 92 | + }); |
| 93 | + |
| 94 | + // Run precheck |
| 95 | + const precheckResult = await hyperliquidAbilityClient.precheck( |
| 96 | + { |
| 97 | + action: HyperliquidAction.SPOT_BUY, |
| 98 | + useTestnet: false, // Set to true for testnet |
| 99 | + spot: { |
| 100 | + symbol: 'PURR/USDC', |
| 101 | + price: '5.1', |
| 102 | + size: '4', |
| 103 | + }, |
| 104 | + }, |
| 105 | + { |
| 106 | + delegatorPkpEthAddress: '0x...', // The Vincent User's Vincent Wallet address |
| 107 | + }, |
| 108 | + ); |
| 109 | + |
| 110 | + if (precheckResult.success) { |
| 111 | + console.log('Spot buy precheck passed, ready to execute'); |
| 112 | + } else { |
| 113 | + // Handle different types of failures |
| 114 | + if (precheckResult.runtimeError) { |
| 115 | + console.error('Runtime error:', precheckResult.runtimeError); |
| 116 | + } |
| 117 | + if (precheckResult.schemaValidationError) { |
| 118 | + console.error('Schema validation error:', precheckResult.schemaValidationError); |
| 119 | + } |
| 120 | + if (precheckResult.result) { |
| 121 | + console.error('Spot buy precheck failed:', precheckResult.result.reason); |
| 122 | + } |
| 123 | + } |
| 124 | + ``` |
| 125 | + |
| 126 | + </Tab> |
| 127 | + |
| 128 | + <Tab title="Response"> |
| 129 | + ### Success |
| 130 | + |
| 131 | + A successful `precheck` response will contain: |
| 132 | + |
| 133 | + ```typescript |
| 134 | + { |
| 135 | + /** |
| 136 | + * The action that was prechecked |
| 137 | + */ |
| 138 | + action: 'spotBuy'; |
| 139 | + } |
| 140 | + ``` |
| 141 | + |
| 142 | + ### Failure |
| 143 | + |
| 144 | + A failure `precheck` response will contain: |
| 145 | + |
| 146 | + ```typescript |
| 147 | + { |
| 148 | + /** |
| 149 | + * The action that was prechecked |
| 150 | + */ |
| 151 | + action: 'spotBuy'; |
| 152 | + /** |
| 153 | + * The reason the precheck failed, such as insufficient spot balance |
| 154 | + */ |
| 155 | + reason: string; |
| 156 | + } |
| 157 | + ``` |
| 158 | + |
| 159 | + </Tab> |
| 160 | +</Tabs> |
| 161 | + |
| 162 | +## Executing the `execute` Function |
| 163 | + |
| 164 | +The `execute` function performs the actual buy operation, placing a buy order on Hyperliquid's spot market. |
| 165 | + |
| 166 | +For the `spotBuy` action, the `execute` function will: |
| 167 | + |
| 168 | +- Place a buy order for the specified token pair at the given price and size. |
| 169 | +- Return the order result from Hyperliquid. |
| 170 | + |
| 171 | +<Tabs> |
| 172 | + <Tab title="Parameters"> |
| 173 | + The `execute` function requires the following parameters: |
| 174 | + |
| 175 | + ```typescript |
| 176 | + import { HyperliquidAction, OrderType } from '@lit-protocol/vincent-ability-hyperliquid'; |
| 177 | + |
| 178 | + { |
| 179 | + /** |
| 180 | + * The action to perform (must be HyperliquidAction.SPOT_BUY) |
| 181 | + */ |
| 182 | + action: HyperliquidAction.SPOT_BUY; |
| 183 | + /** |
| 184 | + * Whether to use Hyperliquid testnet (optional, defaults to false) |
| 185 | + */ |
| 186 | + useTestnet?: boolean; |
| 187 | + /** |
| 188 | + * Spot buy parameters |
| 189 | + */ |
| 190 | + spot: { |
| 191 | + /** |
| 192 | + * The trading pair symbol (e.g., "PURR/USDC", "ETH/USDC") |
| 193 | + */ |
| 194 | + symbol: string; |
| 195 | + /** |
| 196 | + * The limit price for the buy order. |
| 197 | + * Must follow Hyperliquid's spot price rules: |
| 198 | + * - Max 5 significant figures |
| 199 | + * - Max (8 - szDecimals) decimal places |
| 200 | + * https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#spot-price-examples |
| 201 | + */ |
| 202 | + price: string; |
| 203 | + /** |
| 204 | + * The size (amount of tokens) to buy. |
| 205 | + * Must be rounded to the token's szDecimals. |
| 206 | + * https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#spot-price-examples |
| 207 | + */ |
| 208 | + size: string; |
| 209 | + /** |
| 210 | + * The order type for the buy order (optional). |
| 211 | + * You may specify either a limit or market order using the form: |
| 212 | + * { type: "limit", tif: "Gtc" | "Ioc" | "Alo" } |
| 213 | + * or |
| 214 | + * { type: "market" } |
| 215 | + * Defaults to: { type: "limit", tif: "Gtc" } |
| 216 | + */ |
| 217 | + orderType?: |
| 218 | + | { type: OrderType.LIMIT; tif: 'Gtc' | 'Ioc' | 'Alo' } |
| 219 | + | { type: OrderType.MARKET }; |
| 220 | + }; |
| 221 | + } |
| 222 | + ``` |
| 223 | + |
| 224 | + </Tab> |
| 225 | + |
| 226 | + <Tab title="Implementation"> |
| 227 | + The `execute` function can be executed using the same `VincentAbilityClient` instance as used for the `precheck` function: |
| 228 | + |
| 229 | + ```typescript |
| 230 | + import { OrderType } from '@lit-protocol/vincent-ability-hyperliquid'; |
| 231 | + |
| 232 | + const executeResult = await hyperliquidAbilityClient.execute( |
| 233 | + { |
| 234 | + action: HyperliquidAction.SPOT_BUY, |
| 235 | + useTestnet: false, // Set to true for testnet |
| 236 | + spot: { |
| 237 | + symbol: 'PURR/USDC', |
| 238 | + price: '5.1', |
| 239 | + size: '4', |
| 240 | + orderType: { type: OrderType.MARKET }, // Optional: defaults to limit order with Gtc tif |
| 241 | + }, |
| 242 | + }, |
| 243 | + { |
| 244 | + delegatorPkpEthAddress: '0x...', // The Vincent User's Vincent Wallet address |
| 245 | + }, |
| 246 | + ); |
| 247 | + |
| 248 | + if (executeResult.success) { |
| 249 | + const { orderResult } = executeResult.result; |
| 250 | + console.log('Spot buy executed successfully:', orderResult); |
| 251 | + } else { |
| 252 | + // Handle different types of failures |
| 253 | + if (executeResult.runtimeError) { |
| 254 | + console.error('Runtime error:', executeResult.runtimeError); |
| 255 | + } |
| 256 | + if (executeResult.schemaValidationError) { |
| 257 | + console.error('Schema validation error:', executeResult.schemaValidationError); |
| 258 | + } |
| 259 | + if (executeResult.result) { |
| 260 | + console.error('Spot buy execution failed:', executeResult.result.reason); |
| 261 | + } |
| 262 | + } |
| 263 | + ``` |
| 264 | + |
| 265 | + </Tab> |
| 266 | + |
| 267 | + <Tab title="Response"> |
| 268 | + **Success Response** |
| 269 | + |
| 270 | + A successful `execute` response will contain: |
| 271 | + |
| 272 | + ```typescript |
| 273 | + { |
| 274 | + /** |
| 275 | + * The action that was executed |
| 276 | + */ |
| 277 | + action: 'spotBuy'; |
| 278 | + /** |
| 279 | + * The order response from Hyperliquid request as defined by the Hyperliquid SDK: @nktkas/hyperliquid |
| 280 | + * https://github.com/nktkas/hyperliquid/blob/2233ce942eb50ef8850073b387b9918d3a54a10b/src/api/exchange/order.ts#L103-L194 |
| 281 | + */ |
| 282 | + orderResult: OrderResponse; |
| 283 | + } |
| 284 | + ``` |
| 285 | + |
| 286 | + **Failure Response** |
| 287 | + |
| 288 | + A failure `execute` response will contain: |
| 289 | + |
| 290 | + ```typescript |
| 291 | + { |
| 292 | + /** |
| 293 | + * The action that was executed |
| 294 | + */ |
| 295 | + action: 'spotBuy'; |
| 296 | + /** |
| 297 | + * The reason the execution failed, such as insufficient spot balance |
| 298 | + */ |
| 299 | + reason: string; |
| 300 | + } |
| 301 | + ``` |
| 302 | + |
| 303 | + </Tab> |
| 304 | +</Tabs> |
| 305 | + |
| 306 | +## Important Considerations |
| 307 | + |
| 308 | +<AccordionGroup> |
| 309 | + <Accordion title="Price and Size Formatting Rules" icon="ruler"> |
| 310 | + Hyperliquid has strict formatting requirements for spot orders. See the [Hyperliquid API documentation](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/tick-and-lot-size#spot-price-examples) for more details. |
| 311 | + |
| 312 | + </Accordion> |
| 313 | + |
| 314 | +<Accordion title="Getting Current Market Prices" icon="chart-line"> |
| 315 | + You'll need to fetch the current market price before placing an order. Use the Hyperliquid API or |
| 316 | + SDK to get the mid price for your trading pair, then adjust it based on your strategy (e.g., 1% |
| 317 | + above mid price for market buys). |
| 318 | +</Accordion> |
| 319 | + |
| 320 | +<Accordion title="Order Types" icon="list"> |
| 321 | + You can specify either a limit or market order using the `orderType` parameter. See the |
| 322 | + [Parameters](#parameters) section for more details. |
| 323 | +</Accordion> |
| 324 | + |
| 325 | + <Accordion title="Verifying Order Success" icon="check"> |
| 326 | + After the order is executed, you can verify the balances changed by checking the spot balances using a [Hyperliquid SDK](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api), or by using the [Hyperliquid API](https://hyperliquid.gitbook.io/hyperliquid-docs/for-developers/api/info-endpoint/spot#retrieve-a-users-token-balances). |
| 327 | + </Accordion> |
| 328 | +</AccordionGroup> |
| 329 | + |
| 330 | +## Reference Implementation |
| 331 | + |
| 332 | +For a complete working example showing the full spot buy workflow including balance verification and price calculation, see the [buy.spec.ts](https://github.com/LIT-Protocol/Vincent/blob/main/packages/apps/ability-hyperliquid/test/e2e/spot/buy.spec.ts) end-to-end test in the `ability-hyperliquid` package. |
| 333 | + |
| 334 | +## Next Steps |
| 335 | + |
| 336 | +Explore the rest of the supported Hyperliquid actions: |
| 337 | + |
| 338 | +<CardGroup cols={3}> |
| 339 | + |
| 340 | +<Card title="Deposit" href="/ability/official-abilities/hyperliquid/deposit" icon="arrow-down" /> |
| 341 | + |
| 342 | +<Card title="Withdraw" href="/ability/official-abilities/hyperliquid/withdraw" icon="arrow-up" /> |
| 343 | + |
| 344 | +<Card |
| 345 | + title="Send Spot Asset" |
| 346 | + href="/ability/official-abilities/hyperliquid/send-spot-asset" |
| 347 | + icon="coins" |
| 348 | +/> |
| 349 | + |
| 350 | +<Card |
| 351 | + title="Send Perp USDC" |
| 352 | + href="/ability/official-abilities/hyperliquid/send-perp-usdc" |
| 353 | + icon="dollar-sign" |
| 354 | +/> |
| 355 | + |
| 356 | +<Card |
| 357 | + title="Transfer to Spot" |
| 358 | + href="/ability/official-abilities/hyperliquid/transfer-to-spot" |
| 359 | + icon="arrow-right" |
| 360 | +/> |
| 361 | + |
| 362 | +<Card |
| 363 | + title="Transfer to Perp" |
| 364 | + href="/ability/official-abilities/hyperliquid/transfer-to-perp" |
| 365 | + icon="arrow-left" |
| 366 | +/> |
| 367 | + |
| 368 | +<Card title="Spot Sell" href="/ability/official-abilities/hyperliquid/spot-sell" icon="tag" /> |
| 369 | + |
| 370 | +<Card |
| 371 | + title="Perp Long" |
| 372 | + href="/ability/official-abilities/hyperliquid/perp-long" |
| 373 | + icon="arrow-up-right" |
| 374 | +/> |
| 375 | + |
| 376 | +<Card |
| 377 | + title="Perp Short" |
| 378 | + href="/ability/official-abilities/hyperliquid/perp-short" |
| 379 | + icon="arrow-down-right" |
| 380 | +/> |
| 381 | + |
| 382 | +<Card title="Cancel Order" href="/ability/official-abilities/hyperliquid/cancel-order" icon="ban" /> |
| 383 | + |
| 384 | +<Card |
| 385 | + title="Cancel All Orders" |
| 386 | + href="/ability/official-abilities/hyperliquid/cancel-all-orders-for-symbol" |
| 387 | + icon="trash" |
| 388 | +/> |
| 389 | + |
| 390 | +</CardGroup> |
0 commit comments