@candledottv/agent-sdk 0.4.6 → 0.4.8

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/dist/client.d.ts CHANGED
@@ -27,6 +27,8 @@
27
27
  * bounded by `maxRetries` (default 3 retries after the initial attempt).
28
28
  */
29
29
  import { type HyperliquidNetwork, type HyperliquidTypedData } from "./hyperliquid";
30
+ import type { HyperliquidPnlSection } from "./hyperliquid-pnl";
31
+ import type { AgentPlansResult, PlanPrice, PlanTable } from "./plans";
30
32
  import type { SecretStore } from "./secret-store";
31
33
  import { type WalletChain } from "./wallet-import";
32
34
  export type Chain = "solana" | "hood";
@@ -225,6 +227,8 @@ export interface ConfirmSelfLaunchResult extends LaunchResult {
225
227
  export interface DryRunResult {
226
228
  success: true;
227
229
  dryRun: true;
230
+ /** Wallet the real launch pays from; null when no wallet is available for the resolved chain. */
231
+ launchWallet: string | null;
228
232
  resolved: {
229
233
  chain: Chain;
230
234
  quoteAsset: string;
@@ -236,9 +240,36 @@ export interface DryRunResult {
236
240
  };
237
241
  checks: {
238
242
  image: string;
239
- exclusiveEligible: boolean;
243
+ /** `"ok"` when a `bannerUrl` was sent and checked; absent otherwise. */
244
+ banner?: string;
245
+ /**
246
+ * Present only for an exclusive (or test-exclusive) mode, the modes that run the Believer
247
+ * check, and then `true`: an ineligible account gets EXCLUSIVE_NOT_ELIGIBLE instead. Absent in
248
+ * any other mode, where nothing was checked.
249
+ */
250
+ exclusiveEligible?: boolean;
240
251
  };
241
252
  matrixVersion: number;
253
+ /**
254
+ * Solana only: the assembled launch transaction's size. Absent on Hood, and when the size
255
+ * computation itself failed transiently. A body that would not fit fails the dry run with
256
+ * TRANSACTION_TOO_LARGE instead, so `fits` is always true when present.
257
+ */
258
+ size?: {
259
+ txBytes: number;
260
+ limit: number;
261
+ maxNameBytes: number;
262
+ fits: boolean;
263
+ };
264
+ }
265
+ /**
266
+ * POST /api/v1/launch/self/dry-run response: the headless dry run's shape, with `launchWallet` the
267
+ * linked or TEE wallet `buildSelfLaunch()` would pay from, and `launchWalletId` its id. Never
268
+ * checks that wallet's balance.
269
+ */
270
+ export interface SelfLaunchDryRunResult extends Omit<DryRunResult, "launchWallet"> {
271
+ launchWallet: string;
272
+ launchWalletId: string;
242
273
  }
243
274
  /** POST /api/v1/launch/headless blocking (or replayed) success response. */
244
275
  export interface LaunchResult {
@@ -409,21 +440,30 @@ export interface AgentProfile {
409
440
  */
410
441
  export interface AgentTierInfo {
411
442
  success: true;
412
- /** Display tier: max > pro > believer > free. */
443
+ /**
444
+ * Display tier: max > pro > believer > free. From the three-plan launch the server sends only
445
+ * `free`, `pro` or `max`; `believer` stays in this type for one release after it, then goes.
446
+ */
413
447
  tier: "free" | "believer" | "pro" | "max";
414
448
  /** Live-evaluated tier, independent of the Believer key-issuance label. */
415
449
  liveTier: "free" | "pro" | "max";
416
450
  stakedCndl: number;
417
451
  heldCndl: number;
452
+ /** `graceMs` is 0 from the three-plan launch: Pro through CNDL then has no grace window. */
418
453
  thresholds: {
419
454
  minStakedCndl: number;
420
455
  minHeldCndl: number;
421
456
  graceMs: number;
422
457
  };
423
- /** `startedAt` is null unless `active` (see the endpoint's own doc for why). */
458
+ /**
459
+ * `startedAt` is null unless `active` (see the endpoint's own doc for why). `endsAt` is the
460
+ * server's deadline for an open window; absent from an older server. Never active from the
461
+ * three-plan launch.
462
+ */
424
463
  grace: {
425
464
  active: boolean;
426
465
  startedAt: number | null;
466
+ endsAt?: number | null;
427
467
  };
428
468
  maxTierExpiresAt: number | null;
429
469
  /**
@@ -435,8 +475,12 @@ export interface AgentTierInfo {
435
475
  maxExpired: boolean;
436
476
  /** When the lapsed grant ended (ms). Present only when `maxExpired`. */
437
477
  maxExpiredAt?: number;
438
- /** Which kind of grant lapsed. Present only when `maxExpired`. */
439
- maxExpiredSource?: "subscription" | "trial" | "team";
478
+ /**
479
+ * Which kind of grant lapsed. Present only when `maxExpired`. `"promo"` is the Max that came free
480
+ * with a first Pro purchase; while the account still pays for Pro, that lapse is not reported.
481
+ * Treat an unknown value as a generic Max expiry.
482
+ */
483
+ maxExpiredSource?: "subscription" | "trial" | "team" | "promo";
440
484
  /**
441
485
  * The server's own sentence about the lapse, dated, with the renewal link. Relay it verbatim:
442
486
  * it is the same copy the CLI doctor row, the MCP notice, and the tier refusals use, so every
@@ -453,6 +497,21 @@ export interface AgentTierInfo {
453
497
  feeRawSum: string;
454
498
  count: number;
455
499
  }>;
500
+ /** The live tier's cap floors. Absent from an older server. */
501
+ tierCaps?: {
502
+ rateLimitPerMin: number;
503
+ dailyLaunchCap: number;
504
+ uploadsPerMin: number;
505
+ linkedWallets: number;
506
+ };
507
+ /** When the tier was evaluated (ms), so a caller can say how fresh it is. Absent from an older server. */
508
+ checkedAt?: number;
509
+ /** Max's price. Kept beside `planTable` for compatibility; read `planTable` for every plan. */
510
+ maxPricing?: PlanPrice;
511
+ /** Pro's price, null while Pro is not sold. Absent from a server before the plan table. */
512
+ proPricing?: PlanPrice | null;
513
+ /** The plan table in force, the same one `getPlans()` returns. Absent from an older server. */
514
+ planTable?: PlanTable;
456
515
  }
457
516
  /**
458
517
  * One per-transaction spend cap, mirroring `SpendLimit` in `apps/api/src/lib/agent-policy.ts`
@@ -487,22 +546,46 @@ export interface ImportWalletResult {
487
546
  privyWalletId: string;
488
547
  }
489
548
  /**
490
- * One row of `GET /api/v1/agent/wallets`'s `page` array: the linkedWallets Convex row minus
491
- * internal bookkeeping fields (userAddress/addressLower/privyWalletId/verifiedAt) a caller has
492
- * no use for. `privyPolicyId` present is what makes a row spend-capable (the import flow); its
493
- * absence means attribution-only (link-existing). `revokedAt` set means the row is a
494
- * tombstone -- `listWallets()` excludes these by default; pass `includeRevoked: true` to see
495
- * them.
549
+ * What a linked wallet can do, decided by the server (BE-860): `tee`, a TEE wallet bound to one
550
+ * key; `imported`, a spend-capable wallet from the import flow; `linked`, attribution-only, which
551
+ * cannot sign. Not `SelfWallet.kind`, whose `linked` covers both of the last two.
552
+ */
553
+ export type WalletKind = "tee" | "imported" | "linked";
554
+ /**
555
+ * One row of `GET /api/v1/agent/wallets`'s `page` array. The server returns the whole linkedWallets
556
+ * row, so a page also carries fields this type does not name (`userAddress`, `addressLower`,
557
+ * `verifiedAt` and others); the type names the ones a caller acts on. Branch on `walletKind` for
558
+ * what a row can do. `revokedAt` set means the row is a tombstone -- `listWallets()` excludes these
559
+ * by default; pass `includeRevoked: true` to see them.
496
560
  */
497
561
  export interface LinkedWalletRow {
498
562
  _id: string;
499
563
  chain: WalletChain;
500
564
  address: string;
565
+ /** The wallet's Privy id: what `selfLaunch()`, `trade()` and `launchAtomic()` sign a linked leg with. */
566
+ privyWalletId: string;
501
567
  label?: string;
502
568
  privyPolicyId?: string;
503
569
  signerQuorumId?: string;
504
570
  revokedAt?: number;
505
571
  addedVia: "agent" | "session";
572
+ /**
573
+ * What this wallet can do: `tee`, `imported` (spend-capable) or `linked` (attribution-only).
574
+ * Stable; derived by the server. Absent only from an API that predates it (before 2026-10), where
575
+ * `privyPolicyId` present meant spend-capable and its absence attribution-only.
576
+ */
577
+ walletKind?: WalletKind;
578
+ /**
579
+ * Served, but its values are internal code names and not promised (today `"ember-tee"`, or the
580
+ * legacy `"ember-hot"`, on a TEE wallet; absent on every other row). Use `walletKind`.
581
+ */
582
+ profile?: "ember-tee" | "ember-hot";
583
+ /**
584
+ * TEE wallets only: whether the account owner has allowed this wallet to pay for a launch.
585
+ * Absent reads as false. Only the owner can change it (`PUT /api/v1/agent/wallets/:id/capabilities`
586
+ * with a device token or session; the CLI's `candle wallets allow-launch`).
587
+ */
588
+ allowLaunch?: boolean;
506
589
  }
507
590
  /** GET /api/v1/agent/wallets response: one page of the account's linked wallets. */
508
591
  export interface ListWalletsResult {
@@ -548,13 +631,70 @@ export interface ProfileOpenPosition {
548
631
  unrealizedUsd?: number;
549
632
  /** The chain this position was traded on. Optional: a server that predates it omits it. */
550
633
  chain?: Chain;
634
+ /**
635
+ * The wallet holding it: positions live in wallets, so one token held in two wallets is two
636
+ * positions. `unknown:solana` or `unknown:hood` names the pool for fills no record places in a
637
+ * wallet, which is not an address. Optional: a server that predates 2026-10-02 omits it.
638
+ */
639
+ wallet?: string;
640
+ /**
641
+ * The key this position belongs to, by prefix: the wallet's bound key, else the key whose buy
642
+ * opened it; null for Manual (web-app trades). Optional: a server that predates 2026-10-02 omits it.
643
+ */
644
+ agent?: string | null;
645
+ /** When the round behind this position opened, epoch ms. Optional, as `wallet`. */
646
+ openedTs?: number;
647
+ /** Why there is no mark. Present exactly when `markPriceUsd` is absent, on a server that sends it. */
648
+ unpricedReason?: "no-market-row" | "unusable-price";
649
+ /**
650
+ * Worth under one cent at its mark. Still listed and still counted; `openPositionsExDust` leaves it
651
+ * out. An unpriced position is never dust. Optional: a server that predates 2026-10-02 omits it.
652
+ */
653
+ dust?: true;
654
+ }
655
+ /**
656
+ * Closed positions as one equation (P&L spec PNL-ED-8): `madeUsd + lostUsd + partialSellsUsd`
657
+ * equals the scope's `realizedNetUsd`. A position is closed when its wallet's quantity returns to
658
+ * zero through a sale.
659
+ */
660
+ export interface ProfileClosedSummary {
661
+ /** Closed positions, those with unknown cost included. */
662
+ closed: number;
663
+ /** Sum of the closed positions that made money, USD. */
664
+ madeUsd: number;
665
+ /** Sum of the closed positions that lost money, USD: zero or negative. */
666
+ lostUsd: number;
667
+ /**
668
+ * The rest of the realized net: partial sells of positions still open, and fees not in a closed
669
+ * position (a buy fee on an open position, a sell with nothing open).
670
+ */
671
+ partialSellsUsd: number;
672
+ /** Closed positions won and lost, leaving out those with unknown cost. */
673
+ wins: number;
674
+ losses: number;
675
+ /** Closed positions with unknown cost: listed in `closed`, left out of `wins` and `losses`. */
676
+ costUnknown: number;
677
+ }
678
+ /**
679
+ * Fields every scope of `ProfilePnlResult` gained on 2026-10-02 (the total, each `byChain` entry
680
+ * and each `byWallet` row). Each is optional: a server that predates it omits it.
681
+ */
682
+ export interface ProfilePnlEngineFields {
683
+ /** Realized net plus unrealized: the figure the console labels P&L, to the cent. */
684
+ totalUsd?: number;
685
+ /** Open positions that are not dust. */
686
+ openPositionsExDust?: number;
687
+ /** Closed positions this scope's sales closed. */
688
+ closedRounds?: number;
689
+ /** Money made, minus money lost, plus partial sells, equals `realizedNetUsd`. */
690
+ closed?: ProfileClosedSummary;
551
691
  }
552
692
  /**
553
693
  * One chain's share of a profile's P&L (`ProfilePnlResult.pnl.byChain`): the total's figures over
554
694
  * that chain's fills alone. `openPositions` is a COUNT here; the positions themselves are in
555
695
  * `pnl.openPositions`, each carrying its `chain`.
556
696
  */
557
- export interface ProfileChainPnl {
697
+ export interface ProfileChainPnl extends ProfilePnlEngineFields {
558
698
  realizedGrossUsd: number;
559
699
  feesUsd: number;
560
700
  realizedNetUsd: number;
@@ -575,7 +715,7 @@ export interface ProfileChainPnl {
575
715
  measured: number;
576
716
  unmeasured: number;
577
717
  };
578
- /** Confirmed trades on this chain in the window. */
718
+ /** This key's ledger fills on this chain in the window. */
579
719
  tradesConsidered: number;
580
720
  }
581
721
  /**
@@ -586,11 +726,27 @@ export interface ProfileChainPnl {
586
726
  * that could be marked. A position with no price is counted in `unmarkedPositions` rather than
587
727
  * valued at zero, and `oldestMarkAt` says how old the marks are, so a stale figure is visible.
588
728
  * Deposits and withdrawals are excluded entirely: funding a wallet is not trading profit.
729
+ *
730
+ * Since 2026-10-02 (P&L spec R2) the figures are this key's share of the account's one P&L read,
731
+ * the read the console, the dashboard, `/books` and `/keys/pnl` share, so they agree with the
732
+ * console to the cent for the same moment:
733
+ * - realized and fees are on the fills this key placed; an open position belongs to the wallet's
734
+ * bound key, else to the key whose buy opened it; a closed position to the key whose sale closed it;
735
+ * - each wallet is its own average-cost pool, and the total is the sum of `byWallet`
736
+ * (it used to pool every wallet of the key);
737
+ * - a recorded move between two of the account's wallets carries its cost and realizes nothing;
738
+ * tokens that arrive with no cost anyone can state realize nothing when sold;
739
+ * - `openPositions` counts one per wallet and token, dust included;
740
+ * - `tradesConsidered` counts this key's ledger fills, and `lookback` / `truncated` are the
741
+ * account's activity bound, not 500 of this key's trades.
742
+ * Every account's realized figure can move on the day a server ships this.
589
743
  */
590
744
  export interface ProfilePnlResult {
745
+ /** Optional while Hyperliquid is enabled; separate from spot totals. */
746
+ hyperliquid?: HyperliquidPnlSection;
591
747
  success: true;
592
748
  keyPrefix: string;
593
- pnl: {
749
+ pnl: ProfilePnlEngineFields & {
594
750
  realizedGrossUsd: number;
595
751
  /** Candle fees over the counted fills. Reported separately, netted only into realizedNetUsd. */
596
752
  feesUsd: number;
@@ -609,32 +765,51 @@ export interface ProfilePnlResult {
609
765
  /** Fills counted, and fills that had no trusted USD price and so were left out entirely. */
610
766
  counted: number;
611
767
  unvalued: number;
768
+ /** Fills held out because their token has a fill of unknown size. Part of `unvalued`. Optional. */
769
+ unresolved?: number;
770
+ /** The tokens those fills belong to: their P&L is unknown, not zero. Optional. */
771
+ unresolvedMints?: string[];
772
+ /** Fees and measured slippage, reported and never netted a second time. Optional. */
773
+ friction?: {
774
+ feesUsd: number;
775
+ slippageUsd: number;
776
+ slippageBpsAvg?: number;
777
+ measured: number;
778
+ unmeasured: number;
779
+ };
780
+ /** This key's ledger fills in the window. */
612
781
  tradesConsidered: number;
782
+ /** The account's activity bound, shared by every private P&L read (it was 500 of this key's trades). */
613
783
  lookback: number;
614
784
  /** True when the lookback window was full, so this is not a lifetime figure. */
615
785
  truncated: boolean;
616
786
  /**
617
- * The same fills divided by the wallet that paid for each trade, ordered by
618
- * `tradesConsidered` then address. Optional: a server that predates it omits it.
787
+ * The same figures divided by wallet, ordered by `tradesConsidered` then address. Optional: a
788
+ * server that predates it omits it.
619
789
  *
620
- * Each row is an independent average-cost pool over its own fills, so the rows need not sum to
621
- * the total above, which pools all fills and stays correct. A token bought in one wallet and
622
- * sold from another leaves the buyer holding it and the seller with a sale that realizes
623
- * nothing; and even with no transfer, A buying 100 X for $100, B buying 100 X for $200 and A
624
- * selling 100 X for $300 realizes $150 in total but $200 summed over the wallets.
790
+ * Each wallet is its own average-cost pool, and the total above is the sum of its wallets: A
791
+ * buying 100 X for $100, B buying 100 X for $200 and A selling 100 X for $300 realizes $200.
792
+ * (Before 2026-10-02 the total pooled every wallet and realized $150 here.) A token moved
793
+ * between two of the account's wallets carries its cost once the move is recorded; until then
794
+ * the buyer still holds it and the seller's sale realizes nothing.
625
795
  */
626
796
  byWallet?: ProfileWalletPnl[];
627
797
  /**
628
- * The same figures split by the chain each trade was on, both chains always present. Each is
629
- * its own average-cost pool, so the two need not sum exactly to the total above, for the
630
- * reason `byWallet` rows need not. Optional: a server that predates it omits it.
798
+ * The same figures split by chain, both chains always present. A token lives on one chain, so
799
+ * the two sum to the total above. Optional: a server that predates it omits it.
631
800
  */
632
801
  byChain?: Record<Chain, ProfileChainPnl>;
633
802
  };
634
803
  }
635
- /** One row of `ProfilePnlResult.pnl.byWallet`: one paying wallet's share of a profile's P&L. */
636
- export interface ProfileWalletPnl {
637
- /** The paying wallet's address as stored: base58, or EIP-55 on Hood. */
804
+ /**
805
+ * One row of `ProfilePnlResult.pnl.byWallet`: one wallet's share of a profile's P&L. A wallet two
806
+ * keys trade carries this key's share only.
807
+ */
808
+ export interface ProfileWalletPnl extends ProfilePnlEngineFields {
809
+ /**
810
+ * The wallet's address as stored: base58, or EIP-55 on Hood. `unknown:solana` or `unknown:hood`
811
+ * is the pool for fills no record places in a wallet: a row, not an address.
812
+ */
638
813
  wallet: string;
639
814
  payerType: "main" | "linked";
640
815
  /**
@@ -668,7 +843,7 @@ export interface ProfileWalletPnl {
668
843
  measured: number;
669
844
  unmeasured: number;
670
845
  };
671
- /** Confirmed trades in the window this wallet paid for. */
846
+ /** This key's ledger fills in the window from this wallet. */
672
847
  tradesConsidered: number;
673
848
  }
674
849
  /**
@@ -775,8 +950,9 @@ export interface PortfolioHoodSection {
775
950
  *
776
951
  * `prices` keys a Solana mint by its address, Hood native ETH as `hood:native`, and a Hood token
777
952
  * as `hood:<lowercased contract>`, so lowercase a Hood `mint` before the lookup. Read `complete`
778
- * before quoting a total: it is false when the wallet list was cut off or any wallet's read failed
779
- * on either chain.
953
+ * before quoting a total: it is false when the wallet list was cut off, any wallet's read failed
954
+ * on either chain, or an LP position could not be read. `walletsComplete` is the list on its own.
955
+ * Absent on a server that predates it, in which case `complete: false` may be either cause.
780
956
  *
781
957
  * Not typed here: the `lp` section a deployment with LP enabled adds.
782
958
  */
@@ -790,6 +966,11 @@ export interface PortfolioResult {
790
966
  /** Solana addresses whose read failed. Hood's are in `hood.unavailable`. */
791
967
  unavailable: string[];
792
968
  complete: boolean;
969
+ /**
970
+ * Whether every wallet Candle knows was listed. False only when that list was cut off.
971
+ * Independent of `complete`. Absent on a server that predates the field.
972
+ */
973
+ walletsComplete?: boolean;
793
974
  }
794
975
  /**
795
976
  * One row of a profile's trade history: what was ordered, what actually filled, what it cost,
@@ -813,7 +994,26 @@ export interface ProfileTradeRow {
813
994
  filledAmount?: number;
814
995
  usdValue?: number;
815
996
  feeBps: number;
997
+ /**
998
+ * An estimate from the trade's size and rate, scaled by collected over planned fee. 0 when no fee
999
+ * was collected, including when the plan forgoes it.
1000
+ */
816
1001
  feeUsd?: number;
1002
+ /**
1003
+ * The fee the build planned, in raw units of `quoteAsset`: every venue pays its fee in the quote
1004
+ * asset. Absent on a server before 2026-10-05.
1005
+ */
1006
+ feeRaw?: string;
1007
+ /**
1008
+ * What the treasury received, in raw units of `quoteAsset`. Confirmed rows only. Equal to
1009
+ * `feeRaw` unless it was measured otherwise.
1010
+ */
1011
+ feeCollectedRaw?: string;
1012
+ /**
1013
+ * True for a `built` row that holds a signature: the trade is on chain but was not booked.
1014
+ * `errorCode` says why. Absent on a server before 2026-10-05.
1015
+ */
1016
+ landedUnconfirmed?: boolean;
817
1017
  payerWallet: string;
818
1018
  venue?: "curve" | "jupiter" | "dex";
819
1019
  signature?: string;
@@ -824,6 +1024,22 @@ export interface ProfileTradesResult {
824
1024
  success: true;
825
1025
  keyPrefix: string;
826
1026
  trades: ProfileTradeRow[];
1027
+ /**
1028
+ * Pass back as `cursor` for the next, older page. Present whenever the page read a full `limit`,
1029
+ * so a short or even empty page can still have one: only its absence means the end.
1030
+ */
1031
+ nextCursor?: string;
1032
+ }
1033
+ /** Options for `getProfileTrades`. */
1034
+ export interface ProfileTradesOptions {
1035
+ /** Rows to read, 1 to 1,000. Default 200. */
1036
+ limit?: number;
1037
+ /** Inclusive lower bound on `createdAt`: an ISO 8601 string, epoch milliseconds, or a `Date`. */
1038
+ since?: string | number | Date;
1039
+ /** Exclusive upper bound on `createdAt`, in the same forms as `since`. */
1040
+ until?: string | number | Date;
1041
+ /** A previous page's `nextCursor`, verbatim. */
1042
+ cursor?: string;
827
1043
  }
828
1044
  /** `GET /api/v1/agent/keys/{prefix}/wallets` response. */
829
1045
  export interface ProfileWalletsResult {
@@ -845,6 +1061,27 @@ export type TradePayer = {
845
1061
  type: "linked";
846
1062
  linkedWalletId: string;
847
1063
  };
1064
+ /**
1065
+ * The Jupiter/DFlow race one Solana `jupiter`-venue build ran. Raw amounts and lamports are decimal
1066
+ * strings. Present only while DFlow is enabled on the deployment, and never on paper or a replay.
1067
+ */
1068
+ export interface TradeRace {
1069
+ jupiterOutRaw: string;
1070
+ /** DFlow's quoted output, when it gave an accepted quote. */
1071
+ dflowOutRaw?: string;
1072
+ /**
1073
+ * Why DFlow did not build the transaction: `quote:<reason>`, `build:<reason>` (including
1074
+ * `build:priority_fee_over_cap`), or `net:fee_exceeds_edge` when its larger output did not
1075
+ * cover its larger priority fee.
1076
+ */
1077
+ dflowRefusal?: string;
1078
+ /** The priority-fee ceiling both builds were given, in lamports. Absent from an older server. */
1079
+ priorityFeeCapLamports?: string;
1080
+ /** The priority fee decoded from Jupiter's built transaction. Absent when Jupiter built none. */
1081
+ jupiterPriorityFeeLamports?: string;
1082
+ /** The priority fee decoded from DFlow's built transaction. Absent when DFlow returned none. */
1083
+ dflowPriorityFeeLamports?: string;
1084
+ }
848
1085
  /** POST /api/v1/trade/agent/build request body. */
849
1086
  export interface BuildTradeRequest {
850
1087
  /** Idempotency key, unique per account; shared with the matching confirmTrade() call. */
@@ -856,6 +1093,18 @@ export interface BuildTradeRequest {
856
1093
  payer: TradePayer;
857
1094
  /** Bps, 0-10000. Server defaults to 100 (1%) when omitted. */
858
1095
  maxSlippageBps?: number;
1096
+ /**
1097
+ * The most this build may bid as a Solana priority fee, in lamports: an integer from 0 to
1098
+ * 10,000,000. Replaces the default ceiling of 25 bps of the trade's SOL leg (floored at 100,000,
1099
+ * capped at 10,000,000), so it can raise the ceiling for a small trade that has to land as well
1100
+ * as lower it. `0` asks for no priority fee, and is not the same as omitting the field.
1101
+ *
1102
+ * Applies to Solana `jupiter`-venue builds and is ignored everywhere else (Hood, the curve
1103
+ * venue, paper). A hard limit on DFlow; a requested limit on Jupiter, whose paid figure is
1104
+ * `race.jupiterPriorityFeeLamports` when the response carries `race`. A very low value may not
1105
+ * land before its blockhash expires.
1106
+ */
1107
+ maxPriorityFeeLamports?: number;
859
1108
  /**
860
1109
  * What the wallet spends on a buy, or receives on a sell. Safe to pass straight through from a
861
1110
  * `POST /trade/agent/quote` response: the two endpoints take the same ids.
@@ -906,6 +1155,17 @@ export interface TradeFee {
906
1155
  /** Solana "built" artifacts: one unsigned transaction, the fee (if any) already embedded inside it. */
907
1156
  export interface SolanaTradeArtifacts {
908
1157
  venue: "curve" | "jupiter";
1158
+ /**
1159
+ * Which quoter built the transaction. On the `jupiter` venue Candle also asks DFlow for a quote and
1160
+ * uses it only when its output is strictly larger: net of each venue's priority fee when a leg is
1161
+ * SOL, raw otherwise. Otherwise this is `jupiter`. `curve` on the curve venue.
1162
+ */
1163
+ quoteSource?: "curve" | "jupiter" | "dflow";
1164
+ /**
1165
+ * The Jupiter/DFlow race on a `jupiter` venue build: Jupiter's quoted output, DFlow's when it gave an
1166
+ * accepted quote, and why DFlow did not build the transaction when it did not. Absent on the curve venue.
1167
+ */
1168
+ race?: TradeRace;
909
1169
  transactionBase64: string;
910
1170
  quoteAsset: string;
911
1171
  quoteMint: string;
@@ -1062,6 +1322,12 @@ export interface ExecutedTradeResult {
1062
1322
  * server had already read. Present on the executed response since 2026-09-04.
1063
1323
  */
1064
1324
  route?: TradeRoute;
1325
+ /**
1326
+ * Solana `jupiter` venue only: which quoter built the transaction that executed (`jupiter` or `dflow`),
1327
+ * and the Jupiter/DFlow race behind it. Absent on the curve venue, on Hood, and on an idempotent replay.
1328
+ */
1329
+ quoteSource?: "jupiter" | "dflow";
1330
+ race?: TradeRace;
1065
1331
  }
1066
1332
  /** POST /api/v1/trade/agent/build response: "built" for a linked payer, "executed" for a main payer (or an idempotent replay of an already-confirmed trade under the same clientTradeId). */
1067
1333
  export type BuildTradeResult = BuildTradeBuiltResult | ExecutedTradeResult;
@@ -1332,6 +1598,89 @@ export interface PerpsOrders {
1332
1598
  releasedUsdMicros: number;
1333
1599
  }[];
1334
1600
  }
1601
+ /**
1602
+ * Perps C (BE-647, HL-ED-8): `perpsDeposit()`. Relay moves funds from the key's Hood or Solana TEE
1603
+ * wallet onto Hyperliquid perps USDC at the key's EVM TEE wallet's own address. The asset decides
1604
+ * the paying chain: SOL or USDC from the Solana TEE wallet, ETH or USDG from the Hood one. Needs
1605
+ * `swap:write` and a raw cap on the asset. There is no withdrawal yet.
1606
+ */
1607
+ export interface PerpsDepositParams {
1608
+ /** Idempotency id, 1 to 128 of `A-Za-z0-9._:-`. Rebuilding under the same id answers its job. */
1609
+ clientDepositId: string;
1610
+ asset: "SOL" | "USDC" | "ETH" | "USDG";
1611
+ /** Raw base units of `asset`, as a decimal string. */
1612
+ amountRaw: string;
1613
+ /** The paying TEE wallet's row id (the relay's :id, and the secretStore key). */
1614
+ walletId: string;
1615
+ /** The paying wallet's Privy wallet id. */
1616
+ privyWalletId: string;
1617
+ /** The Hyperliquid account: the EVM TEE wallet's address. The build is refused if it names another. */
1618
+ account: string;
1619
+ /** From Solana only: the EVM TEE wallet whose Hyperliquid account receives. Omit from Hood. */
1620
+ perpsWalletId?: string;
1621
+ /** Relay slippage, 1 to 1000 bps (default 100). */
1622
+ maxSlippageBps?: number;
1623
+ /** Sign and submit (default), or stop after the build and its check. */
1624
+ submit?: boolean;
1625
+ }
1626
+ /** What `POST /agent/perps/deposit` builds. A Hood build also carries the first sequenced leg. */
1627
+ export interface PerpsDepositBuild {
1628
+ success: true;
1629
+ status: "built";
1630
+ clientDepositId: string;
1631
+ depositId: string;
1632
+ chain: "solana" | "hood";
1633
+ venue: "relay";
1634
+ network: HyperliquidNetwork;
1635
+ asset: PerpsDepositParams["asset"];
1636
+ amountRaw: string;
1637
+ walletId: string;
1638
+ walletAddress: string;
1639
+ destination: {
1640
+ walletId: string;
1641
+ address: string;
1642
+ chainId: number;
1643
+ currency: string;
1644
+ };
1645
+ firstDeposit: boolean;
1646
+ expectedOutRaw: string;
1647
+ minimumOutRaw: string;
1648
+ outDecimals: number;
1649
+ floorUsdcMicros: string;
1650
+ minimumCreditUsdcMicros: string;
1651
+ fee: {
1652
+ bps: number;
1653
+ feeRaw: string;
1654
+ };
1655
+ statusChecks: string[];
1656
+ requestId: string | null;
1657
+ expiresAt: number;
1658
+ /** Solana: the one unsigned deposit. */
1659
+ transactionsBase64?: string[];
1660
+ /** Hood: the sequenced leg protocol's first body. */
1661
+ mode?: "sequenced";
1662
+ operationId?: string;
1663
+ legKind?: string;
1664
+ plannedLegCount?: number;
1665
+ nextLeg?: {
1666
+ chainId: number;
1667
+ nonce: number;
1668
+ gas: string;
1669
+ maxFeePerGas: string;
1670
+ maxPriorityFeePerGas: string;
1671
+ to: string;
1672
+ data: string;
1673
+ value: string;
1674
+ };
1675
+ }
1676
+ export interface PerpsDepositResult {
1677
+ build: PerpsDepositBuild;
1678
+ submitted: boolean;
1679
+ /** `/perps/deposit/submit`'s final answer: `status: "submitted"` and the chain hashes. */
1680
+ result: Record<string, unknown> | null;
1681
+ }
1682
+ /** Why a deposit build must not be signed, or null. */
1683
+ export declare function perpsDepositProblem(build: PerpsDepositBuild, params: PerpsDepositParams): string | null;
1335
1684
  /**
1336
1685
  * The base assets `swap()` converts between. Inlined rather than imported from `@candle/shared`'s
1337
1686
  * `BaseAssetKey`, for the same reason `packages/mcp` inlines its curve constants: this SDK is
@@ -1762,6 +2111,14 @@ export declare class CandleClient {
1762
2111
  * with (possibly none) and lets the server's own auth middleware decide.
1763
2112
  */
1764
2113
  getAgentTier(): Promise<AgentTierInfo>;
2114
+ /**
2115
+ * The plan table in force on this deployment (`GET /api/v1/agent/plans`, no credential): each
2116
+ * plan's price, agent fee, perps builder fee, the limits a new key gets, what it can do
2117
+ * (`capabilities`), and `promoMaxDays`. Quote prices and fees from here rather than hard-coding
2118
+ * them: they differ by deployment and change at the three-plan launch. `planTableRows()` renders
2119
+ * it. A server that predates the table answers 404 (`CandleApiError`).
2120
+ */
2121
+ getPlans(): Promise<AgentPlansResult>;
1765
2122
  dryRunLaunch(req: LaunchRequest): Promise<DryRunResult>;
1766
2123
  /**
1767
2124
  * Blocking launch with idempotent retries. Generates `clientLaunchId` when absent and
@@ -1816,15 +2173,21 @@ export declare class CandleClient {
1816
2173
  * Includes FAILED trades, deliberately: a record that dropped them would misrepresent what the
1817
2174
  * agent did, and `errorCode` is how you find out why one did not go through. For a spreadsheet
1818
2175
  * instead of JSON, request the same path with `?format=csv`.
2176
+ *
2177
+ * Newest first. Narrow by `since` / `until` and page by passing `nextCursor` back as `cursor`
2178
+ * until it is absent; a short page is not the end.
1819
2179
  */
1820
- getProfileTrades(keyPrefix: string, opts?: {
1821
- limit?: number;
1822
- }): Promise<ProfileTradesResult>;
2180
+ getProfileTrades(keyPrefix: string, opts?: ProfileTradesOptions): Promise<ProfileTradesResult>;
1823
2181
  /**
1824
2182
  * One profile's realized P&L, fees, and open positions marked at current prices
1825
2183
  * (GET /api/v1/agent/keys/{prefix}/pnl). Read `unrealizedUsd` with `unmarkedPositions` and
1826
2184
  * `oldestMarkAt`: an unpriced position is counted there, never valued at zero.
1827
2185
  *
2186
+ * The figures are the key's share of the account's one P&L read, the console's figures to the
2187
+ * cent (`pnl.totalUsd` is the console's P&L). Since 2026-10-02 the total is the sum of the key's
2188
+ * wallets, not one pool across them, and `lookback` is the account's activity bound; see
2189
+ * `ProfilePnlResult` for every meaning that changed.
2190
+ *
1828
2191
  * Check `unvalued` and `truncated` before quoting the number: the first counts fills that had
1829
2192
  * no trusted USD price and were left out rather than counted as zero, the second says the
1830
2193
  * lookback window was full and this is not a lifetime figure.
@@ -1944,6 +2307,14 @@ export declare class CandleClient {
1944
2307
  signerPublicKey: string;
1945
2308
  label?: string;
1946
2309
  }): Promise<ImportWalletResult>;
2310
+ /**
2311
+ * Self-signed launch dry run: the same body as `buildSelfLaunch()`, the same checks (payer and
2312
+ * TEE rules, plan, the key's caps), and the same refusals, without building, reserving or
2313
+ * recording anything; the `clientLaunchId` stays unused. Does not check the payer's balance, the
2314
+ * day cap, a `clientLaunchId` already used with another body or payer, or a Solana TEE wallet's
2315
+ * USD spend window; `buildSelfLaunch()` can still refuse for those.
2316
+ */
2317
+ dryRunSelfLaunch(req: BuildSelfLaunchRequest): Promise<SelfLaunchDryRunResult>;
1947
2318
  /**
1948
2319
  * Self-signed launch build: returns an unsigned transaction for the agent to sign and
1949
2320
  * broadcast itself. Candle never signs and never holds the signer key. Signing a linked wallet
@@ -2124,8 +2495,9 @@ export declare class CandleClient {
2124
2495
  * Signs, broadcasts, and waits for its receipt, then -- when the build carried a `feeTransfer`
2125
2496
  * leg (a platform fee applies) -- does that leg next at `nonce + 1` and captures `feeTxHash`.
2126
2497
  * Requires `evmRpcUrl`; throws a clear error naming it when unset, before any signing. Does NOT
2127
- * send a dev buy: a Hood self-launch's dev buy runs out-of-band, server-side, after confirm --
2128
- * the build response never includes a dev-buy leg, and this method does not assemble one.
2498
+ * send a dev buy: a Hood self-launch's dev buy is a separate transaction the caller sends itself
2499
+ * and reports to `confirmSelfLaunch` as `devBuySignature`. The build response never includes a
2500
+ * dev-buy leg, and this method does not assemble one.
2129
2501
  */
2130
2502
  selfLaunch(req: SelfLaunchRequest): Promise<ConfirmSelfLaunchResult>;
2131
2503
  /**
@@ -2190,8 +2562,13 @@ export declare class CandleClient {
2190
2562
  * transaction hash. Shared by trade()'s and selfLaunch()'s Hood branches, both of which must run
2191
2563
  * their legs strictly sequentially -- see trade()'s jsdoc for why a later leg's `estimateGas`
2192
2564
  * depends on an earlier leg already being mined.
2565
+ *
2566
+ * `surfaceLegOutcome` is the fee leg only. A receipt revert, a receipt read that fails, a
2567
+ * receipt timeout, or a broadcast whose result is ambiguous then throws `EvmLegOutcome` with
2568
+ * the hash once it is known. Every other caller gets the original error.
2193
2569
  */
2194
2570
  private signBroadcastAndWaitEvmLeg;
2571
+ private broadcastAndWaitEvmLeg;
2195
2572
  /** The server's perps settings: network, Candle's builder, this key's fee, and its limits. */
2196
2573
  perpsConfig(): Promise<PerpsConfig>;
2197
2574
  /**
@@ -2228,6 +2605,20 @@ export declare class CandleClient {
2228
2605
  startTime: number;
2229
2606
  funding: Record<string, unknown>[];
2230
2607
  }>;
2608
+ /**
2609
+ * Deposit onto the key's Hyperliquid account through Relay (Perps C, HL-ED-8): build, check the
2610
+ * build names `account` on chain 1337 with no Candle fee, then sign through the relay and submit.
2611
+ * From Solana that is one deposit transaction; from Hood each sequenced leg (approve, then the
2612
+ * deposit) is signed and submitted in turn. The fill is Relay's, after the deposit lands: read it
2613
+ * with `perpsDepositStatus()`. Candle checks Relay's steps before it stamps them; `candle perps
2614
+ * deposit` additionally decodes them on the caller's machine.
2615
+ */
2616
+ perpsDeposit(params: PerpsDepositParams): Promise<PerpsDepositResult>;
2617
+ /** A deposit's job: what was built and submitted, the Hood operation, and Relay's fill status. */
2618
+ perpsDepositStatus(clientDepositId: string): Promise<{
2619
+ success: true;
2620
+ job: Record<string, unknown>;
2621
+ }>;
2231
2622
  /** The builder every perps build is checked against (see `hyperliquidBuilder` in the options). */
2232
2623
  private perpsBuilder;
2233
2624
  /**
@@ -2266,8 +2657,13 @@ export declare class CandleClient {
2266
2657
  */
2267
2658
  private jsonRpcCallRaw;
2268
2659
  }
2660
+ /** Test-only. Pass null to restore the production receipt wait. */
2661
+ export declare function __setEvmReceiptWaitForTest(opts: {
2662
+ timeoutMs?: number;
2663
+ pollMs?: number;
2664
+ } | null): void;
2269
2665
  /** This build's own version. Kept in lockstep with package.json by the release-bump CI guard. */
2270
- export declare const SDK_VERSION = "0.4.6";
2666
+ export declare const SDK_VERSION = "0.4.8";
2271
2667
  /** Test seam: the once-per-process latch would otherwise weld the suite's first case to the rest. */
2272
2668
  export declare function __resetSdkUpdateNoticeForTest(): void;
2273
2669
  //# sourceMappingURL=client.d.ts.map