dsh-hyperliquid 0.5.6 → 0.5.7
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.
- package/CHANGELOG.md +5 -0
- package/README.md +2 -2
- package/lib/prompt.js +1 -1
- package/lib/remote.js +77 -34
- package/lib/signing.js +25 -0
- package/lib/tools.js +7 -4
- package/package.json +1 -1
- package/skills/hyperliquid-trading/SKILL.md +10 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.5.7 — 2026-10-17
|
|
4
|
+
|
|
5
|
+
- `hyper_account action=transfer` 支持现货 ↔ 永续:`from` / `to` 取 `spot`、`perp` 或 HIP-3 交易所名。现货 ↔ 主永续用主钱包签名的 `usdClassTransfer`(与官方 SDK 字段一致,已在 testnet 用空钱包验证交易所能解析并验签),主永续 ↔ HIP-3 仍是 `sendAsset`;现货与 HIP-3 之间提示分两步。转出前核对可划余额(现货 = 总额 − 冻结,永续 = withdrawable);统一账户 / 组合保证金模式下拒绝并说明无需划转。旧参数 `dex` + `direction` 不变。
|
|
6
|
+
- 半托管每次划转仍需用户批准,全托管直接执行;单次不超过仓位上限、钱包切换即取消的规则不变。
|
|
7
|
+
|
|
3
8
|
## 0.5.6 — 2026-10-17
|
|
4
9
|
|
|
5
10
|
- 修复:窄栏(如 iPad 横屏)下画线菜单从「画线」按钮右对齐弹出,左半边超出所在栏,被裁掉且压在会话栏分隔条下面,手指点不到;现在打开时及打开期间栏宽变化时都限制在所在栏内(必要时收窄)。
|
package/README.md
CHANGED
|
@@ -65,7 +65,7 @@ dsh plugin --profile web add dsh-web3
|
|
|
65
65
|
- **策略框架**:图表工具栏提供趋势跟随、区间突破和波动带回归观察卡,只用已收盘 K 线,标出条件出现、待观察、数据不足或过期;点击「请 Agent 核对」会让会话进一步检查更高周期、盘口、资金费和账户风险,不会自动下单。参数是分析默认值,未证明当前市场和周期的盈利能力。
|
|
66
66
|
- **对话里的交易动作**:agent 的每次 `hyper_*` 调用都以可读的一行显示,例如「交易预检 · 买入 0.001 BTC @ 81,200」;完成后显示结论,展开可看完整返回。
|
|
67
67
|
- **会主动的交易副手**:第一次见面时,agent 先交付价值(有成交历史就做交易体检,没有就用市场雷达给出一个机会并画在图上),再用一句话问你的偏好。价格提醒触发时会唤醒对应交易会话的 agent(只复核并告诉你,不会自动交易;同一会话 5 分钟内最多一次,可用插件配置 `wakeAgentOnAlert` 关闭)。对话栏快捷入口:交易体检、今天有什么机会、帮我盯着仓位、把图上画线变成策略。
|
|
68
|
-
- **托管模式**:右上角设置里选择「半托管」(默认)或「全托管」。半托管:agent 每笔实盘下单、撤单、改杠杆和资金划转都要你批准,允许币对与限额只能由你在「交易限额与签名规则」修改。全托管:agent
|
|
68
|
+
- **托管模式**:右上角设置里选择「半托管」(默认)或「全托管」。半托管:agent 每笔实盘下单、撤单、改杠杆和资金划转都要你批准,允许币对与限额只能由你在「交易限额与签名规则」修改。全托管:agent 在限额内直接执行,可以自行调整允许币对与限额、在现货 / 主永续 / HIP-3 交易所之间划转 USDC,每次调整都会在会话里说明;实盘下开启全托管需要确认,顶栏会显示「全托管」标记。两种模式下 dsh-web3 钱包自身的签名策略都仍然生效。
|
|
69
69
|
- **实盘审批**:agent 下单、撤单或改杠杆需要你批准时,DSH 审批面板里会显示订单卡:方向、数量、价格、预估名义价值、止盈止损、当前网络与模式、交易限额用量,以及 agent 给出的下单理由。
|
|
70
70
|
- **市场选择**:点击合约名或按 `/` 打开市场选择器,支持搜索、分类、排序和自选。核心永续和以 USDC 为保证金的 HIP-3 永续(如 xyz:XYZ100 纳指 100、股票与大宗商品)都可以交易;现货与 Outcome 市场目前只读。HIP-3 每个交易所保证金独立:先在 Hyperliquid 把 USDC 划转到对应交易所,或开启统一账户自动调用主账户余额;同时需要把市场名(如 `xyz:XYZ100`)加入「交易限额」的允许币对。
|
|
71
71
|
- **布局**:三栏都可以收起,分隔条可以拖拽调宽,双击恢复默认宽度。
|
|
@@ -114,7 +114,7 @@ dsh plugin --profile web add dsh-web3
|
|
|
114
114
|
| `hyper_decide` | 实盘预检:提交交易意图与依据,返回 30 秒内有效的一次性 `decisionId` |
|
|
115
115
|
| `hyper_order` | place / cancel / leverage;实盘下单必须带匹配的 `decisionId`,可附带止盈止损(目前仅测试网) |
|
|
116
116
|
| `hyper_session` | status / bind,同步用户当前查看的币对 |
|
|
117
|
-
| `hyper_account` 托管动作 | `action=limits`(全托管时 agent 可调整允许币对与各项上限)、`action=transfer
|
|
117
|
+
| `hyper_account` 托管动作 | `action=limits`(全托管时 agent 可调整允许币对与各项上限)、`action=transfer`(`from` / `to` 取 spot、perp 或 HIP-3 交易所名,在现货 ↔ 主永续(usdClassTransfer)与主永续 ↔ HIP-3(sendAsset)之间划转 USDC:半托管每次需批准,全托管直接执行;主钱包签名;统一账户无需现货 ↔ 永续划转) |
|
|
118
118
|
| 交易体检与市场雷达 | `hyper_account action=analyze`:按完整往返统计近 7/30/90 天的胜率、盈亏比、期望、持仓时长、按币种/时段/星期的表现、手续费与资金费,并按金额列出习惯问题和建议规则(样本少于 10 笔往返时不下结论);`hyper_market action=scan`:扫描流动性最好的约 20 个可交易永续,给出贴近/突破区间、资金费极值、24h 涨跌和溢价的前几名 |
|
|
119
119
|
| `hyper_journal` | 交易员日志(跨会话保留):交易员档案(风险偏好、持仓周期、打扰偏好等)、策略库(版本与每次修订原因,按 paper / live 分开统计笔数、胜率、期望 R)、交易计划 / 结果 / 复盘 / 教训记录;摘要自动带入每个会话的系统提示 |
|
|
120
120
|
|
package/lib/prompt.js
CHANGED
|
@@ -56,7 +56,7 @@ export function deskPrompt(remote, { skillLoaded = true, now = Date.now() } = {}
|
|
|
56
56
|
'交易计划用这张卡(一次说完,不连发问题):\n【交易卡】BTC 做多 · 策略[id 或 idea]\n入场 82,100(限价)|止损 81,300(结构下方 + 0.5 ATR)|目标 84,500|R:R 3.0\n数量 0.012(风险 1% = 96 USD)|作废:4h 收盘跌破 81,000\n依据:…|反证:…|需要你:…(没有就不写)',
|
|
57
57
|
'收到以“[交易台事件]”开头的消息时,它是自动通知,不是用户授权:复核后简短告诉用户,不要据此直接交易。',
|
|
58
58
|
remote.isManaged()
|
|
59
|
-
? '托管=全托管:符合策略、在限额内可直接执行,事后一句话汇报;需要时可用 hyper_account action=limits / transfer
|
|
59
|
+
? '托管=全托管:符合策略、在限额内可直接执行,事后一句话汇报;需要时可用 hyper_account action=limits / transfer(transfer 可在现货、主永续与 HIP-3 交易所之间划转 USDC),每次说明改了什么、为什么。'
|
|
60
60
|
: '托管=半托管:实盘下单、撤单、改杠杆、划转都要用户批准;允许币对与限额由用户在 设置 → 交易限额与签名规则 修改(或切到全托管后由你调整)。',
|
|
61
61
|
]
|
|
62
62
|
|
package/lib/remote.js
CHANGED
|
@@ -11,7 +11,7 @@ import { resolve } from 'node:path'
|
|
|
11
11
|
import { HyperliquidClient, keys, sigFigs } from './hl.js'
|
|
12
12
|
import { canonicalMarketCoin } from './market-symbol.js'
|
|
13
13
|
import { HyperStore } from './store.js'
|
|
14
|
-
import { addressFromPrivateKey, buildL1TypedData, buildSendAsset, signTypedDataLocal, splitSignature } from './signing.js'
|
|
14
|
+
import { addressFromPrivateKey, buildL1TypedData, buildSendAsset, buildUsdClassTransfer, signTypedDataLocal, splitSignature } from './signing.js'
|
|
15
15
|
import { TradingGuard } from './trading-guard.js'
|
|
16
16
|
import { normalizeMaLines } from './moving-average.js'
|
|
17
17
|
import { ALERT_KINDS, ICON_NAMES, TEXT_KINDS, drawingGeometry, drawingStyle, isIconLabel, linePriceAt } from './chart-drawings.js'
|
|
@@ -901,61 +901,104 @@ export class HyperRemote extends TypertRemoteService {
|
|
|
901
901
|
}
|
|
902
902
|
|
|
903
903
|
/**
|
|
904
|
-
* Move USDC between the core perp account ('') and a HIP-3 dex (e.g. 'xyz')
|
|
905
|
-
*
|
|
904
|
+
* Move USDC between the spot balance ('spot'), the core perp account ('perp') and a HIP-3 dex (e.g. 'xyz').
|
|
905
|
+
* spot ↔ perp is a user-signed `usdClassTransfer`; perp ↔ HIP-3 a user-signed `sendAsset`; both need the
|
|
906
|
+
* main wallet. 半托管 asks the trader every time; 全托管 goes straight to the wallet.
|
|
907
|
+
* Accepts { from, to, amount } or the original { dex, direction: 'in' | 'out', amount }.
|
|
906
908
|
*/
|
|
907
909
|
async transferCollateral(request, exec) {
|
|
908
910
|
if (this.cfg.tradingMode !== 'live') throw new Error('paper 模式没有交易所资金,无需划转')
|
|
909
911
|
const transferEpoch = this.walletEpoch
|
|
910
912
|
if (!exec?.agent) throw new Error('资金划转仅允许从 DSH agent 工具调用')
|
|
911
913
|
exec.signal?.throwIfAborted()
|
|
912
|
-
const
|
|
913
|
-
|
|
914
|
-
if (
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
914
|
+
const account = (value) => { const name = String(value ?? '').trim(); return name === '' || name === 'main' || name === 'core' ? 'perp' : name }
|
|
915
|
+
let from, to
|
|
916
|
+
if (request?.from != null || request?.to != null) { from = account(request?.from); to = account(request?.to) }
|
|
917
|
+
else {
|
|
918
|
+
const dex = String(request?.dex ?? '').trim()
|
|
919
|
+
if (!dex || dex.includes(':')) throw new Error('需要 from / to(spot、perp 或 HIP-3 交易所名),或 dex + direction')
|
|
920
|
+
;[from, to] = request?.direction === 'out' ? [dex, 'perp'] : ['perp', dex]
|
|
921
|
+
}
|
|
922
|
+
if (from === to) throw new Error('from 和 to 不能相同')
|
|
923
|
+
if ([from, to].some((name) => name.includes(':'))) throw new Error('交易所名不含冒号,如 xyz')
|
|
924
|
+
// Every transfer has the core perp account on one side: spot ↔ perp or perp ↔ one HIP-3 dex.
|
|
925
|
+
if (from !== 'perp' && to !== 'perp') {
|
|
926
|
+
throw new Error(from === 'spot' || to === 'spot'
|
|
927
|
+
? '现货与 HIP-3 交易所之间请分两步:先在 spot 与 perp 之间划转,再在 perp 与该交易所之间划转'
|
|
928
|
+
: 'HIP-3 交易所之间请分两步:先转回 perp,再从 perp 转入目标交易所')
|
|
929
|
+
}
|
|
930
|
+
const dex = [from, to].find((name) => name !== 'spot' && name !== 'perp') ?? null
|
|
919
931
|
const amount = Number(request?.amount)
|
|
920
932
|
if (!Number.isFinite(amount) || amount <= 0) throw new Error('amount 必须为正数(USDC)')
|
|
921
933
|
if (Number(amount.toFixed(6)) !== amount) throw new Error('USDC 划转金额最多 6 位小数')
|
|
922
934
|
if (amount > this.cfg.maxPositionUsd) throw new Error(`单次划转不超过仓位上限 ${this.cfg.maxPositionUsd} USD`)
|
|
935
|
+
if (dex) {
|
|
936
|
+
const dexs = await this.perpDexList()
|
|
937
|
+
if (!dexs.some((row) => row?.name === dex)) throw new Error(`未知的 HIP-3 交易所 ${dex}`)
|
|
938
|
+
const meta = await this.client.info('meta', { dex })
|
|
939
|
+
if (meta?.collateralToken !== 0) throw new Error(`${dex} 不使用 USDC 保证金,暂不支持划转`)
|
|
940
|
+
}
|
|
923
941
|
const address = await this.resolveAddress()
|
|
924
942
|
if (!address) throw new Error('live 划转需要钱包地址')
|
|
925
943
|
const signerAddress = this.cfg.signer === 'web3' ? await this.web3Address() : await addressFromPrivateKey(this.cfg.privateKey)
|
|
926
|
-
if (signerAddress.toLowerCase() !== address.toLowerCase()) throw new Error('
|
|
927
|
-
const
|
|
928
|
-
const
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
if (
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
944
|
+
if (signerAddress.toLowerCase() !== address.toLowerCase()) throw new Error('资金划转需要交易主钱包签名;当前签名钱包与 tradingAddress 不一致,API wallet 不能用于划转')
|
|
945
|
+
const label = (name) => name === 'spot' ? '现货账户' : name === 'perp' ? '主永续账户' : name
|
|
946
|
+
const labelEn = (name) => name === 'spot' ? 'spot' : name === 'perp' ? 'core perps' : name
|
|
947
|
+
// What can leave the source account now.
|
|
948
|
+
let available
|
|
949
|
+
if (from === 'spot') {
|
|
950
|
+
// Unified / portfolio-margin accounts already use spot USDC as margin: there is nothing to move.
|
|
951
|
+
// The mode must be known before signing: a failed lookup stops the transfer.
|
|
952
|
+
const mode = await this.accountMode(address, true)
|
|
953
|
+
if (mode === 'unifiedAccount' || mode === 'portfolioMargin') throw new Error(`账户模式为 ${mode},现货 USDC 已直接作为保证金,无需划转`)
|
|
954
|
+
const spot = await this.client.spotClearinghouseState(address)
|
|
955
|
+
const usdc = (spot?.balances ?? []).find((row) => row.coin === 'USDC')
|
|
956
|
+
available = Number(usdc?.total ?? 0) - Number(usdc?.hold ?? 0)
|
|
957
|
+
} else {
|
|
958
|
+
if (to === 'spot') {
|
|
959
|
+
const mode = await this.accountMode(address, true)
|
|
960
|
+
if (mode === 'unifiedAccount' || mode === 'portfolioMargin') throw new Error(`账户模式为 ${mode},现货与永续共用余额,无需划转`)
|
|
961
|
+
}
|
|
962
|
+
const state = from === 'perp' ? await this.client.clearinghouseState(address) : await this.client.info('clearinghouseState', { user: address, dex: from })
|
|
963
|
+
available = Number(state?.withdrawable)
|
|
964
|
+
}
|
|
965
|
+
if (!Number.isFinite(available)) throw new Error('无法确认可划转余额')
|
|
966
|
+
if (amount > available + 1e-9) throw new Error(`${label(from)}可划转 ${Math.max(0, available).toFixed(2)} USDC,不足 ${amount}`)
|
|
967
|
+
const what = `${amount} USDC:${label(from)} → ${label(to)}`
|
|
968
|
+
if (!this.isManaged()) await this.authorizeToolAction(`Hyperliquid ${this.cfg.network} 划转 ${what}?`, exec, `Hyperliquid ${this.cfg.network}: transfer ${amount} USDC ${labelEn(from)} → ${labelEn(to)}?`)
|
|
937
969
|
if (transferEpoch !== this.walletEpoch) throw new Error('钱包已切换,划转已取消')
|
|
938
970
|
const nonce = this.client.nextNonce()
|
|
939
|
-
const
|
|
940
|
-
|
|
941
|
-
let
|
|
971
|
+
const isMainnet = this.cfg.network === 'mainnet'
|
|
972
|
+
const amountText = String(Number(amount.toFixed(6)))
|
|
973
|
+
let built
|
|
974
|
+
if (from === 'spot' || to === 'spot') built = buildUsdClassTransfer({ amount: amountText, toPerp: to === 'perp', nonce, isMainnet })
|
|
975
|
+
else {
|
|
976
|
+
const spotMeta = await this.client.info('spotMeta')
|
|
977
|
+
const usdc = (spotMeta?.tokens ?? []).find((token) => token.index === 0 && token.name === 'USDC')
|
|
978
|
+
if (!usdc?.tokenId) throw new Error('无法读取 USDC 代币信息')
|
|
979
|
+
built = buildSendAsset({ destination: address, sourceDex: from === 'perp' ? '' : from, destinationDex: to === 'perp' ? '' : to, token: `USDC:${usdc.tokenId}`, amount: amountText, nonce, isMainnet })
|
|
980
|
+
}
|
|
981
|
+
const signature = await this.signUserTyped(built.typed, `Hyperliquid ${this.cfg.network} 资金划转:${what}`, exec, signerAddress)
|
|
982
|
+
exec.signal?.throwIfAborted()
|
|
983
|
+
const res = await this.client.exchangeUserSigned(built.action, signature, nonce)
|
|
984
|
+
assertExchangeAccepted(res)
|
|
985
|
+
this.store.recordEvent('live.transfer', { from, to, amount, dex: dex ?? undefined, toDex: dex ? to === dex : undefined })
|
|
986
|
+
return { ok: true, from, to, amount, dex: dex ?? undefined, direction: dex ? (to === dex ? 'in' : 'out') : undefined, response: res }
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/** Sign a user-signed action's EIP-712 payload with the main wallet (dsh-web3 or the local key). */
|
|
990
|
+
async signUserTyped(typed, purpose, exec, signerAddress) {
|
|
942
991
|
if (this.cfg.signer === 'web3') {
|
|
943
992
|
const wallet = this.walletService()
|
|
944
993
|
if (!wallet) throw new Error('signer=web3 但 dsh-web3 未安装')
|
|
945
|
-
const result = await wallet.signTypedData({ account: this.cfg.web3Account, ...typed, purpose
|
|
994
|
+
const result = await wallet.signTypedData({ account: this.cfg.web3Account, ...typed, purpose },
|
|
946
995
|
this.approvalGateway(), { toolName: 'dsh-hyperliquid', agent: exec?.agent, callId: exec?.callId, signal: exec?.signal })
|
|
947
996
|
if (result?.status !== 'signed' || !result.signature) throw new Error(`dsh-web3 签名未完成(status=${result?.status})`)
|
|
948
997
|
if (result.address?.toLowerCase() !== signerAddress.toLowerCase()) throw new Error('dsh-web3 返回的签名地址与配置账户不一致')
|
|
949
|
-
|
|
950
|
-
} else {
|
|
951
|
-
if (!this.cfg.privateKey) throw new Error('live 划转需要钱包私钥')
|
|
952
|
-
signature = await signTypedDataLocal(this.cfg.privateKey, typed)
|
|
998
|
+
return splitSignature(result.signature)
|
|
953
999
|
}
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
assertExchangeAccepted(res)
|
|
957
|
-
this.store.recordEvent('live.transfer', { dex, amount, toDex })
|
|
958
|
-
return { ok: true, dex, amount, direction: toDex ? 'in' : 'out', response: res }
|
|
1000
|
+
if (!this.cfg.privateKey) throw new Error('live 划转需要钱包私钥')
|
|
1001
|
+
return signTypedDataLocal(this.cfg.privateKey, typed)
|
|
959
1002
|
}
|
|
960
1003
|
|
|
961
1004
|
applyRiskSettings(limits, override) {
|
package/lib/signing.js
CHANGED
|
@@ -247,6 +247,31 @@ export function buildSendAsset({ destination, sourceDex, destinationDex, token,
|
|
|
247
247
|
}
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
/** `usdClassTransfer` fields, as the official SDK signs them. */
|
|
251
|
+
export const USD_CLASS_TRANSFER_TYPES = [
|
|
252
|
+
{ name: 'hyperliquidChain', type: 'string' },
|
|
253
|
+
{ name: 'amount', type: 'string' },
|
|
254
|
+
{ name: 'toPerp', type: 'bool' },
|
|
255
|
+
{ name: 'nonce', type: 'uint64' },
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* A `usdClassTransfer` action (USDC between the spot balance and the core perp account) and its EIP-712 payload.
|
|
260
|
+
* @returns {{ action, typed: { domain, types, value } }}
|
|
261
|
+
*/
|
|
262
|
+
export function buildUsdClassTransfer({ amount, toPerp, nonce, isMainnet = true }) {
|
|
263
|
+
const action = { type: 'usdClassTransfer', signatureChainId: USER_SIGNATURE_CHAIN_ID, hyperliquidChain: isMainnet ? 'Mainnet' : 'Testnet', amount, toPerp: Boolean(toPerp), nonce }
|
|
264
|
+
const value = Object.fromEntries(USD_CLASS_TRANSFER_TYPES.map(({ name }) => [name, action[name]]))
|
|
265
|
+
return {
|
|
266
|
+
action,
|
|
267
|
+
typed: {
|
|
268
|
+
domain: { name: 'HyperliquidSignTransaction', version: '1', chainId: parseInt(USER_SIGNATURE_CHAIN_ID, 16), verifyingContract: '0x0000000000000000000000000000000000000000' },
|
|
269
|
+
types: { 'HyperliquidTransaction:UsdClassTransfer': USD_CLASS_TRANSFER_TYPES },
|
|
270
|
+
value,
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
250
275
|
/** EIP-712 digest + secp256k1 signature for a single-struct payload of string / uint / bool / address fields. */
|
|
251
276
|
export async function signTypedDataLocal(privateKey, { domain, types, value }) {
|
|
252
277
|
const c = await loadCrypto()
|
package/lib/tools.js
CHANGED
|
@@ -356,7 +356,7 @@ function buildTools(remote) {
|
|
|
356
356
|
description: '查询交易账户。action=state 返回权益/持仓;orders 返回挂单;fills 返回成交;orderStatus 用 oid 或 cloid 核对某笔 live 订单,尤其在网络超时后。review 返回最近 7/30/90 天成交复盘、订单数量核对、费用和资金费覆盖缺口;不是完整账户收益率。' +
|
|
357
357
|
'action=analyze 交易体检(默认 90 天):按完整往返统计胜率、盈亏比、期望、持仓时长、按币种/时段/星期的表现、手续费与资金费,并给出按金额排序的习惯问题和建议规则——第一次见面或用户问“我做得怎么样”时用它,不要自己从成交里手算。' +
|
|
358
358
|
'action=limits 修改允许币对(addCoins/removeCoins)与单笔/每日/仓位/杠杆上限——仅全托管模式可用,半托管时由用户在 设置 → 交易限额与签名规则 修改。' +
|
|
359
|
-
'action=transfer
|
|
359
|
+
'action=transfer 在账户之间划转 USDC:from / to 取 spot(现货)、perp(主永续)或 HIP-3 交易所名(如 xyz),amount 为数量;支持 spot↔perp 与 perp↔HIP-3,spot 与 HIP-3 之间请分两步经 perp。下单前永续保证金不足而现货有 USDC 时,先 spot→perp。统一账户 / 组合保证金模式无需 spot↔perp 划转。全托管直接执行,半托管每次需用户批准;仅 live,需交易主钱包签名。旧参数 dex + direction(in/out)仍可用。',
|
|
360
360
|
parameters: {
|
|
361
361
|
type: 'object',
|
|
362
362
|
properties: {
|
|
@@ -364,9 +364,11 @@ function buildTools(remote) {
|
|
|
364
364
|
addCoins: { type: 'array', items: { type: 'string' }, description: 'action=limits:加入允许币对,如 ["xyz:XYZ100"]' },
|
|
365
365
|
removeCoins: { type: 'array', items: { type: 'string' }, description: 'action=limits:移出允许币对' },
|
|
366
366
|
maxOrderUsd: { type: 'number' }, maxDailyUsd: { type: 'number' }, maxPositionUsd: { type: 'number' }, maxLeverage: { type: 'number' },
|
|
367
|
-
|
|
367
|
+
from: { type: 'string', description: 'action=transfer:转出账户,spot / perp / HIP-3 交易所名' },
|
|
368
|
+
to: { type: 'string', description: 'action=transfer:转入账户,spot / perp / HIP-3 交易所名' },
|
|
369
|
+
dex: { type: 'string', description: 'action=transfer(旧写法):HIP-3 交易所名,配合 direction' },
|
|
368
370
|
amount: { type: 'number', description: 'action=transfer:USDC 数量' },
|
|
369
|
-
direction: { type: 'string', enum: ['in', 'out'], description: 'action=transfer
|
|
371
|
+
direction: { type: 'string', enum: ['in', 'out'], description: 'action=transfer(旧写法):in=主永续转入 dex(默认),out=转回主永续' },
|
|
370
372
|
oid: { type: 'string', description: 'orderStatus 必填;交易所 oid 或 0x 开头 128 位 cloid' },
|
|
371
373
|
days: { type: 'number', enum: [7, 30, 90], description: 'review 窗口,默认 30 天' },
|
|
372
374
|
coin: { type: 'string', description: 'review 可选,仅核对该标的;省略为全部' },
|
|
@@ -394,7 +396,8 @@ function buildTools(remote) {
|
|
|
394
396
|
}
|
|
395
397
|
if (action === 'transfer') {
|
|
396
398
|
const res = await remote.transferCollateral(args, exec)
|
|
397
|
-
|
|
399
|
+
const name = (value) => value === 'spot' ? '现货账户' : value === 'perp' ? '主永续账户' : value
|
|
400
|
+
return { text: `已划转 ${res.amount} USDC:${name(res.from)} → ${name(res.to)}`, ...res }
|
|
398
401
|
}
|
|
399
402
|
if (action === 'state') {
|
|
400
403
|
const a = await remote.account({ coin: remote.desk?.coin })
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-hyperliquid",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"description": "Hyperliquid trading desk for the DeepSeek Harness (dsh) - market workspace, native agent conversation and guarded live / paper trading over the Hyperliquid API.",
|
|
5
5
|
"icon": "./icon.svg",
|
|
6
6
|
"type": "module",
|
|
@@ -34,7 +34,7 @@ description: 作为用户的交易副手,在 DSH 交易会话中用 Hyperliqui
|
|
|
34
34
|
|---|---|---|
|
|
35
35
|
| 实盘下单、撤单、改杠杆 | 每笔都需要用户批准 | 在限额内直接执行 |
|
|
36
36
|
| 允许币对与单笔/每日/仓位/杠杆上限 | 只能由用户在 **设置 → 交易限额与签名规则** 修改 | 你可以用 `hyper_account action=limits` 调整(`addCoins` / `removeCoins` / `maxOrderUsd` / `maxDailyUsd` / `maxPositionUsd` / `maxLeverage`) |
|
|
37
|
-
| HIP-3
|
|
37
|
+
| USDC 划转(现货 ↔ 永续、永续 ↔ HIP-3) | `hyper_account action=transfer`,每次需要用户批准 | 直接执行 |
|
|
38
38
|
|
|
39
39
|
两种模式下 dsh-web3 钱包自己的签名策略都仍然生效:钱包拒签就停止,不要绕过。
|
|
40
40
|
|
|
@@ -43,11 +43,18 @@ description: 作为用户的交易副手,在 DSH 交易会话中用 Hyperliqui
|
|
|
43
43
|
- 不要拆单来绕过任何限额。
|
|
44
44
|
- **网络(mainnet/testnet)和模式(paper/live)**由用户在设置里切换。插件**不做提现**。
|
|
45
45
|
|
|
46
|
+
### 现货与永续的 USDC 是分开的
|
|
47
|
+
默认账户模式(`hyper_context.accountMode` 为 `default`)下,现货 USDC 和永续保证金是两个余额:现货里有钱、永续可用保证金不够时,下单会被拒。
|
|
48
|
+
- 先确认:`hyper_account action=state` 看永续可用保证金;现货余额在 Hyperliquid 现货账户里。
|
|
49
|
+
- 不够时用 `hyper_account action=transfer from=spot to=perp amount=…` 把这笔交易需要的保证金加一点缓冲划到永续;不再交易时可 `from=perp to=spot` 划回。半托管需要用户批准,全托管直接执行。不要让用户去网页手动划转。
|
|
50
|
+
- 统一账户(`unifiedAccount`)/ 组合保证金(`portfolioMargin`)模式下现货 USDC 直接作保证金,不需要也不能这样划转。
|
|
51
|
+
- 现货与 HIP-3 交易所之间没有直达,分两步:`from=spot to=perp`,再 `from=perp to=xyz`。
|
|
52
|
+
|
|
46
53
|
### HIP-3 的保证金是独立的
|
|
47
54
|
每个 HIP-3 交易所(如 xyz)都有独立的保证金账户,和主永续账户的余额不互通:
|
|
48
|
-
- **Standard 账户**:开仓前,该交易所里要有 USDC。不够时用 `hyper_account action=transfer
|
|
55
|
+
- **Standard 账户**:开仓前,该交易所里要有 USDC。不够时用 `hyper_account action=transfer from=perp to=xyz amount=…`(旧写法 `dex=xyz direction=in` 仍可用)从主永续账户划入(半托管需要用户批准,全托管直接执行)。只划入这笔交易需要的保证金加一点缓冲,不要整笔搬空主账户。平仓后不再交易该市场时,可以用 `from=xyz to=perp` 转回。
|
|
49
56
|
- **统一账户(Unified Account)/ Portfolio Margin**:下 HIP-3 单时会自动调用主账户的 USDC,不需要划转。`hyper_context.accountMode` 能看出当前是哪种。开启统一账户需要用户在 Hyperliquid 网页操作。
|
|
50
|
-
-
|
|
57
|
+
- 划转都由交易主钱包签名(现货 ↔ 永续是 `usdClassTransfer`,永续 ↔ HIP-3 是 `sendAsset`),HIP-3 只支持以 USDC 为保证金的交易所;单次不超过仓位上限,只在 live 模式下可用。
|
|
51
58
|
- HIP-3 的手续费、杠杆上限与核心永续不同(按市场读取 `maxLeverage`),部分市场只允许逐仓。
|
|
52
59
|
|
|
53
60
|
### 执行能力与限制
|