Class: Hyperliquid::Exchange

Inherits:
Object
  • Object
show all
Defined in:
lib/hyperliquid/exchange.rb

Constant Summary collapse

DEFAULT_SLIPPAGE =
0.05

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(private_key:, base_url: MAINNET_URL, vault_address: nil, account_address: nil, skip_ws: false) ⇒ Exchange

Returns a new instance of Exchange.

Parameters:

  • private_key (String)

    hex private key

  • base_url (String) (defaults to: MAINNET_URL)

    API URL (defaults to mainnet)

  • vault_address (String, nil) (defaults to: nil)

    default vault address for all operations

  • account_address (String, nil) (defaults to: nil)

    address to use for queries (e.g. when trading as agent)



17
18
19
20
21
22
23
24
# File 'lib/hyperliquid/exchange.rb', line 17

def initialize(private_key:, base_url: MAINNET_URL, vault_address: nil, account_address: nil, skip_ws: false)
  @signer = Signer.new(private_key: private_key, base_url: base_url)
  @info = Info.new(base_url: base_url, skip_ws: skip_ws)
  @transport = Transport.new(base_url: base_url)
  @vault_address = vault_address
  @account_address = 
  @expires_after = nil
end

Instance Attribute Details

#expires_afterObject

Returns the value of attribute expires_after.



11
12
13
# File 'lib/hyperliquid/exchange.rb', line 11

def expires_after
  @expires_after
end

#infoObject (readonly)

Returns the value of attribute info.



10
11
12
# File 'lib/hyperliquid/exchange.rb', line 10

def info
  @info
end

#signerObject (readonly)

Returns the value of attribute signer.



10
11
12
# File 'lib/hyperliquid/exchange.rb', line 10

def signer
  @signer
end

Instance Method Details

#addressObject



26
27
28
# File 'lib/hyperliquid/exchange.rb', line 26

def address
  @signer.address
end

#agent_enable_dex_abstractionObject

Enable dex abstraction for an agent.



720
721
722
723
# File 'lib/hyperliquid/exchange.rb', line 720

def agent_enable_dex_abstraction
  action = { "type" => "agentEnableDexAbstraction" }
  post_action(action)
end

#agent_set_abstraction(abstraction) ⇒ Object

Set abstraction level for an agent.

Parameters:

  • abstraction (String)

    “u”, “p”, or “i”



727
728
729
730
# File 'lib/hyperliquid/exchange.rb', line 727

def agent_set_abstraction(abstraction)
  action = { "type" => "agentSetAbstraction", "abstraction" => abstraction }
  post_action(action)
end

#approve_agent(name: nil) ⇒ Array

Approve an agent to trade on your behalf. Generates a new agent key and returns [response, agent_private_key].

Parameters:

  • name (String, nil) (defaults to: nil)

    agent name

Returns:

  • (Array)
    response, agent_private_key_hex


355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
# File 'lib/hyperliquid/exchange.rb', line 355

def approve_agent(name: nil)
  agent_key = "0x#{SecureRandom.hex(32)}"
   = Eth::Key.new(priv: agent_key.delete_prefix("0x"))
  ts = timestamp_ms

  action = {
    "type" => "approveAgent",
    "agentAddress" => .address.to_s,
    "agentName" => name || "",
    "nonce" => ts
  }
  sig = @signer.sign_user_signed_action(
    action,
    primary_type: "ApproveAgent",
    payload_types: USER_SIGNED_TYPES["ApproveAgent"]
  )

  # Remove agentName from action if no name provided (matches Python SDK behavior)
  action.delete("agentName") if name.nil?

  payload = { action: action, nonce: ts, signature: sig }
  result = @transport.post_exchange(payload)

  [result, agent_key]
end

#approve_builder_fee(builder:, max_fee_rate:) ⇒ Object

Approve a builder fee.

Parameters:

  • builder (String)

    builder address

  • max_fee_rate (String)

    max fee rate



384
385
386
387
388
389
390
391
392
# File 'lib/hyperliquid/exchange.rb', line 384

def approve_builder_fee(builder:, max_fee_rate:)
  action = {
    "type" => "approveBuilderFee",
    "maxFeeRate" => max_fee_rate,
    "builder" => builder,
    "nonce" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "ApproveBuilderFee")
end

#bulk_cancel(cancels) ⇒ Object

Cancel multiple orders by order ID.

Parameters:

  • cancels (Array<Hash>)

    each with :coin and :oid keys



165
166
167
168
169
170
171
172
173
# File 'lib/hyperliquid/exchange.rb', line 165

def bulk_cancel(cancels)
  cancel_wires = cancels.map do |c|
    asset = @info.name_to_asset(c[:coin])
    { "a" => asset, "o" => c[:oid] }
  end

  action = { "type" => "cancel", "cancels" => cancel_wires }
  post_action(action)
end

#bulk_cancel_by_cloid(cancels) ⇒ Object

Cancel multiple orders by client order ID.

Parameters:

  • cancels (Array<Hash>)

    each with :coin and :cloid keys



177
178
179
180
181
182
183
184
185
# File 'lib/hyperliquid/exchange.rb', line 177

def bulk_cancel_by_cloid(cancels)
  cancel_wires = cancels.map do |c|
    asset = @info.name_to_asset(c[:coin])
    { "asset" => asset, "cloid" => c[:cloid].to_s }
  end

  action = { "type" => "cancelByCloid", "cancels" => cancel_wires }
  post_action(action)
end

#bulk_modify_orders(modifications) ⇒ Object

Modify multiple orders at once.

Parameters:

  • modifications (Array<Hash>)

    each with :oid and :order keys



133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/hyperliquid/exchange.rb', line 133

def bulk_modify_orders(modifications)
  wires = modifications.map do |mod|
    asset = @info.name_to_asset(mod[:order][:coin])
    oid_val = mod[:oid].is_a?(Cloid) ? mod[:oid].to_raw : mod[:oid]
    {
      "oid" => oid_val,
      "order" => Utils.order_request_to_order_wire(mod[:order], asset)
    }
  end

  action = { "type" => "batchModify", "modifies" => wires }
  post_action(action)
end

#bulk_orders(order_requests, grouping: "na", builder: nil, vault_address: nil) ⇒ Object

Place multiple orders at once.

Parameters:

  • order_requests (Array<Hash>)

    array of order request hashes

  • grouping (String) (defaults to: "na")

    “na”, “normalTpsl”, or “positionTpsl”

  • builder (Hash, nil) (defaults to: nil)
  • vault_address (String, nil) (defaults to: nil)


63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/hyperliquid/exchange.rb', line 63

def bulk_orders(order_requests, grouping: "na", builder: nil, vault_address: nil)
  wires = order_requests.map do |req|
    asset = @info.name_to_asset(req[:coin])
    Utils.order_request_to_order_wire(req, asset)
  end

  action = { "type" => "order", "orders" => wires, "grouping" => grouping }
  action["builder"] = { "b" => builder["b"].downcase, "f" => builder["f"] } if builder

  vault = vault_address || @vault_address
  post_action(action, vault_address: vault)
end

#c_signer_jail_selfObject

Jail self as c-signer.



657
658
659
# File 'lib/hyperliquid/exchange.rb', line 657

def c_signer_jail_self
  c_signer_action("jailSelf")
end

#c_signer_unjail_selfObject

Unjail self as c-signer.



652
653
654
# File 'lib/hyperliquid/exchange.rb', line 652

def c_signer_unjail_self
  c_signer_action("unjailSelf")
end

#c_validator_change_profile(unjailed:, node_ip: nil, name: nil, description: nil, disable_delegations: nil, commission_bps: nil, signer: nil) ⇒ Object

Change validator profile.



685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'lib/hyperliquid/exchange.rb', line 685

def c_validator_change_profile(unjailed:, node_ip: nil, name: nil, description: nil,
                               disable_delegations: nil, commission_bps: nil, signer: nil)
  action = {
    "type" => "CValidatorAction",
    "changeProfile" => {
      "node_ip" => node_ip ? { "Ip" => node_ip } : nil,
      "name" => name,
      "description" => description,
      "unjailed" => unjailed,
      "disable_delegations" => disable_delegations,
      "commission_bps" => commission_bps,
      "signer" => signer
    }
  }
  post_action(action, vault_address: nil)
end

#c_validator_register(node_ip:, name:, description:, delegations_disabled:, commission_bps:, signer:, unjailed:, initial_wei:) ⇒ Object

Register as a validator.



664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
# File 'lib/hyperliquid/exchange.rb', line 664

def c_validator_register(node_ip:, name:, description:, delegations_disabled:, commission_bps:,
                         signer:, unjailed:, initial_wei:)
  action = {
    "type" => "CValidatorAction",
    "register" => {
      "profile" => {
        "node_ip" => { "Ip" => node_ip },
        "name" => name,
        "description" => description,
        "delegations_disabled" => delegations_disabled,
        "commission_bps" => commission_bps,
        "signer" => signer
      },
      "unjailed" => unjailed,
      "initial_wei" => initial_wei
    }
  }
  post_action(action, vault_address: nil)
end

#c_validator_unregisterObject

Unregister as a validator.



703
704
705
706
# File 'lib/hyperliquid/exchange.rb', line 703

def c_validator_unregister
  action = { "type" => "CValidatorAction", "unregister" => nil }
  post_action(action, vault_address: nil)
end

#cancel(coin, oid) ⇒ Object

Cancel a single order by order ID.

Parameters:

  • coin (String)
  • oid (Integer)


152
153
154
# File 'lib/hyperliquid/exchange.rb', line 152

def cancel(coin, oid)
  bulk_cancel([{ coin: coin, oid: oid }])
end

#cancel_by_cloid(coin, cloid) ⇒ Object

Cancel a single order by client order ID.

Parameters:

  • coin (String)
  • cloid (Cloid)


159
160
161
# File 'lib/hyperliquid/exchange.rb', line 159

def cancel_by_cloid(coin, cloid)
  bulk_cancel_by_cloid([{ coin: coin, cloid: cloid }])
end

#convert_to_multi_sig_user(authorized_users:, threshold:) ⇒ Object

Convert account to multi-sig.

Parameters:

  • authorized_users (Array<String>)

    list of authorized signer addresses

  • threshold (Integer)

    number of signatures required



471
472
473
474
475
476
477
478
479
480
# File 'lib/hyperliquid/exchange.rb', line 471

def convert_to_multi_sig_user(authorized_users:, threshold:)
  sorted_users = authorized_users.sort
  signers = { "authorizedUsers" => sorted_users, "threshold" => threshold }
  action = {
    "type" => "convertToMultiSigUser",
    "signers" => JSON.generate(signers),
    "nonce" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "ConvertToMultiSigUser")
end

#create_sub_account(name:) ⇒ Object

Create a sub-account.

Parameters:

  • name (String)

    sub-account name



398
399
400
401
# File 'lib/hyperliquid/exchange.rb', line 398

def (name:)
  action = { "type" => "createSubAccount", "name" => name }
  post_action(action, vault_address: nil)
end

#market_close(coin, sz: nil, px: nil, slippage: DEFAULT_SLIPPAGE, cloid: nil, builder: nil) ⇒ Object

Market close: close entire position (or partial) at market.

Parameters:

  • coin (String)
  • sz (Float, nil) (defaults to: nil)

    size to close (default: entire position)

  • px (Float, nil) (defaults to: nil)

    reference price (default: mid price)

  • slippage (Float) (defaults to: DEFAULT_SLIPPAGE)
  • cloid (Cloid, nil) (defaults to: nil)
  • builder (Hash, nil) (defaults to: nil)

Raises:



97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/hyperliquid/exchange.rb', line 97

def market_close(coin, sz: nil, px: nil, slippage: DEFAULT_SLIPPAGE, cloid: nil, builder: nil)
  addr = @account_address || @vault_address || address
  state = @info.user_state(addr)
  position = state["assetPositions"]&.find { |p| p["position"]["coin"] == coin }
  raise Error, "No open position for #{coin}" unless position

  szi = position["position"]["szi"].to_f
  is_buy = szi < 0 # close short = buy, close long = sell
  sz ||= szi.abs

  px = slippage_price(coin, is_buy, slippage, px)
  order(coin, is_buy: is_buy, sz: sz, limit_px: px,
              order_type: { limit: { "tif" => "Ioc" } }, reduce_only: true, cloid: cloid, builder: builder)
end

#market_open(coin, is_buy:, sz:, px: nil, slippage: DEFAULT_SLIPPAGE, cloid: nil, builder: nil) ⇒ Object

Market open: buy/sell at market with slippage tolerance.

Parameters:

  • coin (String)
  • is_buy (Boolean)
  • sz (Float)

    size

  • px (Float, nil) (defaults to: nil)

    reference price (default: mid price)

  • slippage (Float) (defaults to: DEFAULT_SLIPPAGE)

    slippage as decimal (default 0.05 = 5%)

  • cloid (Cloid, nil) (defaults to: nil)
  • builder (Hash, nil) (defaults to: nil)


84
85
86
87
88
# File 'lib/hyperliquid/exchange.rb', line 84

def market_open(coin, is_buy:, sz:, px: nil, slippage: DEFAULT_SLIPPAGE, cloid: nil, builder: nil)
  px = slippage_price(coin, is_buy, slippage, px)
  order(coin, is_buy: is_buy, sz: sz, limit_px: px,
              order_type: { limit: { "tif" => "Ioc" } }, cloid: cloid, builder: builder)
end

#modify_order(oid, coin:, is_buy:, sz:, limit_px:, order_type:, reduce_only: false, cloid: nil) ⇒ Object

Modify a single order.

Parameters:

  • oid (Integer, Cloid)

    order ID or client order ID to modify

  • coin (String)
  • is_buy (Boolean)
  • sz (Float)
  • limit_px (Float)
  • order_type (Hash)
  • reduce_only (Boolean) (defaults to: false)
  • cloid (Cloid, nil) (defaults to: nil)


123
124
125
126
127
128
129
# File 'lib/hyperliquid/exchange.rb', line 123

def modify_order(oid, coin:, is_buy:, sz:, limit_px:, order_type:, reduce_only: false, cloid: nil)
  order_request = {
    coin: coin, is_buy: is_buy, sz: sz, limit_px: limit_px,
    order_type: order_type, reduce_only: reduce_only, cloid: cloid
  }
  bulk_modify_orders([{ oid: oid, order: order_request }])
end

#multi_sig(multi_sig_user, inner_action, signatures, nonce, vault_address: nil) ⇒ Object

Execute a multi-sig action.

Parameters:

  • multi_sig_user (String)

    multi-sig user address

  • inner_action (Hash)

    the action to execute

  • signatures (Array)

    existing signatures

  • nonce (Integer)

    nonce

  • vault_address (String, nil) (defaults to: nil)


488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
# File 'lib/hyperliquid/exchange.rb', line 488

def multi_sig(multi_sig_user, inner_action, signatures, nonce, vault_address: nil)
  multi_sig_action = {
    "type" => "multiSig",
    "signatureChainId" => "0x66eee",
    "signatures" => signatures,
    "payload" => {
      "multiSigUser" => multi_sig_user.downcase,
      "outerSigner" => @signer.address.downcase,
      "action" => inner_action
    }
  }

  sig = @signer.sign_multi_sig_action(multi_sig_action, vault_address: vault_address, nonce: nonce,
                                                        expires_after: @expires_after)

  payload = {
    action: multi_sig_action,
    nonce: nonce,
    signature: sig,
    vaultAddress: vault_address,
    expiresAfter: @expires_after
  }
  @transport.post_exchange(payload)
end

#noop(nonce) ⇒ Object

Send a no-op action (useful for testing signing).

Parameters:

  • nonce (Integer)


762
763
764
765
# File 'lib/hyperliquid/exchange.rb', line 762

def noop(nonce)
  action = { "type" => "noop" }
  post_action(action, nonce: nonce)
end

#order(coin, is_buy:, sz:, limit_px:, order_type:, reduce_only: false, cloid: nil, builder: nil, vault_address: nil) ⇒ Object

Place a single order.

Parameters:

  • coin (String)

    e.g. “ETH”

  • is_buy (Boolean)
  • sz (Float)

    order size

  • limit_px (Float)

    limit price

  • order_type (Hash)

    e.g. { limit: { “tif” => “Gtc” } } or { trigger: { … } }

  • reduce_only (Boolean) (defaults to: false)
  • cloid (Cloid, nil) (defaults to: nil)

    client order ID

  • builder (Hash, nil) (defaults to: nil)

    e.g. { “b” => “0x…”, “f” => 10 }

  • vault_address (String, nil) (defaults to: nil)

    override default vault



49
50
51
52
53
54
55
56
# File 'lib/hyperliquid/exchange.rb', line 49

def order(coin, is_buy:, sz:, limit_px:, order_type:, reduce_only: false, cloid: nil, builder: nil,
          vault_address: nil)
  order_request = {
    coin: coin, is_buy: is_buy, sz: sz, limit_px: limit_px,
    order_type: order_type, reduce_only: reduce_only, cloid: cloid
  }
  bulk_orders([order_request], builder: builder, vault_address: vault_address)
end

#perp_deploy_register_asset(dex:, coin:, sz_decimals:, oracle_px:, margin_table_id:, only_isolated:, max_gas: nil, schema: nil) ⇒ Object

Register a new perp asset.



607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
# File 'lib/hyperliquid/exchange.rb', line 607

def perp_deploy_register_asset(dex:, coin:, sz_decimals:, oracle_px:, margin_table_id:,
                               only_isolated:, max_gas: nil, schema: nil)
  schema_wire = nil
  if schema
    schema_wire = {
      "fullName" => schema[:full_name],
      "collateralToken" => schema[:collateral_token],
      "oracleUpdater" => schema[:oracle_updater]&.downcase
    }
  end
  action = {
    "type" => "perpDeploy",
    "registerAsset" => {
      "maxGas" => max_gas,
      "assetRequest" => {
        "coin" => coin,
        "szDecimals" => sz_decimals,
        "oraclePx" => oracle_px,
        "marginTableId" => margin_table_id,
        "onlyIsolated" => only_isolated
      },
      "dex" => dex,
      "schema" => schema_wire
    }
  }
  post_action(action, vault_address: nil)
end

#perp_deploy_set_oracle(dex:, oracle_pxs:, all_mark_pxs:, external_perp_pxs:) ⇒ Object

Set oracle prices for a perp dex.



636
637
638
639
640
641
642
643
644
645
646
647
# File 'lib/hyperliquid/exchange.rb', line 636

def perp_deploy_set_oracle(dex:, oracle_pxs:, all_mark_pxs:, external_perp_pxs:)
  action = {
    "type" => "perpDeploy",
    "setOracle" => {
      "dex" => dex,
      "oraclePxs" => oracle_pxs.sort.to_a,
      "markPxs" => all_mark_pxs.map { |m| m.sort.to_a },
      "externalPerpPxs" => external_perp_pxs.sort.to_a
    }
  }
  post_action(action, vault_address: nil)
end

#schedule_cancel(time: nil) ⇒ Object

Schedule cancel-all after a delay.

Parameters:

  • time (Integer, nil) (defaults to: nil)

    timestamp in ms when to cancel. nil to clear.



189
190
191
192
193
# File 'lib/hyperliquid/exchange.rb', line 189

def schedule_cancel(time: nil)
  action = { "type" => "scheduleCancel" }
  action["time"] = time if time
  post_action(action)
end

#send_asset(destination, source_dex:, destination_dex:, token:, amount:) ⇒ Object

Send asset between dexes.

Parameters:

  • destination (String)

    recipient address

  • source_dex (String)

    source dex identifier

  • destination_dex (String)

    destination dex identifier

  • token (String)

    token identifier

  • amount (Float)

    amount to send



334
335
336
337
338
339
340
341
342
343
344
345
346
347
# File 'lib/hyperliquid/exchange.rb', line 334

def send_asset(destination, source_dex:, destination_dex:, token:, amount:)
  ts = timestamp_ms
  action = {
    "type" => "sendAsset",
    "destination" => destination,
    "sourceDex" => source_dex,
    "destinationDex" => destination_dex,
    "token" => token,
    "amount" => amount.to_s,
    "fromSubAccount" => @vault_address || "",
    "nonce" => ts
  }
  post_user_signed_action(action, primary_type: "SendAsset")
end

#set_expires_after(expires_after) ⇒ Object

Set expiration for subsequent actions (millisecond timestamp). Not supported on user-signed actions.

Parameters:

  • expires_after (Integer, nil)

    timestamp in ms, or nil to clear



33
34
35
# File 'lib/hyperliquid/exchange.rb', line 33

def set_expires_after(expires_after)
  @expires_after = expires_after
end

#set_referrer(code) ⇒ Object

Set referrer code.

Parameters:

  • code (String)

    referral code



263
264
265
266
# File 'lib/hyperliquid/exchange.rb', line 263

def set_referrer(code)
  action = { "type" => "setReferrer", "code" => code }
  post_action(action, vault_address: nil)
end

#spot_deploy_enable_freeze_privilege(token) ⇒ Object

Enable freeze privilege for a spot token.



542
543
544
# File 'lib/hyperliquid/exchange.rb', line 542

def spot_deploy_enable_freeze_privilege(token)
  spot_deploy_token_action("enableFreezePrivilege", token)
end

#spot_deploy_enable_quote_token(token) ⇒ Object

Enable quote token for a spot token.



561
562
563
# File 'lib/hyperliquid/exchange.rb', line 561

def spot_deploy_enable_quote_token(token)
  spot_deploy_token_action("enableQuoteToken", token)
end

#spot_deploy_freeze_user(token, user:, freeze:) ⇒ Object

Freeze/unfreeze a user for a spot token.



547
548
549
550
551
552
553
# File 'lib/hyperliquid/exchange.rb', line 547

def spot_deploy_freeze_user(token, user:, freeze:)
  action = {
    "type" => "spotDeploy",
    "freezeUser" => { "token" => token, "user" => user.downcase, "freeze" => freeze }
  }
  post_action(action, vault_address: nil)
end

#spot_deploy_genesis(token, max_supply:, no_hyperliquidity: false) ⇒ Object

Run genesis for a spot token.



566
567
568
569
570
571
# File 'lib/hyperliquid/exchange.rb', line 566

def spot_deploy_genesis(token, max_supply:, no_hyperliquidity: false)
  genesis = { "token" => token, "maxSupply" => max_supply }
  genesis["noHyperliquidity"] = true if no_hyperliquidity
  action = { "type" => "spotDeploy", "genesis" => genesis }
  post_action(action, vault_address: nil)
end

#spot_deploy_register_hyperliquidity(spot, start_px:, order_sz:, n_orders:, n_seeded_levels: nil) ⇒ Object

Register hyperliquidity for a spot pair.



583
584
585
586
587
588
589
590
591
592
593
# File 'lib/hyperliquid/exchange.rb', line 583

def spot_deploy_register_hyperliquidity(spot, start_px:, order_sz:, n_orders:, n_seeded_levels: nil)
  register = {
    "spot" => spot,
    "startPx" => start_px.to_s,
    "orderSz" => order_sz.to_s,
    "nOrders" => n_orders
  }
  register["nSeededLevels"] = n_seeded_levels if n_seeded_levels
  action = { "type" => "spotDeploy", "registerHyperliquidity" => register }
  post_action(action, vault_address: nil)
end

#spot_deploy_register_spot(base_token:, quote_token:) ⇒ Object

Register a spot trading pair.



574
575
576
577
578
579
580
# File 'lib/hyperliquid/exchange.rb', line 574

def spot_deploy_register_spot(base_token:, quote_token:)
  action = {
    "type" => "spotDeploy",
    "registerSpot" => { "tokens" => [base_token, quote_token] }
  }
  post_action(action, vault_address: nil)
end

#spot_deploy_register_token(token_name:, sz_decimals:, wei_decimals:, max_gas:, full_name:) ⇒ Object

Register a new spot token.



516
517
518
519
520
521
522
523
524
525
526
# File 'lib/hyperliquid/exchange.rb', line 516

def spot_deploy_register_token(token_name:, sz_decimals:, wei_decimals:, max_gas:, full_name:)
  action = {
    "type" => "spotDeploy",
    "registerToken2" => {
      "spec" => { "name" => token_name, "szDecimals" => sz_decimals, "weiDecimals" => wei_decimals },
      "maxGas" => max_gas,
      "fullName" => full_name
    }
  }
  post_action(action, vault_address: nil)
end

#spot_deploy_revoke_freeze_privilege(token) ⇒ Object

Revoke freeze privilege for a spot token.



556
557
558
# File 'lib/hyperliquid/exchange.rb', line 556

def spot_deploy_revoke_freeze_privilege(token)
  spot_deploy_token_action("revokeFreezePrivilege", token)
end

#spot_deploy_set_deployer_trading_fee_share(token, share:) ⇒ Object

Set deployer trading fee share for a spot token.



596
597
598
599
600
601
602
# File 'lib/hyperliquid/exchange.rb', line 596

def spot_deploy_set_deployer_trading_fee_share(token, share:)
  action = {
    "type" => "spotDeploy",
    "setDeployerTradingFeeShare" => { "token" => token, "share" => share }
  }
  post_action(action, vault_address: nil)
end

#spot_deploy_user_genesis(token:, user_and_wei:, existing_token_and_wei:) ⇒ Object

User genesis for a spot token.



529
530
531
532
533
534
535
536
537
538
539
# File 'lib/hyperliquid/exchange.rb', line 529

def spot_deploy_user_genesis(token:, user_and_wei:, existing_token_and_wei:)
  action = {
    "type" => "spotDeploy",
    "userGenesis" => {
      "token" => token,
      "userAndWei" => user_and_wei.map { |user, wei| [user.downcase, wei] },
      "existingTokenAndWei" => existing_token_and_wei
    }
  }
  post_action(action, vault_address: nil)
end

#spot_transfer(destination, token:, amount:) ⇒ Object

Transfer spot tokens to another address.

Parameters:

  • destination (String)

    recipient address

  • token (String)

    token identifier

  • amount (Float)


287
288
289
290
291
292
293
294
295
296
# File 'lib/hyperliquid/exchange.rb', line 287

def spot_transfer(destination, token:, amount:)
  action = {
    "type" => "spotSend",
    "destination" => destination,
    "token" => token,
    "amount" => amount.to_s,
    "time" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "SpotSend")
end

#sub_account_spot_transfer(sub_account_user:, is_deposit:, token:, amount:) ⇒ Object

Transfer spot tokens to/from a sub-account.

Parameters:

  • sub_account_user (String)
  • is_deposit (Boolean)
  • token (String)
  • amount (Float)


422
423
424
425
426
427
428
429
430
431
# File 'lib/hyperliquid/exchange.rb', line 422

def (sub_account_user:, is_deposit:, token:, amount:)
  action = {
    "type" => "subAccountSpotTransfer",
    "subAccountUser" => ,
    "isDeposit" => is_deposit,
    "token" => token,
    "amount" => amount.to_s
  }
  post_action(action, vault_address: nil)
end

#sub_account_transfer(sub_account_user:, is_deposit:, usd:) ⇒ Object

Transfer USD to/from a sub-account.

Parameters:

  • sub_account_user (String)

    sub-account address

  • is_deposit (Boolean)

    true = deposit into sub, false = withdraw

  • usd (Integer)

    USD amount (raw integer)



407
408
409
410
411
412
413
414
415
# File 'lib/hyperliquid/exchange.rb', line 407

def (sub_account_user:, is_deposit:, usd:)
  action = {
    "type" => "subAccountTransfer",
    "subAccountUser" => ,
    "isDeposit" => is_deposit,
    "usd" => usd
  }
  post_action(action, vault_address: nil)
end

#token_delegate(validator:, wei:, is_undelegate: false) ⇒ Object

Delegate or undelegate tokens.

Parameters:

  • validator (String)

    validator address

  • wei (Integer)

    amount in wei

  • is_undelegate (Boolean) (defaults to: false)


455
456
457
458
459
460
461
462
463
464
# File 'lib/hyperliquid/exchange.rb', line 455

def token_delegate(validator:, wei:, is_undelegate: false)
  action = {
    "type" => "tokenDelegate",
    "validator" => validator,
    "wei" => wei,
    "isUndelegate" => is_undelegate,
    "nonce" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "TokenDelegate")
end

#twap_cancel(coin, twap_id:) ⇒ Object

Cancel a TWAP order.

Parameters:

  • coin (String)
  • twap_id (Integer)


223
224
225
226
227
# File 'lib/hyperliquid/exchange.rb', line 223

def twap_cancel(coin, twap_id:)
  asset = @info.name_to_asset(coin)
  action = { "type" => "twapCancel", "a" => asset, "t" => twap_id }
  post_action(action)
end

#twap_order(coin, is_buy:, sz:, minutes:, reduce_only: false, randomize: true) ⇒ Object

Place a TWAP order.

Parameters:

  • coin (String)
  • is_buy (Boolean)
  • sz (Float)
  • reduce_only (Boolean) (defaults to: false)
  • minutes (Integer)

    duration

  • randomize (Boolean) (defaults to: true)

    randomize execution



204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
# File 'lib/hyperliquid/exchange.rb', line 204

def twap_order(coin, is_buy:, sz:, minutes:, reduce_only: false, randomize: true)
  asset = @info.name_to_asset(coin)
  action = {
    "type" => "twapOrder",
    "twap" => {
      "a" => asset,
      "b" => is_buy,
      "s" => Utils.float_to_wire(sz),
      "r" => reduce_only,
      "m" => minutes,
      "t" => randomize
    }
  }
  post_action(action)
end

#update_isolated_margin(coin, is_buy:, amount:) ⇒ Object

Update isolated margin for a coin.

Parameters:

  • coin (String)
  • is_buy (Boolean)
  • amount (Float)

    USD amount (positive = add, negative = remove)



250
251
252
253
254
255
256
257
258
259
# File 'lib/hyperliquid/exchange.rb', line 250

def update_isolated_margin(coin, is_buy:, amount:)
  asset = @info.name_to_asset(coin)
  action = {
    "type" => "updateIsolatedMargin",
    "asset" => asset,
    "isBuy" => is_buy,
    "ntli" => Utils.float_to_usd_int(amount)
  }
  post_action(action)
end

#update_leverage(coin, leverage:, is_cross: true) ⇒ Object

Update leverage for a coin.

Parameters:

  • coin (String)
  • leverage (Integer)
  • is_cross (Boolean) (defaults to: true)


235
236
237
238
239
240
241
242
243
244
# File 'lib/hyperliquid/exchange.rb', line 235

def update_leverage(coin, leverage:, is_cross: true)
  asset = @info.name_to_asset(coin)
  action = {
    "type" => "updateLeverage",
    "asset" => asset,
    "isCross" => is_cross,
    "leverage" => leverage
  }
  post_action(action)
end

#usd_class_transfer(amount:, to_perp:) ⇒ Object

Transfer between perp and spot.

Parameters:

  • amount (Float)

    USD amount

  • to_perp (Boolean)

    true = spot->perp, false = perp->spot



314
315
316
317
318
319
320
321
322
323
324
325
326
# File 'lib/hyperliquid/exchange.rb', line 314

def usd_class_transfer(amount:, to_perp:)
  ts = timestamp_ms
  str_amount = amount.to_s
  str_amount += " subaccount:#{@vault_address}" if @vault_address

  action = {
    "type" => "usdClassTransfer",
    "amount" => str_amount,
    "toPerp" => to_perp,
    "nonce" => ts
  }
  post_user_signed_action(action, primary_type: "UsdClassTransfer")
end

#usd_transfer(destination, amount:) ⇒ Object

Transfer USD to another address.

Parameters:

  • destination (String)

    recipient address

  • amount (Float)

    USD amount



273
274
275
276
277
278
279
280
281
# File 'lib/hyperliquid/exchange.rb', line 273

def usd_transfer(destination, amount:)
  action = {
    "type" => "usdSend",
    "destination" => destination,
    "amount" => amount.to_s,
    "time" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "UsdSend")
end

#use_big_blocks(enable) ⇒ Object

Enable or disable big blocks.

Parameters:

  • enable (Boolean)


712
713
714
715
# File 'lib/hyperliquid/exchange.rb', line 712

def use_big_blocks(enable)
  action = { "type" => "evmUserModify", "usingBigBlocks" => enable }
  post_action(action, vault_address: nil)
end

#user_dex_abstraction(user, enabled:) ⇒ Object

Set dex abstraction for a user (user-signed action).

Parameters:

  • user (String)

    user address

  • enabled (Boolean)


735
736
737
738
739
740
741
742
743
# File 'lib/hyperliquid/exchange.rb', line 735

def user_dex_abstraction(user, enabled:)
  action = {
    "type" => "userDexAbstraction",
    "user" => user.downcase,
    "enabled" => enabled,
    "nonce" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "UserDexAbstraction")
end

#user_set_abstraction(user, abstraction:) ⇒ Object

Set user abstraction level (user-signed action).

Parameters:

  • user (String)

    user address

  • abstraction (String)

    “unifiedAccount”, “portfolioMargin”, or “disabled”



748
749
750
751
752
753
754
755
756
# File 'lib/hyperliquid/exchange.rb', line 748

def user_set_abstraction(user, abstraction:)
  action = {
    "type" => "userSetAbstraction",
    "user" => user.downcase,
    "abstraction" => abstraction,
    "nonce" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "UserSetAbstraction")
end

#vault_usd_transfer(vault_address:, is_deposit:, usd:) ⇒ Object

Transfer USD to/from a vault.

Parameters:

  • vault_address (String)

    vault address

  • is_deposit (Boolean)
  • usd (Integer)

    amount



439
440
441
442
443
444
445
446
447
# File 'lib/hyperliquid/exchange.rb', line 439

def vault_usd_transfer(vault_address:, is_deposit:, usd:)
  action = {
    "type" => "vaultTransfer",
    "vaultAddress" => vault_address,
    "isDeposit" => is_deposit,
    "usd" => usd
  }
  post_action(action, vault_address: nil)
end

#withdraw_from_bridge(destination, amount:) ⇒ Object

Withdraw USDC from bridge to L1.

Parameters:

  • destination (String)

    recipient address

  • amount (Float)

    USDC amount



301
302
303
304
305
306
307
308
309
# File 'lib/hyperliquid/exchange.rb', line 301

def withdraw_from_bridge(destination, amount:)
  action = {
    "type" => "withdraw3",
    "destination" => destination,
    "amount" => amount.to_s,
    "time" => timestamp_ms
  }
  post_user_signed_action(action, primary_type: "Withdraw")
end