@candledottv/cli 0.11.29 → 0.11.31

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.
Files changed (2) hide show
  1. package/dist/index.js +110 -38
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -8898,10 +8898,12 @@ function createEvmRpc(url, fetchFn) {
8898
8898
  if (r === null || r === undefined)
8899
8899
  return null;
8900
8900
  const status = asQuantity(r.status, "eth_getTransactionReceipt");
8901
+ const logs = (Array.isArray(r.logs) ? r.logs : []).flatMap((log) => typeof log?.address === "string" && Array.isArray(log.topics) && log.topics.every((topic) => typeof topic === "string") ? [{ address: log.address, topics: log.topics }] : []);
8901
8902
  return {
8902
8903
  status: status === 1n ? 1 : 0,
8903
8904
  blockNumber: asQuantity(r.blockNumber, "eth_getTransactionReceipt"),
8904
- transactionHash: typeof r.transactionHash === "string" ? r.transactionHash : hash
8905
+ transactionHash: typeof r.transactionHash === "string" ? r.transactionHash : hash,
8906
+ logs
8905
8907
  };
8906
8908
  },
8907
8909
  async getTransactionByHash(hash) {
@@ -11575,6 +11577,7 @@ async function runSequencedLegs(ctx, key, opts) {
11575
11577
  const signed = await relaySignEvmLeg(ctx, key, opts.wallet, leg);
11576
11578
  signedCount += 1;
11577
11579
  signedKinds.add(current.legKind);
11580
+ opts.onSigned?.(current.legKind, signed.hash);
11578
11581
  if (opts.clientId !== undefined && opts.kind !== undefined)
11579
11582
  await saveOperationHash(ctx, key, opts.clientId, opts.kind, signed.hash, current.operationId);
11580
11583
  const posted = await apiRequest(opts.submitPath, {
@@ -12704,24 +12707,6 @@ function decodeArgs(data, types2, base = 4) {
12704
12707
  return;
12705
12708
  }
12706
12709
  }
12707
- function v2CallOk(data, value, terms) {
12708
- const selector = selectorOf(data);
12709
- if (selector === V2_SWAP_ETH_FOR_TOKENS_SELECTOR) {
12710
- const args = decodeArgs(data, ["uint", ADDRESSES, "address", "uint"]);
12711
- if (!args || terms.inputToken !== undefined)
12712
- return false;
12713
- const path = asList(args[1]);
12714
- return path.length >= 2 && sameEvmAddress(asAddress(path[0]), HOOD_WETH_ADDRESS) && terms.outputToken !== undefined && sameEvmAddress(asAddress(path[path.length - 1]), terms.outputToken) && asNumber(args[0]) >= terms.minOutRaw && sameEvmAddress(asAddress(args[2]), terms.wallet);
12715
- }
12716
- if (selector === V2_SWAP_TOKENS_FOR_ETH_SELECTOR) {
12717
- const args = decodeArgs(data, ["uint", "uint", ADDRESSES, "address", "uint"]);
12718
- if (!args || terms.inputToken === undefined || value !== 0n)
12719
- return false;
12720
- const path = asList(args[2]);
12721
- return asNumber(args[0]) <= terms.amountRaw && asNumber(args[1]) >= terms.minOutRaw && terms.outputToken === undefined && path.length >= 2 && sameEvmAddress(asAddress(path[0]), terms.inputToken) && sameEvmAddress(asAddress(path[path.length - 1]), HOOD_WETH_ADDRESS) && sameEvmAddress(asAddress(args[3]), terms.wallet);
12722
- }
12723
- return false;
12724
- }
12725
12710
  function v3SwapOf(call) {
12726
12711
  const selector = selectorOf(call);
12727
12712
  if (selector === V3_EXACT_INPUT_SINGLE_SELECTOR) {
@@ -12902,9 +12887,7 @@ function kyberCallOk(data, terms) {
12902
12887
  const amount = asNumber(desc[7]);
12903
12888
  return sameEvmAddress(asAddress(desc[0]), terms.inputToken ?? KYBER_NATIVE) && sameEvmAddress(asAddress(desc[1]), terms.outputToken ?? KYBER_NATIVE) && asNumber(desc[8]) >= terms.minOutRaw && sameEvmAddress(asAddress(desc[6]), terms.wallet) && amount === terms.amountRaw && asList(desc[3]).reduce((sum, part) => sum + asNumber(part), 0n) <= amount && asList(desc[4]).length === 0 && asList(desc[5]).every((part) => asNumber(part) === 0n) && asBytes(desc[10]).length === 0;
12904
12889
  }
12905
- function dexCallOk(to, data, value, terms) {
12906
- if (sameEvmAddress(to, HOOD_UNIV2_ROUTER))
12907
- return v2CallOk(data, value, terms);
12890
+ function dexCallOk(to, data, terms) {
12908
12891
  if (sameEvmAddress(to, HOOD_UNIV3_ROUTER))
12909
12892
  return v3CallOk(data, terms);
12910
12893
  if (sameEvmAddress(to, HOOD_V4_UNIVERSAL_ROUTER))
@@ -12952,7 +12935,7 @@ function feeLegOk(leg, fee) {
12952
12935
  return false;
12953
12936
  if (BigInt(leg.value) > fee.cap)
12954
12937
  return false;
12955
- return fee.treasury === undefined || sameEvmAddress(leg.to, fee.treasury);
12938
+ return sameEvmAddress(leg.to, fee.treasury);
12956
12939
  }
12957
12940
  if (leg.value !== "0" || !sameEvmAddress(leg.to, HOOD_USDG_ADDRESS))
12958
12941
  return false;
@@ -12960,7 +12943,37 @@ function feeLegOk(leg, fee) {
12960
12943
  const decoded = data ? decodeErc20Transfer(data) : undefined;
12961
12944
  if (!decoded || decoded.amount > fee.cap)
12962
12945
  return false;
12963
- return fee.treasury === undefined || sameEvmAddress(decoded.recipient, fee.treasury);
12946
+ return sameEvmAddress(decoded.recipient, fee.treasury);
12947
+ }
12948
+ async function hoodFeeTreasury(rpc) {
12949
+ try {
12950
+ const answer = await rpc.call({ to: HOOD_SPLITTER_FACTORY, data: hexToBytes2(SPLITTER_PLATFORM_VAULT_SELECTOR) });
12951
+ const vault = wordAddress2(word2(answer, 0, 0));
12952
+ return vault !== undefined && BigInt(vault) !== 0n ? vault : undefined;
12953
+ } catch {
12954
+ return;
12955
+ }
12956
+ }
12957
+ function curveCreatedBy(receipt, wallet) {
12958
+ if (!receipt || receipt.status !== 1)
12959
+ return;
12960
+ const created = (receipt.logs ?? []).filter((log) => sameEvmAddress(log.address, HOOD_CURVE_FACTORY) && log.topics[0]?.toLowerCase() === CURVE_CREATED_TOPIC);
12961
+ if (created.length !== 1)
12962
+ return;
12963
+ const topics = created[0].topics;
12964
+ const topicAddress = (topic) => {
12965
+ const bytes = topic === undefined ? undefined : bytesOf(topic);
12966
+ return bytes?.length === 32 ? wordAddress2(bytes) : undefined;
12967
+ };
12968
+ const curve = topicAddress(topics[1]);
12969
+ const creator = topicAddress(topics[3]);
12970
+ if (curve === undefined || BigInt(curve) === 0n || creator === undefined)
12971
+ return;
12972
+ return sameEvmAddress(creator, wallet) ? curve : undefined;
12973
+ }
12974
+ function launchBuyLegOk(leg, buyRaw, curve) {
12975
+ const data = bytesOf(leg.data);
12976
+ return data !== undefined && leg.value === buyRaw && sameEvmAddress(leg.to, curve) && data.length === 36 && selectorOf(data) === CURVE_BUY_SELECTOR;
12964
12977
  }
12965
12978
  function hoodTradeLegCheck(terms) {
12966
12979
  let curve;
@@ -12970,6 +12983,13 @@ function hoodTradeLegCheck(terms) {
12970
12983
  }) : Promise.resolve(undefined);
12971
12984
  return curve;
12972
12985
  };
12986
+ let treasury;
12987
+ const chainTreasury = () => {
12988
+ treasury ??= terms.treasury ? terms.treasury().catch(() => {
12989
+ return;
12990
+ }) : Promise.resolve(undefined);
12991
+ return treasury;
12992
+ };
12973
12993
  const spenderOk = async (spender) => {
12974
12994
  if (terms.venue !== "curve")
12975
12995
  return among(spender, DEX_SPENDERS);
@@ -12982,8 +13002,12 @@ function hoodTradeLegCheck(terms) {
12982
13002
  const data = bytesOf(leg.data);
12983
13003
  if (!data)
12984
13004
  return false;
12985
- if (kind === "feeTransfer")
12986
- return terms.fee !== undefined && feeLegOk(leg, terms.fee);
13005
+ if (kind === "feeTransfer") {
13006
+ if (terms.fee === undefined)
13007
+ return false;
13008
+ const named = await chainTreasury();
13009
+ return named !== undefined && feeLegOk(leg, { ...terms.fee, treasury: named });
13010
+ }
12987
13011
  if (kind === "approval") {
12988
13012
  if (terms.inputToken === undefined || leg.value !== "0" || !sameEvmAddress(leg.to, terms.inputToken))
12989
13013
  return false;
@@ -13008,7 +13032,7 @@ function hoodTradeLegCheck(terms) {
13008
13032
  if (terms.inputToken !== undefined ? value !== 0n : value > terms.amountRaw)
13009
13033
  return false;
13010
13034
  if (terms.venue === "dex")
13011
- return dexCallOk(leg.to, data, value, {
13035
+ return dexCallOk(leg.to, data, {
13012
13036
  wallet: terms.wallet,
13013
13037
  ...terms.inputToken !== undefined ? { inputToken: terms.inputToken } : {},
13014
13038
  amountRaw: terms.amountRaw,
@@ -13044,7 +13068,7 @@ async function registeredCurveFor(rpc, token) {
13044
13068
  }
13045
13069
  return;
13046
13070
  }
13047
- var HOOD_CURVE_FACTORY = "0xD08f8489F026957EdeD3Bb8Ef8A9d151A7B1DF22", HOOD_CURVE_REGISTRIES, HOOD_UNIV2_ROUTER = "0x89e5db8b5aa49aa85ac63f691524311aeb649eba", HOOD_UNIV3_ROUTER = "0xCaf681a66D020601342297493863E78C959E5cb2", HOOD_V4_UNIVERSAL_ROUTER = "0x8876789976decbfcbbbe364623c63652db8c0904", HOOD_KYBER_ROUTER = "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", HOOD_PERMIT2 = "0x000000000022D473030F116dDEE9F6B43aC78BA3", HOOD_SPLITTER_FACTORY = "0x9318bD328Ac32DBAe08bbD85B634E6B6B06683BF", KYBER_NATIVE = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", ADDRESS_THIS = "0x0000000000000000000000000000000000000002", DEX_SPENDERS, CREATE_CURVE_SELECTOR = "0xe5ab9610", ERC20_APPROVE_SELECTOR = "0x095ea7b3", PERMIT2_APPROVE_SELECTOR = "0x87517c45", CURVE_BUY_SELECTOR = "0xd96a094a", CURVE_BUY_WITH_QUOTE_SELECTOR = "0x6818735c", CURVE_SELL_SELECTOR = "0xd79875eb", V2_SWAP_ETH_FOR_TOKENS_SELECTOR = "0xb6f9de95", V2_SWAP_TOKENS_FOR_ETH_SELECTOR = "0x791ac947", V3_MULTICALL_SELECTOR = "0x5ae401dc", V3_EXACT_INPUT_SINGLE_SELECTOR = "0x04e45aaf", V3_EXACT_INPUT_SELECTOR = "0xb858183f", V3_UNWRAP_WETH9_SELECTOR = "0x49404b7c", V3_REFUND_ETH_SELECTOR = "0x12210e8a", UNIVERSAL_EXECUTE_SELECTOR = "0x3593564c", KYBER_SWAP_SELECTOR = "0xe21fd0e9", KYBER_SWAP_GENERIC_SELECTOR = "0x59e50fed", KYBER_SWAP_SIMPLE_SELECTOR = "0x8af033fb", SPLITTER_DEV_SELECTOR = "0x91cca3db", SPLITTER_IS_SPLITTER_SELECTOR = "0xa4c597d1", CURVE_FOR_BASE_TOKEN_SELECTOR = "0x446b9253", LAUNCH_FEE_MAX_BPS = 1000n, MAX_ABI_ARRAY = 64, ADDRESSES, V3_SINGLE, V3_PATH, KYBER_DESC, KYBER_EXECUTION, V4_POOL_KEY, V4_SWAP_PARAMS, asBytes = (value) => value, asAddress = (value) => value, asNumber = (value) => value, asList = (value) => value, routedInput = (terms) => terms.inputToken ?? HOOD_WETH_ADDRESS, routedOutput = (terms) => terms.outputToken ?? HOOD_WETH_ADDRESS, UR_V3_SWAP_EXACT_IN = 0, UR_WRAP_ETH = 11, UR_UNWRAP_WETH = 12, UR_V4_SWAP = 16, V4_SWAP_EXACT_IN_SINGLE = 6, V4_SETTLE = 11, V4_SETTLE_ALL = 12, V4_TAKE = 14, V4_TAKE_ALL = 15, NATIVE_CURRENCY = "0x0000000000000000000000000000000000000000";
13071
+ var HOOD_CURVE_FACTORY = "0xD08f8489F026957EdeD3Bb8Ef8A9d151A7B1DF22", HOOD_CURVE_REGISTRIES, HOOD_UNIV3_ROUTER = "0xCaf681a66D020601342297493863E78C959E5cb2", HOOD_V4_UNIVERSAL_ROUTER = "0x8876789976decbfcbbbe364623c63652db8c0904", HOOD_KYBER_ROUTER = "0x6131B5fae19EA4f9D964eAc0408E4408b66337b5", HOOD_PERMIT2 = "0x000000000022D473030F116dDEE9F6B43aC78BA3", HOOD_SPLITTER_FACTORY = "0x9318bD328Ac32DBAe08bbD85B634E6B6B06683BF", KYBER_NATIVE = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE", ADDRESS_THIS = "0x0000000000000000000000000000000000000002", DEX_SPENDERS, CREATE_CURVE_SELECTOR = "0xe5ab9610", ERC20_APPROVE_SELECTOR = "0x095ea7b3", PERMIT2_APPROVE_SELECTOR = "0x87517c45", CURVE_BUY_SELECTOR = "0xd96a094a", CURVE_BUY_WITH_QUOTE_SELECTOR = "0x6818735c", CURVE_SELL_SELECTOR = "0xd79875eb", V3_MULTICALL_SELECTOR = "0x5ae401dc", V3_EXACT_INPUT_SINGLE_SELECTOR = "0x04e45aaf", V3_EXACT_INPUT_SELECTOR = "0xb858183f", V3_UNWRAP_WETH9_SELECTOR = "0x49404b7c", V3_REFUND_ETH_SELECTOR = "0x12210e8a", UNIVERSAL_EXECUTE_SELECTOR = "0x3593564c", KYBER_SWAP_SELECTOR = "0xe21fd0e9", KYBER_SWAP_GENERIC_SELECTOR = "0x59e50fed", KYBER_SWAP_SIMPLE_SELECTOR = "0x8af033fb", SPLITTER_DEV_SELECTOR = "0x91cca3db", SPLITTER_IS_SPLITTER_SELECTOR = "0xa4c597d1", CURVE_FOR_BASE_TOKEN_SELECTOR = "0x446b9253", SPLITTER_PLATFORM_VAULT_SELECTOR = "0x20f094f8", CURVE_CREATED_TOPIC = "0xed3a740542131b3621499825e40efbcaf096e3b1608de865c08a2109378bb36b", LAUNCH_FEE_MAX_BPS = 1000n, MAX_ABI_ARRAY = 64, V3_SINGLE, V3_PATH, KYBER_DESC, KYBER_EXECUTION, V4_POOL_KEY, V4_SWAP_PARAMS, asBytes = (value) => value, asAddress = (value) => value, asNumber = (value) => value, asList = (value) => value, routedInput = (terms) => terms.inputToken ?? HOOD_WETH_ADDRESS, routedOutput = (terms) => terms.outputToken ?? HOOD_WETH_ADDRESS, UR_V3_SWAP_EXACT_IN = 0, UR_WRAP_ETH = 11, UR_UNWRAP_WETH = 12, UR_V4_SWAP = 16, V4_SWAP_EXACT_IN_SINGLE = 6, V4_SETTLE = 11, V4_SETTLE_ALL = 12, V4_TAKE = 14, V4_TAKE_ALL = 15, NATIVE_CURRENCY = "0x0000000000000000000000000000000000000000";
13048
13072
  var init_hood_legs = __esm(() => {
13049
13073
  init_evm_lite();
13050
13074
  HOOD_CURVE_REGISTRIES = [
@@ -13052,8 +13076,7 @@ var init_hood_legs = __esm(() => {
13052
13076
  "0x75934c16162075583435358f9F042D8D6E42Bd5C",
13053
13077
  "0xFD54D094ad93349CA316bA309A3C8573E3D6C0cd"
13054
13078
  ];
13055
- DEX_SPENDERS = [HOOD_UNIV2_ROUTER, HOOD_UNIV3_ROUTER, HOOD_KYBER_ROUTER, HOOD_PERMIT2];
13056
- ADDRESSES = { array: "address" };
13079
+ DEX_SPENDERS = [HOOD_UNIV3_ROUTER, HOOD_KYBER_ROUTER, HOOD_PERMIT2];
13057
13080
  V3_SINGLE = { tuple: ["address", "address", "uint", "address", "uint", "uint", "uint"] };
13058
13081
  V3_PATH = { tuple: ["bytes", "address", "uint", "uint"] };
13059
13082
  KYBER_DESC = {
@@ -13856,7 +13879,6 @@ async function hoodSwap(ctx, args) {
13856
13879
  const recorded = kind === "trade" ? token : HOOD_USDG_ADDRESS;
13857
13880
  const notices = [];
13858
13881
  const feeRaw = BigInt(data.fee.feeRaw);
13859
- const treasury = data.fee.treasury;
13860
13882
  const feeAsset = artifacts.quoteAsset === "usdg" ? "usdg" : "eth";
13861
13883
  const checkLeg = hoodTradeLegCheck({
13862
13884
  wallet: wallet.address,
@@ -13865,7 +13887,8 @@ async function hoodSwap(ctx, args) {
13865
13887
  outputToken: to.asset === "ETH" ? undefined : to.asset === "USDG" ? HOOD_USDG_ADDRESS : to.asset,
13866
13888
  minOutRaw: BigInt(data.minOutRaw),
13867
13889
  venue: kind === "trade" && artifacts.venue === "curve" ? "curve" : "dex",
13868
- ...kind === "trade" && feeRaw > 0n && typeof treasury === "string" ? { fee: { cap: feeRaw, asset: feeAsset, treasury } } : {},
13890
+ ...kind === "trade" && feeRaw > 0n ? { fee: { cap: feeRaw, asset: feeAsset } } : {},
13891
+ treasury: () => hoodFeeTreasury(rpc()),
13869
13892
  curve: () => registeredCurveFor(rpc(), token)
13870
13893
  });
13871
13894
  const run = await runSequencedLegs(ctx, key, {
@@ -62104,7 +62127,7 @@ var init_convert = __esm(() => {
62104
62127
  });
62105
62128
 
62106
62129
  // ../mcp/src/version.ts
62107
- var SERVER_VERSION = "0.10.17";
62130
+ var SERVER_VERSION = "0.10.18";
62108
62131
 
62109
62132
  // ../mcp/src/update-notice.ts
62110
62133
  function newer(a, b) {
@@ -63039,6 +63062,12 @@ function checkActionIntent2(action, intent) {
63039
63062
  const trigger = leg.t?.trigger;
63040
63063
  if (leg.a !== first.a || leg.b !== !buy || leg.r !== true || decimal2(leg.s) !== decimal2(p.size) || trigger?.tpsl !== kind || trigger.isMarket !== true || decimal2(trigger.triggerPx) !== decimal2(p[field]))
63041
63064
  return "trigger side, size, reduce-only flag or price does not match the request";
63065
+ const px = decimal2(leg.p) ?? 0n;
63066
+ const triggerPx = decimal2(trigger.triggerPx) ?? 0n;
63067
+ const bound = BigInt(HYPERLIQUID_TPSL_SLIPPAGE_BPS2 + HYPERLIQUID_MID_DRIFT_BPS2);
63068
+ const within = leg.b === true ? px * 10000n <= triggerPx * (10000n + bound) : px * 10000n >= triggerPx * (10000n - bound);
63069
+ if (triggerPx <= 0n || !within)
63070
+ return "trigger order price is outside its slippage of the trigger price";
63042
63071
  }
63043
63072
  } else {
63044
63073
  if (list.length !== 1)
@@ -63228,7 +63257,7 @@ function hyperliquidExchangeBody2(action, nonce, signature) {
63228
63257
  function hyperliquidRelayBody2(typedData) {
63229
63258
  return { method: "eth_signTypedData_v4", params: { typed_data: typedData } };
63230
63259
  }
63231
- var HYPERLIQUID_ALLOWED_ACTION_TYPES2, HYPERLIQUID_EXCHANGE_URLS2, HYPERLIQUID_INFO_URLS2, CANDLE_HYPERLIQUID_BUILDER_ADDRESS2 = null, HYPERLIQUID_MAX_BUILDER_FEE_TENTHS_BPS2 = 100, HYPERLIQUID_MAX_BUILDER_FEE_RATE2 = "0.1%", HYPERLIQUID_SIGNATURE_CHAIN_ID2 = "0xa4b1", ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000", UINT64_MAX2, INT64_MIN2, EVM_ADDRESS_RE2, HYPERLIQUID_DEFAULT_SLIPPAGE_BPS2 = 100, HYPERLIQUID_MID_DRIFT_BPS2 = 100;
63260
+ var HYPERLIQUID_ALLOWED_ACTION_TYPES2, HYPERLIQUID_EXCHANGE_URLS2, HYPERLIQUID_INFO_URLS2, CANDLE_HYPERLIQUID_BUILDER_ADDRESS2 = null, HYPERLIQUID_MAX_BUILDER_FEE_TENTHS_BPS2 = 100, HYPERLIQUID_MAX_BUILDER_FEE_RATE2 = "0.1%", HYPERLIQUID_SIGNATURE_CHAIN_ID2 = "0xa4b1", ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000", UINT64_MAX2, INT64_MIN2, EVM_ADDRESS_RE2, HYPERLIQUID_DEFAULT_SLIPPAGE_BPS2 = 100, HYPERLIQUID_MID_DRIFT_BPS2 = 100, HYPERLIQUID_TPSL_SLIPPAGE_BPS2 = 500;
63232
63261
  var init_hyperliquid = __esm(() => {
63233
63262
  init_sha3();
63234
63263
  HYPERLIQUID_ALLOWED_ACTION_TYPES2 = [
@@ -64978,7 +65007,7 @@ init_render();
64978
65007
  init_secret_store();
64979
65008
 
64980
65009
  // src/version.ts
64981
- var CLI_VERSION = "0.11.29";
65010
+ var CLI_VERSION = "0.11.31";
64982
65011
 
64983
65012
  // src/commands/auth.ts
64984
65013
  init_keys_embedded_wallet();
@@ -72736,6 +72765,8 @@ async function hoodLaunch(ctx, key, args) {
72736
72765
  }
72737
72766
  const confirmedPlan = buy ? first.plannedLegCount === 3 ? ["createCurve", "feeTransfer", "trade"] : ["createCurve", "trade"] : undefined;
72738
72767
  let position = 0;
72768
+ let createCurveHash;
72769
+ let quotedCurve;
72739
72770
  const evm = lazyEvmRpc(ctx, flags["--rpc-url"]);
72740
72771
  const run2 = await runSequencedLegs(ctx, key, {
72741
72772
  wallet,
@@ -72747,14 +72778,33 @@ async function hoodLaunch(ctx, key, args) {
72747
72778
  kind: "launch",
72748
72779
  primaryLeg: "createCurve",
72749
72780
  allowedLegs,
72781
+ onSigned: (kind, hash) => {
72782
+ if (kind === "createCurve")
72783
+ createCurveHash = hash;
72784
+ },
72750
72785
  checkLeg: async (kind, leg2) => {
72786
+ const buyCurve = () => {
72787
+ if (createCurveHash === undefined)
72788
+ return Promise.resolve(undefined);
72789
+ quotedCurve ??= launchedCurve(ctx, evm(), createCurveHash, wallet.address).then((created2) => created2 !== undefined && sameEvmAddress(created2, curve.address) ? created2 : undefined);
72790
+ return quotedCurve;
72791
+ };
72751
72792
  if (confirmedPlan && confirmedPlan[position++] !== kind)
72752
72793
  return false;
72753
72794
  if (kind === "createCurve")
72754
72795
  return await createCurveLegOk(leg2, wallet.address, evm());
72755
- if (kind === "feeTransfer")
72756
- return feeCap !== undefined && feeLegOk(leg2, { cap: feeCap, asset: "eth" });
72757
- return kind === "trade" && buy !== undefined && leg2.value === buy.raw && sameEvmAddress(leg2.to, curve.address);
72796
+ if (kind === "feeTransfer") {
72797
+ if (feeCap === undefined)
72798
+ return false;
72799
+ if (buy !== undefined && await buyCurve() === undefined)
72800
+ return false;
72801
+ const treasury = await hoodFeeTreasury(evm());
72802
+ return treasury !== undefined && feeLegOk(leg2, { cap: feeCap, asset: "eth", treasury });
72803
+ }
72804
+ if (kind !== "trade" || buy === undefined)
72805
+ return false;
72806
+ const created = await buyCurve();
72807
+ return created !== undefined && launchBuyLegOk(leg2, buy.raw, created);
72758
72808
  },
72759
72809
  onLanded: async () => {}
72760
72810
  });
@@ -72773,6 +72823,21 @@ async function hoodLaunch(ctx, key, args) {
72773
72823
  ...args.used
72774
72824
  });
72775
72825
  }
72826
+ var RECEIPT_ATTEMPTS = 5;
72827
+ var RECEIPT_RETRY_MS = 1000;
72828
+ async function launchedCurve(ctx, rpc, hash, wallet) {
72829
+ for (let attempt = 1;; attempt++) {
72830
+ let receipt = null;
72831
+ try {
72832
+ receipt = await rpc.getTransactionReceipt(hash);
72833
+ } catch {}
72834
+ if (receipt !== null)
72835
+ return curveCreatedBy(receipt, wallet);
72836
+ if (attempt >= RECEIPT_ATTEMPTS)
72837
+ return;
72838
+ await ctx.deps.sleep(RECEIPT_RETRY_MS);
72839
+ }
72840
+ }
72776
72841
  function hoodLaterLegsGas(count, buys) {
72777
72842
  return count < 2 || !buys ? "" : "; the later legs are priced by Candle when each becomes next";
72778
72843
  }
@@ -73633,6 +73698,12 @@ function checkActionIntent(action, intent) {
73633
73698
  const trigger = leg.t?.trigger;
73634
73699
  if (leg.a !== first.a || leg.b !== !buy || leg.r !== true || decimal(leg.s) !== decimal(p.size) || trigger?.tpsl !== kind || trigger.isMarket !== true || decimal(trigger.triggerPx) !== decimal(p[field]))
73635
73700
  return "trigger side, size, reduce-only flag or price does not match the request";
73701
+ const px = decimal(leg.p) ?? 0n;
73702
+ const triggerPx = decimal(trigger.triggerPx) ?? 0n;
73703
+ const bound = BigInt(HYPERLIQUID_TPSL_SLIPPAGE_BPS + HYPERLIQUID_MID_DRIFT_BPS);
73704
+ const within = leg.b === true ? px * 10000n <= triggerPx * (10000n + bound) : px * 10000n >= triggerPx * (10000n - bound);
73705
+ if (triggerPx <= 0n || !within)
73706
+ return "trigger order price is outside its slippage of the trigger price";
73636
73707
  }
73637
73708
  } else {
73638
73709
  if (list.length !== 1)
@@ -73674,6 +73745,7 @@ async function hyperliquidCloseOrder(fetcher, network, address, params) {
73674
73745
  }
73675
73746
  var HYPERLIQUID_DEFAULT_SLIPPAGE_BPS = 100;
73676
73747
  var HYPERLIQUID_MID_DRIFT_BPS = 100;
73748
+ var HYPERLIQUID_TPSL_SLIPPAGE_BPS = 500;
73677
73749
  async function hyperliquidOrderMarket(fetcher, network, address, method, params) {
73678
73750
  const read = async (body) => {
73679
73751
  const res = await fetcher(HYPERLIQUID_INFO_URLS[network], {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@candledottv/cli",
3
- "version": "0.11.29",
3
+ "version": "0.11.31",
4
4
  "description": "The Candle CLI: authorize a device from your browser, then manage API keys, wallets, and setup health from the terminal",
5
5
  "type": "module",
6
6
  "bin": {