perp-cli 0.14.2 → 0.15.0
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/README.md +152 -13
- package/dist/agent-wallet/store.d.ts +3 -2
- package/dist/agent-wallet/store.js +2 -2
- package/dist/api/public/hyperliquid.js +4 -0
- package/dist/api/public/pacifica.js +83 -13
- package/dist/api/public/urls.d.ts +2 -0
- package/dist/api/public/urls.js +3 -0
- package/dist/arb/utils.d.ts +1 -2
- package/dist/arb/utils.js +1 -2
- package/dist/bot/apex/pulse.js +3 -0
- package/dist/bot/apex/radar.js +2 -1
- package/dist/bot/engine.d.ts +10 -1
- package/dist/bot/engine.js +14 -6
- package/dist/bot/indicators.d.ts +7 -0
- package/dist/bot/indicators.js +16 -0
- package/dist/bot/perp-order.d.ts +4 -4
- package/dist/bot/perp-order.js +5 -5
- package/dist/bot/quarantine.d.ts +1 -1
- package/dist/bot/quarantine.js +1 -1
- package/dist/bot/strategies/apex-strategy.js +3 -2
- package/dist/bot/strategies/engine-mm.js +6 -5
- package/dist/bot/strategies/funding-arb-strategy.js +9 -9
- package/dist/bot/strategies/funding-arb-utils.d.ts +15 -2
- package/dist/bot/strategies/funding-arb-utils.js +43 -24
- package/dist/bot/strategies/funding-auto.js +2 -2
- package/dist/bot/strategies/liquidation-mm.d.ts +1 -0
- package/dist/bot/strategies/liquidation-mm.js +8 -2
- package/dist/bot/strategies/momentum-breakout.d.ts +1 -0
- package/dist/bot/strategies/momentum-breakout.js +11 -3
- package/dist/bot/strategies/spot-perp-arb-strategy.js +23 -12
- package/dist/bot/strategies/spot-perp-executor.d.ts +1 -1
- package/dist/bot/strategies/spot-perp-executor.js +1 -1
- package/dist/bot/strategy-types.d.ts +2 -1
- package/dist/bot/tui/BotDashboard.d.ts +1 -1
- package/dist/bot/tui/BotDashboard.js +1 -1
- package/dist/cache.js +12 -6
- package/dist/cli-program.d.ts +15 -0
- package/dist/cli-program.js +125 -5
- package/dist/commands/agent-import.d.ts +7 -0
- package/dist/commands/agent-import.js +30 -1
- package/dist/commands/agent.d.ts +6 -3
- package/dist/commands/agent.js +160 -12
- package/dist/commands/arb/index.js +4 -4
- package/dist/commands/arb-auto.js +21 -17
- package/dist/commands/arb.d.ts +12 -0
- package/dist/commands/arb.js +61 -143
- package/dist/commands/bot.js +1 -1
- package/dist/commands/builder.js +1 -1
- package/dist/commands/funds.js +113 -3
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.js +27 -7
- package/dist/commands/manage.js +23 -21
- package/dist/commands/market.js +168 -36
- package/dist/commands/options.d.ts +9 -0
- package/dist/commands/options.js +134 -0
- package/dist/commands/pacifica-earn.d.ts +5 -0
- package/dist/commands/pacifica-earn.js +468 -0
- package/dist/commands/pacifica-orders.d.ts +14 -0
- package/dist/commands/pacifica-orders.js +142 -0
- package/dist/commands/portfolio.js +32 -47
- package/dist/commands/rebalance.d.ts +1 -0
- package/dist/commands/rebalance.js +15 -0
- package/dist/commands/risk.d.ts +11 -2
- package/dist/commands/risk.js +39 -44
- package/dist/commands/trade.d.ts +1 -0
- package/dist/commands/trade.js +63 -58
- package/dist/commands/wallet.js +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +15 -4
- package/dist/constants.js +6 -0
- package/dist/dashboard/server.js +1 -1
- package/dist/dashboard/ui.js +1 -1
- package/dist/errors.d.ts +24 -1
- package/dist/errors.js +25 -3
- package/dist/exchanges/arcus/adapter.d.ts +7 -7
- package/dist/exchanges/arcus/adapter.js +12 -12
- package/dist/exchanges/arcus/agent.d.ts +1 -1
- package/dist/exchanges/arcus/agent.js +1 -1
- package/dist/exchanges/arcus/client.js +1 -1
- package/dist/exchanges/arcus/signing.d.ts +2 -3
- package/dist/exchanges/arcus/signing.js +1 -1
- package/dist/exchanges/arcus/spot-chain.d.ts +1 -1
- package/dist/exchanges/arcus/spot-chain.js +1 -1
- package/dist/exchanges/arcus/spot-router.d.ts +1 -1
- package/dist/exchanges/arcus/spot-router.js +2 -2
- package/dist/exchanges/arcus/spot.d.ts +2 -3
- package/dist/exchanges/arcus/spot.js +2 -3
- package/dist/exchanges/aster-spot.d.ts +3 -3
- package/dist/exchanges/aster-spot.js +6 -9
- package/dist/exchanges/aster-typed-data.d.ts +1 -1
- package/dist/exchanges/aster-typed-data.js +1 -1
- package/dist/exchanges/aster.d.ts +9 -4
- package/dist/exchanges/aster.js +125 -55
- package/dist/exchanges/builder-fee.d.ts +1 -1
- package/dist/exchanges/builder-fee.js +13 -2
- package/dist/exchanges/canonical-symbols.d.ts +1 -2
- package/dist/exchanges/canonical-symbols.js +26 -2
- package/dist/exchanges/derive/client.d.ts +37 -0
- package/dist/exchanges/derive/client.js +135 -0
- package/dist/exchanges/derive/options.d.ts +68 -0
- package/dist/exchanges/derive/options.js +360 -0
- package/dist/exchanges/extended/adapter.d.ts +82 -0
- package/dist/exchanges/extended/adapter.js +179 -0
- package/dist/exchanges/extended/client.d.ts +38 -0
- package/dist/exchanges/extended/client.js +88 -0
- package/dist/exchanges/extended/public.d.ts +130 -0
- package/dist/exchanges/extended/public.js +429 -0
- package/dist/exchanges/grvt/adapter.d.ts +86 -0
- package/dist/exchanges/grvt/adapter.js +206 -0
- package/dist/exchanges/grvt/client.d.ts +25 -0
- package/dist/exchanges/grvt/client.js +86 -0
- package/dist/exchanges/grvt/public.d.ts +151 -0
- package/dist/exchanges/grvt/public.js +438 -0
- package/dist/exchanges/hyperliquid-spot.d.ts +1 -1
- package/dist/exchanges/hyperliquid-spot.js +5 -5
- package/dist/exchanges/hyperliquid.d.ts +22 -16
- package/dist/exchanges/hyperliquid.js +80 -55
- package/dist/exchanges/index.d.ts +1 -1
- package/dist/exchanges/index.js +1 -1
- package/dist/exchanges/interface.d.ts +97 -8
- package/dist/exchanges/interface.js +19 -2
- package/dist/exchanges/ioc-outcome.d.ts +1 -1
- package/dist/exchanges/ioc-outcome.js +1 -1
- package/dist/exchanges/legacy-trading-v2.d.ts +2 -2
- package/dist/exchanges/legacy-trading-v2.js +7 -2
- package/dist/exchanges/lighter-public.d.ts +2 -2
- package/dist/exchanges/lighter-public.js +2 -2
- package/dist/exchanges/lighter-signer.d.ts +1 -1
- package/dist/exchanges/lighter-signer.js +1 -1
- package/dist/exchanges/lighter-spot.d.ts +3 -4
- package/dist/exchanges/lighter-spot.js +6 -7
- package/dist/exchanges/lighter.d.ts +11 -11
- package/dist/exchanges/lighter.js +28 -14
- package/dist/exchanges/ondo/adapter.d.ts +5 -6
- package/dist/exchanges/ondo/adapter.js +16 -14
- package/dist/exchanges/ondo/agent.d.ts +1 -1
- package/dist/exchanges/ondo/agent.js +1 -1
- package/dist/exchanges/ondo/client.d.ts +1 -1
- package/dist/exchanges/ondo/client.js +2 -2
- package/dist/exchanges/ondo/public.d.ts +8 -1
- package/dist/exchanges/ondo/public.js +13 -2
- package/dist/exchanges/ondo/spot.d.ts +2 -2
- package/dist/exchanges/ondo/spot.js +3 -3
- package/dist/exchanges/options-interface.d.ts +158 -0
- package/dist/exchanges/options-interface.js +17 -0
- package/dist/exchanges/options-venues.d.ts +12 -0
- package/dist/exchanges/options-venues.js +35 -0
- package/dist/exchanges/pacifica-atomic.d.ts +211 -0
- package/dist/exchanges/pacifica-atomic.js +440 -0
- package/dist/exchanges/pacifica-decimal.d.ts +10 -0
- package/dist/exchanges/pacifica-decimal.js +51 -0
- package/dist/exchanges/pacifica-presigned.d.ts +53 -0
- package/dist/exchanges/pacifica-presigned.js +141 -0
- package/dist/exchanges/pacifica-print.d.ts +200 -0
- package/dist/exchanges/pacifica-print.js +417 -0
- package/dist/exchanges/pacifica-spot.d.ts +2 -2
- package/dist/exchanges/pacifica-spot.js +3 -3
- package/dist/exchanges/pacifica-typed-data.d.ts +1 -1
- package/dist/exchanges/pacifica-typed-data.js +1 -1
- package/dist/exchanges/pacifica-vaults.d.ts +121 -0
- package/dist/exchanges/pacifica-vaults.js +264 -0
- package/dist/exchanges/pacifica.d.ts +32 -5
- package/dist/exchanges/pacifica.js +114 -48
- package/dist/exchanges/precision.d.ts +3 -1
- package/dist/exchanges/precision.js +9 -2
- package/dist/exchanges/qfex/adapter.d.ts +18 -5
- package/dist/exchanges/qfex/adapter.js +32 -12
- package/dist/exchanges/qfex/agent.d.ts +1 -1
- package/dist/exchanges/qfex/agent.js +1 -1
- package/dist/exchanges/qfex/client.d.ts +1 -1
- package/dist/exchanges/qfex/client.js +1 -1
- package/dist/exchanges/qfex/errors.d.ts +1 -1
- package/dist/exchanges/qfex/errors.js +2 -2
- package/dist/exchanges/qfex/public.d.ts +3 -3
- package/dist/exchanges/qfex/public.js +3 -3
- package/dist/exchanges/qfex/signing.d.ts +2 -2
- package/dist/exchanges/qfex/signing.js +4 -5
- package/dist/exchanges/qfex/ws-transport.d.ts +2 -2
- package/dist/exchanges/qfex/ws-transport.js +3 -3
- package/dist/exchanges/rate-limiter.d.ts +1 -1
- package/dist/exchanges/rate-limiter.js +5 -2
- package/dist/exchanges/registry.d.ts +1 -1
- package/dist/exchanges/registry.js +1 -1
- package/dist/exchanges/risex/adapter.d.ts +148 -0
- package/dist/exchanges/risex/adapter.js +796 -0
- package/dist/exchanges/risex/agent.d.ts +154 -0
- package/dist/exchanges/risex/agent.js +384 -0
- package/dist/exchanges/risex/client.d.ts +47 -0
- package/dist/exchanges/risex/client.js +174 -0
- package/dist/exchanges/risex/nonce.d.ts +43 -0
- package/dist/exchanges/risex/nonce.js +212 -0
- package/dist/exchanges/risex/public.d.ts +64 -0
- package/dist/exchanges/risex/public.js +150 -0
- package/dist/exchanges/risex/session.d.ts +71 -0
- package/dist/exchanges/risex/session.js +171 -0
- package/dist/exchanges/risex/typed-data.d.ts +173 -0
- package/dist/exchanges/risex/typed-data.js +240 -0
- package/dist/exchanges/risex/units.d.ts +29 -0
- package/dist/exchanges/risex/units.js +104 -0
- package/dist/exchanges/slippage.d.ts +1 -1
- package/dist/exchanges/slippage.js +1 -1
- package/dist/exchanges/spot-factory.d.ts +3 -3
- package/dist/exchanges/spot-factory.js +7 -7
- package/dist/exchanges/spot-interface.d.ts +5 -5
- package/dist/exchanges/spot-interface.js +2 -2
- package/dist/exchanges/spot-result.d.ts +3 -3
- package/dist/exchanges/spot-result.js +3 -3
- package/dist/exchanges/trading-v2.d.ts +3 -3
- package/dist/exchanges/trading-v2.js +9 -6
- package/dist/exchanges/txflow/adapter.d.ts +54 -0
- package/dist/exchanges/txflow/adapter.js +118 -0
- package/dist/exchanges/txflow/client.d.ts +47 -0
- package/dist/exchanges/txflow/client.js +153 -0
- package/dist/exchanges/txflow/public.d.ts +76 -0
- package/dist/exchanges/txflow/public.js +284 -0
- package/dist/exchanges/unknown-symbol.d.ts +29 -0
- package/dist/exchanges/unknown-symbol.js +51 -0
- package/dist/exchanges/variational/adapter.d.ts +71 -0
- package/dist/exchanges/variational/adapter.js +137 -0
- package/dist/exchanges/variational/client.d.ts +21 -0
- package/dist/exchanges/variational/client.js +66 -0
- package/dist/exchanges/variational/public.d.ts +126 -0
- package/dist/exchanges/variational/public.js +430 -0
- package/dist/exchanges/venue-types.d.ts +6 -7
- package/dist/exchanges/venue-types.js +2 -2
- package/dist/exchanges/venue.d.ts +51 -8
- package/dist/exchanges/venue.js +54 -4
- package/dist/exchanges/venues/arcus.d.ts +1 -2
- package/dist/exchanges/venues/arcus.js +5 -4
- package/dist/exchanges/venues/aster.d.ts +2 -2
- package/dist/exchanges/venues/aster.js +6 -4
- package/dist/exchanges/venues/create-helpers.d.ts +1 -1
- package/dist/exchanges/venues/create-helpers.js +3 -3
- package/dist/exchanges/venues/extended.d.ts +21 -0
- package/dist/exchanges/venues/extended.js +96 -0
- package/dist/exchanges/venues/grvt.d.ts +30 -0
- package/dist/exchanges/venues/grvt.js +98 -0
- package/dist/exchanges/venues/hyperliquid.d.ts +2 -2
- package/dist/exchanges/venues/hyperliquid.js +10 -8
- package/dist/exchanges/venues/index.d.ts +7 -2
- package/dist/exchanges/venues/index.js +8 -2
- package/dist/exchanges/venues/lighter-family.d.ts +7 -9
- package/dist/exchanges/venues/lighter-family.js +9 -11
- package/dist/exchanges/venues/lighter-rh.d.ts +2 -2
- package/dist/exchanges/venues/lighter-rh.js +7 -5
- package/dist/exchanges/venues/lighter.d.ts +1 -1
- package/dist/exchanges/venues/lighter.js +5 -3
- package/dist/exchanges/venues/ondo.d.ts +1 -1
- package/dist/exchanges/venues/ondo.js +5 -3
- package/dist/exchanges/venues/pacifica.d.ts +2 -2
- package/dist/exchanges/venues/pacifica.js +6 -4
- package/dist/exchanges/venues/qfex.d.ts +1 -1
- package/dist/exchanges/venues/qfex.js +4 -2
- package/dist/exchanges/venues/risex-release.d.ts +14 -0
- package/dist/exchanges/venues/risex-release.js +14 -0
- package/dist/exchanges/venues/risex.d.ts +31 -0
- package/dist/exchanges/venues/risex.js +116 -0
- package/dist/exchanges/venues/txflow.d.ts +18 -0
- package/dist/exchanges/venues/txflow.js +77 -0
- package/dist/exchanges/venues/variational.d.ts +21 -0
- package/dist/exchanges/venues/variational.js +85 -0
- package/dist/execution-log.d.ts +1 -1
- package/dist/funding/legacy-public.d.ts +1 -1
- package/dist/funding/legacy-public.js +9 -4
- package/dist/funding/normalize.d.ts +1 -1
- package/dist/funding/normalize.js +1 -1
- package/dist/funding/rates.d.ts +44 -4
- package/dist/funding/rates.js +56 -12
- package/dist/index.js +7 -6
- package/dist/jobs.d.ts +1 -0
- package/dist/jobs.js +25 -1
- package/dist/landing.d.ts +2 -0
- package/dist/landing.js +1 -1
- package/dist/mcp-pacifica-earn.d.ts +9 -0
- package/dist/mcp-pacifica-earn.js +58 -0
- package/dist/mcp-server.js +113 -59
- package/dist/pacifica/client.d.ts +67 -4
- package/dist/pacifica/client.js +170 -8
- package/dist/pacifica/rate-limit.d.ts +144 -0
- package/dist/pacifica/rate-limit.js +267 -0
- package/dist/pacifica/types/order.d.ts +2 -1
- package/dist/plan-executor.js +7 -2
- package/dist/rebalance.js +1 -1
- package/dist/risk.d.ts +2 -1
- package/dist/risk.js +2 -4
- package/dist/settings.d.ts +32 -3
- package/dist/signer/ows-evm.d.ts +1 -1
- package/dist/signer/ows-evm.js +1 -1
- package/dist/smart-order.d.ts +1 -1
- package/dist/smart-order.js +1 -1
- package/dist/strategies/funding-arb.d.ts +1 -1
- package/dist/strategies/funding-arb.js +1 -1
- package/dist/trade-validator.d.ts +1 -1
- package/dist/trade-validator.js +9 -4
- package/dist/utils.d.ts +12 -3
- package/dist/utils.js +11 -3
- package/dist/venue-health.d.ts +40 -0
- package/dist/venue-health.js +75 -0
- package/dist/withdraw-gate.d.ts +1 -1
- package/dist/withdraw-gate.js +1 -1
- package/dist/ws/index.d.ts +959 -0
- package/dist/ws/index.js +4295 -0
- package/dist/ws/node.d.ts +975 -0
- package/dist/ws/node.js +4366 -0
- package/dist/ws/pacifica-instrument.d.ts +8 -0
- package/dist/ws/pacifica-instrument.js +8 -0
- package/dist/ws-cli/credentials.d.ts +62 -0
- package/dist/ws-cli/credentials.js +126 -0
- package/package.json +58 -10
- package/skills/perp-cli/SKILL.md +62 -9
- package/skills/perp-cli/references/agent-operations.md +7 -0
- package/skills/perp-cli/references/commands.md +76 -5
- package/skills/perp-cli/references/ws-library.md +492 -0
package/dist/errors.d.ts
CHANGED
|
@@ -158,7 +158,7 @@ export declare const ERROR_CODES: {
|
|
|
158
158
|
readonly status: 202;
|
|
159
159
|
readonly retryable: false;
|
|
160
160
|
};
|
|
161
|
-
/** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent
|
|
161
|
+
/** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent. */
|
|
162
162
|
readonly ORDER_REJECTED: {
|
|
163
163
|
readonly code: "ORDER_REJECTED";
|
|
164
164
|
readonly status: 422;
|
|
@@ -173,6 +173,29 @@ export declare const ERROR_CODES: {
|
|
|
173
173
|
readonly status: 422;
|
|
174
174
|
readonly retryable: false;
|
|
175
175
|
};
|
|
176
|
+
/** A venue frame could not be parsed or classified (never silently dropped). */
|
|
177
|
+
readonly WS_PROTOCOL_ERROR: {
|
|
178
|
+
readonly code: "WS_PROTOCOL_ERROR";
|
|
179
|
+
readonly status: 502;
|
|
180
|
+
readonly retryable: false;
|
|
181
|
+
};
|
|
182
|
+
readonly WS_AUTH_FAILED: {
|
|
183
|
+
readonly code: "WS_AUTH_FAILED";
|
|
184
|
+
readonly status: 401;
|
|
185
|
+
readonly retryable: false;
|
|
186
|
+
};
|
|
187
|
+
/** A subscription / connection budget (venue limit or caller budget) would be exceeded. */
|
|
188
|
+
readonly SUBSCRIPTION_LIMIT: {
|
|
189
|
+
readonly code: "SUBSCRIPTION_LIMIT";
|
|
190
|
+
readonly status: 400;
|
|
191
|
+
readonly retryable: false;
|
|
192
|
+
};
|
|
193
|
+
/** An event stream's bounded buffer overflowed; the subscription was closed. */
|
|
194
|
+
readonly STREAM_OVERFLOW: {
|
|
195
|
+
readonly code: "STREAM_OVERFLOW";
|
|
196
|
+
readonly status: 507;
|
|
197
|
+
readonly retryable: false;
|
|
198
|
+
};
|
|
176
199
|
readonly EXCHANGE_UNREACHABLE: {
|
|
177
200
|
readonly code: "EXCHANGE_UNREACHABLE";
|
|
178
201
|
readonly status: 503;
|
package/dist/errors.js
CHANGED
|
@@ -25,7 +25,7 @@ export const ERROR_CODES = {
|
|
|
25
25
|
PASSPHRASE_REQUIRED: { code: "PASSPHRASE_REQUIRED", status: 401, retryable: false },
|
|
26
26
|
INVALID_PASSPHRASE: { code: "INVALID_PASSPHRASE", status: 401, retryable: false },
|
|
27
27
|
NOT_IMPLEMENTED: { code: "NOT_IMPLEMENTED", status: 501, retryable: false },
|
|
28
|
-
// Venue abstraction
|
|
28
|
+
// Venue abstraction
|
|
29
29
|
UNKNOWN_VENUE: { code: "UNKNOWN_VENUE", status: 400, retryable: false },
|
|
30
30
|
TIF_REQUIRED: { code: "TIF_REQUIRED", status: 400, retryable: false },
|
|
31
31
|
INVALID_TICK: { code: "INVALID_TICK", status: 400, retryable: false },
|
|
@@ -36,13 +36,21 @@ export const ERROR_CODES = {
|
|
|
36
36
|
ORDER_PARTIAL: { code: "ORDER_PARTIAL", status: 500, retryable: false },
|
|
37
37
|
/** The order was submitted but its outcome is not confirmed; retrying could double-trade. */
|
|
38
38
|
ORDER_PENDING: { code: "ORDER_PENDING", status: 202, retryable: false },
|
|
39
|
-
/** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent
|
|
39
|
+
/** The order was definitely NOT placed: the venue rejected it, or it failed before it was sent. */
|
|
40
40
|
ORDER_REJECTED: { code: "ORDER_REJECTED", status: 422, retryable: false },
|
|
41
41
|
/**
|
|
42
42
|
* The venue explicitly refused a non-order account action (withdraw / transfer / approval) and
|
|
43
43
|
* executed nothing — distinct from a network / unknown outcome (EXCHANGE_ERROR, UNKNOWN).
|
|
44
44
|
*/
|
|
45
45
|
ACTION_REJECTED: { code: "ACTION_REJECTED", status: 422, retryable: false },
|
|
46
|
+
// WebSocket library (perp-cli/ws, src/ws/errors.ts keeps a parity-tested copy)
|
|
47
|
+
/** A venue frame could not be parsed or classified (never silently dropped). */
|
|
48
|
+
WS_PROTOCOL_ERROR: { code: "WS_PROTOCOL_ERROR", status: 502, retryable: false },
|
|
49
|
+
WS_AUTH_FAILED: { code: "WS_AUTH_FAILED", status: 401, retryable: false },
|
|
50
|
+
/** A subscription / connection budget (venue limit or caller budget) would be exceeded. */
|
|
51
|
+
SUBSCRIPTION_LIMIT: { code: "SUBSCRIPTION_LIMIT", status: 400, retryable: false },
|
|
52
|
+
/** An event stream's bounded buffer overflowed; the subscription was closed. */
|
|
53
|
+
STREAM_OVERFLOW: { code: "STREAM_OVERFLOW", status: 507, retryable: false },
|
|
46
54
|
// 5xx - System / transient errors
|
|
47
55
|
EXCHANGE_UNREACHABLE: { code: "EXCHANGE_UNREACHABLE", status: 503, retryable: true },
|
|
48
56
|
RATE_LIMITED: { code: "RATE_LIMITED", status: 429, retryable: true, retryAfterMs: 1000 },
|
|
@@ -92,6 +100,12 @@ export function classifyError(err, exchange) {
|
|
|
92
100
|
const ex = (err.structured.exchange ?? exchange);
|
|
93
101
|
return ex !== undefined ? { ...err.structured, exchange: ex } : { ...err.structured };
|
|
94
102
|
}
|
|
103
|
+
// Structural PerpError (perp-cli/ws WsError is a separate leaf class): keep its registered code.
|
|
104
|
+
if (err instanceof Error && isStructuredLike(err)) {
|
|
105
|
+
const s = err.structured;
|
|
106
|
+
const ex = s.exchange ?? exchange;
|
|
107
|
+
return ex !== undefined ? { ...s, exchange: ex } : { ...s };
|
|
108
|
+
}
|
|
95
109
|
const message = extractErrorMessage(err);
|
|
96
110
|
const lower = message.toLowerCase();
|
|
97
111
|
// Margin-specific checks first (before generic "insufficient" catch)
|
|
@@ -216,6 +230,14 @@ export function classifyError(err, exchange) {
|
|
|
216
230
|
}
|
|
217
231
|
return { ...ERROR_CODES.UNKNOWN, message };
|
|
218
232
|
}
|
|
233
|
+
function isStructuredLike(err) {
|
|
234
|
+
const s = err.structured;
|
|
235
|
+
if (s === null || typeof s !== "object")
|
|
236
|
+
return false;
|
|
237
|
+
const { code, message, status, retryable } = s;
|
|
238
|
+
return typeof code === "string" && Object.prototype.hasOwnProperty.call(ERROR_CODES, code)
|
|
239
|
+
&& typeof message === "string" && typeof status === "number" && typeof retryable === "boolean";
|
|
240
|
+
}
|
|
219
241
|
/** Custom error class that carries a structured error code */
|
|
220
242
|
export class PerpError extends Error {
|
|
221
243
|
structured;
|
|
@@ -235,7 +257,7 @@ export class PerpError extends Error {
|
|
|
235
257
|
};
|
|
236
258
|
}
|
|
237
259
|
}
|
|
238
|
-
// ── Order outcome classification
|
|
260
|
+
// ── Order outcome classification ──
|
|
239
261
|
/**
|
|
240
262
|
* Codes that mean "the order was definitely not placed / filled nothing": a validation
|
|
241
263
|
* or policy failure before sending (incl. PRICE_STALE: no price to build the order), or an
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim
|
|
2
|
+
* Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim.
|
|
3
3
|
*
|
|
4
4
|
* Signing: the agent API key is an Ed25519 key in OWS wallet
|
|
5
5
|
* `meta.agentWalletName` (raw signMessage on the Solana account — no prefix).
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
* (master creds only, for spot swaps) every perp private call throws
|
|
8
8
|
* AGENT_NOT_REGISTERED from requireAccount().
|
|
9
9
|
*
|
|
10
|
-
* Order entry rules (docs.arcus.xyz
|
|
10
|
+
* Order entry rules (docs.arcus.xyz):
|
|
11
11
|
* - every order carries goodTilTime ≥ 1 month ahead (ARCUS_GOOD_TIL_HORIZON_MS),
|
|
12
12
|
* body in µs, signed `g` in ns;
|
|
13
13
|
* - market orders = IOC LIMIT at a protection price derived from mark and an
|
|
14
14
|
* explicit slippage bound, rejected locally when > 10 % from mark;
|
|
15
|
-
* - TIF
|
|
15
|
+
* - TIF: common GTC is sent as GTT with goodTil = now +
|
|
16
16
|
* ARCUS_GOOD_TIL_HORIZON_MS (recorded as execution.expiresAt); IOC / FOK / ALO
|
|
17
17
|
* are native; a limit order without a TIF is GTC;
|
|
18
18
|
* - clientId is always sent (orderAck async) and every OrderResult from a
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
* an `entryTpsl` bundle.
|
|
23
23
|
*/
|
|
24
24
|
import type { EvmSigner } from "../../signer/interface.js";
|
|
25
|
-
import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade } from "../interface.js";
|
|
25
|
+
import type { ExchangeAdapter, ExchangeBalance, ExchangeFundingPayment, ExchangeKline, ExchangeMarketInfo, ExchangeOrder, ExchangePosition, ExchangeTrade, ExchangePublicTrade } from "../interface.js";
|
|
26
26
|
import type { ResolvedSlippage } from "../slippage.js";
|
|
27
27
|
import { type TradingV2 } from "../trading-v2.js";
|
|
28
28
|
import type { VenueCreateContext, VenueDefinition } from "../venue.js";
|
|
@@ -92,7 +92,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
92
92
|
/**
|
|
93
93
|
* modifyOrder (docs modify-order / authentication).
|
|
94
94
|
*
|
|
95
|
-
* Size: the CLI's `req.size` is the new OPEN (unfilled) size
|
|
95
|
+
* Size: the CLI's `req.size` is the new OPEN (unfilled) size, while
|
|
96
96
|
* Arcus modifies take the order's new TOTAL size, filled quantity included
|
|
97
97
|
* (OrderRejectionReason MODIFY_SIZE_ALREADY_FILLED: "the order's new TOTAL size,
|
|
98
98
|
* filled quantity included"). So body `quantity` and signed `q` are
|
|
@@ -143,7 +143,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
143
143
|
bids: [string, string][];
|
|
144
144
|
asks: [string, string][];
|
|
145
145
|
}>;
|
|
146
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
146
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
147
147
|
getFundingHistory(symbol: string, limit?: number): Promise<{
|
|
148
148
|
time: number;
|
|
149
149
|
rate: string;
|
|
@@ -182,7 +182,7 @@ export declare class ArcusAdapter implements ExchangeAdapter, TradingV2 {
|
|
|
182
182
|
}): Promise<unknown>;
|
|
183
183
|
private masterSigner;
|
|
184
184
|
private requireMasterKey;
|
|
185
|
-
/** Master EVM signer for on-chain actions outside the Arcus API (spot swaps
|
|
185
|
+
/** Master EVM signer for on-chain actions outside the Arcus API (spot swaps). */
|
|
186
186
|
masterEvmSigner(): Promise<EvmSigner>;
|
|
187
187
|
/** Sign an unsigned EVM transaction with the master key (digest derived here). Returns a 65-byte 0x signature. */
|
|
188
188
|
signMasterTransaction(tx: import("ethers").Transaction): Promise<string>;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim
|
|
2
|
+
* Arcus adapter — native TradingV2 + legacy ExchangeAdapter shim.
|
|
3
3
|
*
|
|
4
4
|
* Signing: the agent API key is an Ed25519 key in OWS wallet
|
|
5
5
|
* `meta.agentWalletName` (raw signMessage on the Solana account — no prefix).
|
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
* (master creds only, for spot swaps) every perp private call throws
|
|
8
8
|
* AGENT_NOT_REGISTERED from requireAccount().
|
|
9
9
|
*
|
|
10
|
-
* Order entry rules (docs.arcus.xyz
|
|
10
|
+
* Order entry rules (docs.arcus.xyz):
|
|
11
11
|
* - every order carries goodTilTime ≥ 1 month ahead (ARCUS_GOOD_TIL_HORIZON_MS),
|
|
12
12
|
* body in µs, signed `g` in ns;
|
|
13
13
|
* - market orders = IOC LIMIT at a protection price derived from mark and an
|
|
14
14
|
* explicit slippage bound, rejected locally when > 10 % from mark;
|
|
15
|
-
* - TIF
|
|
15
|
+
* - TIF: common GTC is sent as GTT with goodTil = now +
|
|
16
16
|
* ARCUS_GOOD_TIL_HORIZON_MS (recorded as execution.expiresAt); IOC / FOK / ALO
|
|
17
17
|
* are native; a limit order without a TIF is GTC;
|
|
18
18
|
* - clientId is always sent (orderAck async) and every OrderResult from a
|
|
@@ -196,13 +196,13 @@ export class ArcusAdapter {
|
|
|
196
196
|
const meta = ctx.noAgent ? null : ctx.credentials.agent;
|
|
197
197
|
if (meta === null) {
|
|
198
198
|
if (!hasMaster) {
|
|
199
|
-
//
|
|
199
|
+
// no agent key and no master EVM key — nothing can sign.
|
|
200
200
|
throw new PerpError("NO_SIGNER_AVAILABLE", "No Arcus signer: no agent API key and no master EVM wallet / private key", {
|
|
201
201
|
remediation: "Spot swaps: pass --wallet <ows-wallet> (master EVM key). Perp trading: perp wallet agent approve arcus --master <ows-wallet>",
|
|
202
202
|
});
|
|
203
203
|
}
|
|
204
204
|
// Master-only (also --no-agent): spot swaps (master EVM signer) work; perp
|
|
205
|
-
// private calls throw AGENT_NOT_REGISTERED in requireAccount()
|
|
205
|
+
// private calls throw AGENT_NOT_REGISTERED in requireAccount().
|
|
206
206
|
this.client = new ArcusClient(ctx.network, null);
|
|
207
207
|
this.account = null;
|
|
208
208
|
return;
|
|
@@ -462,7 +462,7 @@ export class ArcusAdapter {
|
|
|
462
462
|
return onlineArcusMarkets(raw).map(toArcusVenueMarket);
|
|
463
463
|
}
|
|
464
464
|
async placeOrder(input) {
|
|
465
|
-
//
|
|
465
|
+
// GTC is the uniform default for a limit order without a TIF.
|
|
466
466
|
const tifRequested = input.tif;
|
|
467
467
|
const req = input.type === "limit" && input.tif === null ? { ...input, tif: "GTC" } : input;
|
|
468
468
|
validateOrderRequest(this.venue, this.caps, req);
|
|
@@ -609,7 +609,7 @@ export class ArcusAdapter {
|
|
|
609
609
|
/**
|
|
610
610
|
* modifyOrder (docs modify-order / authentication).
|
|
611
611
|
*
|
|
612
|
-
* Size: the CLI's `req.size` is the new OPEN (unfilled) size
|
|
612
|
+
* Size: the CLI's `req.size` is the new OPEN (unfilled) size, while
|
|
613
613
|
* Arcus modifies take the order's new TOTAL size, filled quantity included
|
|
614
614
|
* (OrderRejectionReason MODIFY_SIZE_ALREADY_FILLED: "the order's new TOTAL size,
|
|
615
615
|
* filled quantity included"). So body `quantity` and signed `q` are
|
|
@@ -886,7 +886,7 @@ export class ArcusAdapter {
|
|
|
886
886
|
const m = await this.market(symbol);
|
|
887
887
|
const res = await this.client.get("/v1/trades", "trades", { market: m.marketDisplayName, limit });
|
|
888
888
|
// Public tape carries no fee; "0" follows the legacy ExchangeTrade convention for public trades.
|
|
889
|
-
return res.trades.map(t => ({ time: usToMs(t.timestamp), symbol: m.baseAsset, side: sideLower(t.side), price: t.price, size: t.size, fee:
|
|
889
|
+
return res.trades.map(t => ({ time: usToMs(t.timestamp), symbol: m.baseAsset, side: sideLower(t.side), price: t.price, size: t.size, fee: null }));
|
|
890
890
|
}
|
|
891
891
|
async getFundingHistory(symbol, limit = 100) {
|
|
892
892
|
const m = await this.market(symbol);
|
|
@@ -915,7 +915,7 @@ export class ArcusAdapter {
|
|
|
915
915
|
const res = await this.client.get("/v1/candles", "candles", { market: m.marketDisplayName, timeframe: interval, from: from * 1000, to: to * 1000 });
|
|
916
916
|
for (const c of res.candles) {
|
|
917
917
|
const time = usToMs(c.openTime);
|
|
918
|
-
byTime.set(time, { time, open: c.open, high: c.high, low: c.low, close: c.close, volume: c.volume, trades: c.tradeCount });
|
|
918
|
+
byTime.set(time, { time, open: c.open, high: c.high, low: c.low, close: c.close, volume: c.volume, quoteVolume: null, trades: c.tradeCount });
|
|
919
919
|
}
|
|
920
920
|
}
|
|
921
921
|
return [...byTime.values()].sort((x, y) => x.time - y.time);
|
|
@@ -995,7 +995,7 @@ export class ArcusAdapter {
|
|
|
995
995
|
out.push({ time: usToMs(p.time), symbol: await this.symbolOf(p.marketId), payment: p.payment });
|
|
996
996
|
return out;
|
|
997
997
|
}
|
|
998
|
-
// ── Legacy: trading shims
|
|
998
|
+
// ── Legacy: trading shims ──
|
|
999
999
|
/** `clientOrderId`: the caller's id when given; otherwise one is generated (orderAck async needs one). */
|
|
1000
1000
|
async marketOrder(symbol, side, size, opts) {
|
|
1001
1001
|
return this.placeOrder({
|
|
@@ -1036,7 +1036,7 @@ export class ArcusAdapter {
|
|
|
1036
1036
|
tif: isLimit ? "GTC" : null, // sent as GTT at the max horizon
|
|
1037
1037
|
reduceOnly: opts?.reduceOnly === true, // non-reduce-only → CAPABILITY_UNSUPPORTED in validation
|
|
1038
1038
|
clientOrderId: newClientOrderId(),
|
|
1039
|
-
// The caller's resolved bound (the adapter never reads settings
|
|
1039
|
+
// The caller's resolved bound (the adapter never reads settings);
|
|
1040
1040
|
// a stop-market without it → INVALID_PARAMS in placeOrder.
|
|
1041
1041
|
slippage: isLimit ? null : opts?.slippage ?? null,
|
|
1042
1042
|
tpsl: null,
|
|
@@ -1060,7 +1060,7 @@ export class ArcusAdapter {
|
|
|
1060
1060
|
});
|
|
1061
1061
|
}
|
|
1062
1062
|
}
|
|
1063
|
-
/** Master EVM signer for on-chain actions outside the Arcus API (spot swaps
|
|
1063
|
+
/** Master EVM signer for on-chain actions outside the Arcus API (spot swaps). */
|
|
1064
1064
|
async masterEvmSigner() {
|
|
1065
1065
|
this.requireMasterKey();
|
|
1066
1066
|
return this.masterSigner();
|
|
@@ -198,7 +198,7 @@ export class ArcusClient {
|
|
|
198
198
|
async send(method, url, endpoint, headers, body) {
|
|
199
199
|
// Timeout covers fetch + body read. A GET failure is definite (TIMEOUT /
|
|
200
200
|
// EXCHANGE_UNREACHABLE); a POST failure may have reached the venue → outcome
|
|
201
|
-
// unknown (ORDER_PENDING, never resubmit
|
|
201
|
+
// unknown (ORDER_PENDING, never resubmit).
|
|
202
202
|
const signal = AbortSignal.timeout(TIMEOUT_MS);
|
|
203
203
|
let res;
|
|
204
204
|
let text;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* "everything else" rule, scheduleCancel — unverified):
|
|
15
15
|
* ed25519(timestampNs + action + canonicalJson(body))
|
|
16
16
|
*
|
|
17
|
-
* Time units
|
|
17
|
+
* Time units: `ct` and X-Timestamp are Unix NANOseconds;
|
|
18
18
|
* signed `g` is NANOseconds; the request body `goodTilTime` is a MICROsecond
|
|
19
19
|
* decimal string (g = goodTilTime × 1000).
|
|
20
20
|
*
|
|
@@ -78,8 +78,7 @@ export declare function placePayload(f: ArcusPlaceFields, untriggered: boolean):
|
|
|
78
78
|
* - authentication page: always `id`, plus `c` "only if the resting order was placed
|
|
79
79
|
* with a client id … the engine rejects a mismatch".
|
|
80
80
|
* Default follows the openapi spec ("idOnly": sign `id`, never `c`; the body sends
|
|
81
|
-
* orderId only). "idAndClientId" is the authentication-page variant. Settled by the
|
|
82
|
-
* docs/TEST-PLAN.md step "Arcus modify signature identity" on testnet.
|
|
81
|
+
* orderId only). "idAndClientId" is the authentication-page variant. Settled by the "Arcus modify signature identity" testnet check.
|
|
83
82
|
*/
|
|
84
83
|
export type ArcusModifyIdentity = "idOnly" | "idAndClientId";
|
|
85
84
|
export declare const ARCUS_MODIFY_SIGNED_IDENTITY: ArcusModifyIdentity;
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* "everything else" rule, scheduleCancel — unverified):
|
|
15
15
|
* ed25519(timestampNs + action + canonicalJson(body))
|
|
16
16
|
*
|
|
17
|
-
* Time units
|
|
17
|
+
* Time units: `ct` and X-Timestamp are Unix NANOseconds;
|
|
18
18
|
* signed `g` is NANOseconds; the request body `goodTilTime` is a MICROsecond
|
|
19
19
|
* decimal string (g = goodTilTime × 1000).
|
|
20
20
|
*
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus Spot Router HTTP client + wire types
|
|
2
|
+
* Arcus Spot Router HTTP client + wire types.
|
|
3
3
|
*
|
|
4
4
|
* Ported from @arcus-xyz/arcus-spot-sdk@1.0.2 (src/client.ts, src/types.ts,
|
|
5
5
|
* src/chains.ts) — Copyright Arcus, licensed under the Apache License 2.0
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus Spot Router HTTP client + wire types
|
|
2
|
+
* Arcus Spot Router HTTP client + wire types.
|
|
3
3
|
*
|
|
4
4
|
* Ported from @arcus-xyz/arcus-spot-sdk@1.0.2 (src/client.ts, src/types.ts,
|
|
5
5
|
* src/chains.ts) — Copyright Arcus, licensed under the Apache License 2.0
|
|
@@ -167,7 +167,7 @@ export class ArcusSpotRouter {
|
|
|
167
167
|
sellAmount: p.sellAmount.toString(),
|
|
168
168
|
taker: p.taker,
|
|
169
169
|
slippageBps: String(p.slippageBps),
|
|
170
|
-
allowWrapped: "false", //
|
|
170
|
+
allowWrapped: "false", // never accept a wrapped placeholder
|
|
171
171
|
});
|
|
172
172
|
}
|
|
173
173
|
/** Single attempt — never retried (a resend could double-execute). Throws RouterHttpError / PerpError. */
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus spot = Stock Token swaps through the Arcus Spot Router
|
|
3
|
-
* §12.4 #5 #7). Not an exchange account: balances are the master wallet's
|
|
2
|
+
* Arcus spot = Stock Token swaps through the Arcus Spot Router. Not an exchange account: balances are the master wallet's
|
|
4
3
|
* ERC-20 balances on Robinhood Chain, and every trade is an exact-input swap
|
|
5
4
|
* settled on-chain (Permit2 `PermitWitnessTransferFrom` + `TakerIntent`).
|
|
6
5
|
*
|
|
@@ -79,7 +78,7 @@ export declare class ArcusSpotAdapter implements SpotAdapter, SpotPricesCapable
|
|
|
79
78
|
* all-in buy price at that notional. The signed intent must then carry
|
|
80
79
|
* minBuyAmount ≥ size × (1 − slippageBps), else nothing is signed.
|
|
81
80
|
* Both sides also require minBuyAmount ≥ quote.buyAmount × (1 − slippageBps).
|
|
82
|
-
* slippageBps = the caller's resolveSlippage() value
|
|
81
|
+
* slippageBps = the caller's resolveSlippage() value; the router
|
|
83
82
|
* takes an integer bound.
|
|
84
83
|
*/
|
|
85
84
|
spotMarketOrder(symbol: string, side: "buy" | "sell", size: string, opts: {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Arcus spot = Stock Token swaps through the Arcus Spot Router
|
|
3
|
-
* §12.4 #5 #7). Not an exchange account: balances are the master wallet's
|
|
2
|
+
* Arcus spot = Stock Token swaps through the Arcus Spot Router. Not an exchange account: balances are the master wallet's
|
|
4
3
|
* ERC-20 balances on Robinhood Chain, and every trade is an exact-input swap
|
|
5
4
|
* settled on-chain (Permit2 `PermitWitnessTransferFrom` + `TakerIntent`).
|
|
6
5
|
*
|
|
@@ -335,7 +334,7 @@ export class ArcusSpotAdapter {
|
|
|
335
334
|
* all-in buy price at that notional. The signed intent must then carry
|
|
336
335
|
* minBuyAmount ≥ size × (1 − slippageBps), else nothing is signed.
|
|
337
336
|
* Both sides also require minBuyAmount ≥ quote.buyAmount × (1 − slippageBps).
|
|
338
|
-
* slippageBps = the caller's resolveSlippage() value
|
|
337
|
+
* slippageBps = the caller's resolveSlippage() value; the router
|
|
339
338
|
* takes an integer bound.
|
|
340
339
|
*/
|
|
341
340
|
async spotMarketOrder(symbol, side, size, opts) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Aster Spot Adapter
|
|
2
|
+
* Aster Spot Adapter.
|
|
3
3
|
*
|
|
4
4
|
* Host `sapi.asterdex.com` (testnet `sapi.asterdex-testnet.com`), paths
|
|
5
5
|
* `/api/v3/*`. Signing is the perp EIP-712 Domain B scheme, reused through
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Venue rules enforced locally (official spot V3 docs):
|
|
12
12
|
* - TIF GTC | IOC | GTX (post-only). FOK is rejected by the venue (-1115).
|
|
13
13
|
* - LIMIT price must be on PRICE_FILTER.tickSize (never rounded).
|
|
14
|
-
* - Market orders are IOC LIMIT at a protection price
|
|
14
|
+
* - Market orders are IOC LIMIT at a protection price: bookTicker
|
|
15
15
|
* mid ± slippage, aligned toward crossing on tickSize, inside PRICE_FILTER
|
|
16
16
|
* min/max and PERCENT_PRICE (venue native MARKET is never sent).
|
|
17
17
|
* - quantity on LOT_SIZE step, min, max (MARKET_LOT_SIZE only for native MARKET).
|
|
@@ -95,7 +95,7 @@ export declare class AsterSpotAdapter implements SpotAdapter, SpotTransferCapabl
|
|
|
95
95
|
/** Effective minimum notional, or null when no filter applies. */
|
|
96
96
|
private _minNotional;
|
|
97
97
|
private _checkNotional;
|
|
98
|
-
/**
|
|
98
|
+
/** gate only when the active signer is an agent lacking canSpotTrade. */
|
|
99
99
|
private _requireSpotPermission;
|
|
100
100
|
private _signed;
|
|
101
101
|
private _publicGet;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Aster Spot Adapter
|
|
2
|
+
* Aster Spot Adapter.
|
|
3
3
|
*
|
|
4
4
|
* Host `sapi.asterdex.com` (testnet `sapi.asterdex-testnet.com`), paths
|
|
5
5
|
* `/api/v3/*`. Signing is the perp EIP-712 Domain B scheme, reused through
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* Venue rules enforced locally (official spot V3 docs):
|
|
12
12
|
* - TIF GTC | IOC | GTX (post-only). FOK is rejected by the venue (-1115).
|
|
13
13
|
* - LIMIT price must be on PRICE_FILTER.tickSize (never rounded).
|
|
14
|
-
* - Market orders are IOC LIMIT at a protection price
|
|
14
|
+
* - Market orders are IOC LIMIT at a protection price: bookTicker
|
|
15
15
|
* mid ± slippage, aligned toward crossing on tickSize, inside PRICE_FILTER
|
|
16
16
|
* min/max and PERCENT_PRICE (venue native MARKET is never sent).
|
|
17
17
|
* - quantity on LOT_SIZE step, min, max (MARKET_LOT_SIZE only for native MARKET).
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
import { unsupported } from "./trading-v2.js";
|
|
25
25
|
import { asterIocOutcome } from "./aster.js";
|
|
26
26
|
import { PerpError, isTransportFailure, orderNotSent, orderOutcomeUnknown, sendFailure, unknownActionRemediation } from "../errors.js";
|
|
27
|
-
import { alignProtectionPrice, exactUnits, floorSize, requireOnTick, requirePositive, slippagePrice, subDecimal } from "./precision.js";
|
|
27
|
+
import { addDecimal, alignProtectionPrice, exactUnits, floorSize, requireOnTick, requirePositive, slippagePrice, subDecimal } from "./precision.js";
|
|
28
28
|
/** Default quote for a bare base symbol (= venue spot quoteAssets[0]). */
|
|
29
29
|
const DEFAULT_QUOTE = "USDT";
|
|
30
30
|
const SPOT_REMEDIATION = "perp wallet agent rotate aster --can-spot";
|
|
@@ -41,9 +41,6 @@ function cmp(a, b) {
|
|
|
41
41
|
return -1;
|
|
42
42
|
return d === "0" ? 0 : 1;
|
|
43
43
|
}
|
|
44
|
-
function addDecimal(a, b) {
|
|
45
|
-
return subDecimal(a, b.startsWith("-") ? b.slice(1) : `-${b}`);
|
|
46
|
-
}
|
|
47
44
|
function isZero(v) {
|
|
48
45
|
return cmp(v, "0") === 0;
|
|
49
46
|
}
|
|
@@ -150,7 +147,7 @@ export class AsterSpotAdapter {
|
|
|
150
147
|
}
|
|
151
148
|
// ── Trading ──
|
|
152
149
|
async spotMarketOrder(symbol, side, size, opts) {
|
|
153
|
-
//
|
|
150
|
+
// IOC LIMIT at the protection price, never native MARKET (no price cap).
|
|
154
151
|
// Pre-send (market, size, price, min notional, permission): a failure is a definite "not placed".
|
|
155
152
|
let m;
|
|
156
153
|
let qty;
|
|
@@ -246,7 +243,7 @@ export class AsterSpotAdapter {
|
|
|
246
243
|
}
|
|
247
244
|
async spotLimitOrder(symbol, side, price, size, opts) {
|
|
248
245
|
const m = this._resolveTrading(symbol);
|
|
249
|
-
// Aster is a legacy family: limit orders keep the GTC default
|
|
246
|
+
// Aster is a legacy family: limit orders keep the GTC default.
|
|
250
247
|
const tif = this._mapTif(opts?.tif === undefined ? "GTC" : opts.tif);
|
|
251
248
|
const px = requireOnTick(price, m.tickSize);
|
|
252
249
|
const qty = this._sizeFor(m, size, false);
|
|
@@ -517,7 +514,7 @@ export class AsterSpotAdapter {
|
|
|
517
514
|
});
|
|
518
515
|
}
|
|
519
516
|
}
|
|
520
|
-
/**
|
|
517
|
+
/** gate only when the active signer is an agent lacking canSpotTrade. */
|
|
521
518
|
_requireSpotPermission() {
|
|
522
519
|
const meta = this._perp.activeAgentMeta();
|
|
523
520
|
if (meta !== null && meta.permissions?.canSpotTrade !== true) {
|
|
@@ -95,7 +95,7 @@ export interface DelAgentParams {
|
|
|
95
95
|
/**
|
|
96
96
|
* Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
|
|
97
97
|
*
|
|
98
|
-
* OPEN ITEM (
|
|
98
|
+
* OPEN ITEM (Aster DelAgent struct — mainnet verification): the
|
|
99
99
|
* public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
|
|
100
100
|
* document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
|
|
101
101
|
* revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
|
|
@@ -99,7 +99,7 @@ export function buildApproveAgentTypedData(params) {
|
|
|
99
99
|
/**
|
|
100
100
|
* Build the EIP-712 typed-data payload for `DELETE /fapi/v3/agent`.
|
|
101
101
|
*
|
|
102
|
-
* OPEN ITEM (
|
|
102
|
+
* OPEN ITEM (Aster DelAgent struct — mainnet verification): the
|
|
103
103
|
* public Aster V3 docs (asterdex/api-docs, futures api v3 + testnet, checked 2026-10-02)
|
|
104
104
|
* document no agent-delete endpoint or DelAgent struct, and HypurrQuant_FE has no
|
|
105
105
|
* revoke method. This field set mirrors the ApproveAgent terminal fields (AgentAddress,
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* Docs: https://docs.asterdex.com/product/aster-perpetuals/api/api-documentation
|
|
19
19
|
* Base: https://fapi.asterdex.com
|
|
20
20
|
*/
|
|
21
|
-
import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
|
|
21
|
+
import type { ExchangeAdapter, ExchangeMarketInfo, ExchangePosition, ExchangeOrder, ExchangeBalance, ExchangeTrade, ExchangePublicTrade, ExchangeFundingPayment, ExchangeKline } from "./interface.js";
|
|
22
22
|
import type { ResolvedSlippage } from "./slippage.js";
|
|
23
23
|
import type { EvmSigner } from "../signer/interface.js";
|
|
24
24
|
import type { AgentMeta } from "../settings.js";
|
|
@@ -161,7 +161,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
|
|
|
161
161
|
/** PRICE_FILTER / PERCENT_PRICE of an API symbol (exchangeInfo, cached CACHE_TTL). */
|
|
162
162
|
private _symbolPriceFilters;
|
|
163
163
|
/**
|
|
164
|
-
* Declared protection-price reference
|
|
164
|
+
* Declared protection-price reference: the venue mark price from
|
|
165
165
|
* GET /fapi/v3/premiumIndex — the same price PERCENT_PRICE is evaluated against.
|
|
166
166
|
* No runtime substitute (no mid / last fallback): unavailable → PRICE_STALE.
|
|
167
167
|
*/
|
|
@@ -190,12 +190,17 @@ export declare class AsterAdapter implements ExchangeAdapter {
|
|
|
190
190
|
bids: [string, string][];
|
|
191
191
|
asks: [string, string][];
|
|
192
192
|
}>;
|
|
193
|
-
getRecentTrades(symbol: string, limit?: number): Promise<
|
|
193
|
+
getRecentTrades(symbol: string, limit?: number): Promise<ExchangePublicTrade[]>;
|
|
194
194
|
getFundingHistory(symbol: string, limit?: number): Promise<{
|
|
195
195
|
time: number;
|
|
196
196
|
rate: string;
|
|
197
197
|
price: string | null;
|
|
198
198
|
}[]>;
|
|
199
|
+
/**
|
|
200
|
+
* Candles over [startTime, endTime]. GET /fapi/v3/klines returns at most 1500 bars per request
|
|
201
|
+
* (1501 → -1130), so the range is read in pages that start after the last bar returned — a long
|
|
202
|
+
* range is never cut to the first page. More than ASTER_KLINE_MAX_PAGES pages → INVALID_PARAMS.
|
|
203
|
+
*/
|
|
199
204
|
getKlines(symbol: string, interval: string, startTime: number, endTime: number): Promise<ExchangeKline[]>;
|
|
200
205
|
getBalance(): Promise<ExchangeBalance>;
|
|
201
206
|
/**
|
|
@@ -267,7 +272,7 @@ export declare class AsterAdapter implements ExchangeAdapter {
|
|
|
267
272
|
/**
|
|
268
273
|
* Native modify (PUT /fapi/v3/order, V3 futures docs "Modify Order"): LIMIT orders
|
|
269
274
|
* only; TIF (incl. GTX) and reduceOnly stay on the order. `size` is the NEW UNFILLED
|
|
270
|
-
* quantity
|
|
275
|
+
* quantity; the venue's `quantity` is the order total, so
|
|
271
276
|
* quantity = size + executedQty (read just before). A fill landing between the read
|
|
272
277
|
* and the PUT can only shrink the remainder, never over-size it. A venue rejection
|
|
273
278
|
* leaves the original order untouched (docs).
|