@byreal-io/byreal-cli-realclaw 0.3.12 → 0.4.1-beta.2

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 (3) hide show
  1. package/README.md +57 -4
  2. package/dist/index.cjs +1468 -283
  3. package/package.json +3 -2
package/dist/index.cjs CHANGED
@@ -969,7 +969,7 @@ var require_command = __commonJS({
969
969
  var EventEmitter = require("node:events").EventEmitter;
970
970
  var childProcess = require("node:child_process");
971
971
  var path3 = require("node:path");
972
- var fs2 = require("node:fs");
972
+ var fs3 = require("node:fs");
973
973
  var process3 = require("node:process");
974
974
  var { Argument: Argument2, humanReadableArgName } = require_argument();
975
975
  var { CommanderError: CommanderError2 } = require_error();
@@ -1902,10 +1902,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
1902
1902
  const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
1903
1903
  function findFile(baseDir, baseName) {
1904
1904
  const localBin = path3.resolve(baseDir, baseName);
1905
- if (fs2.existsSync(localBin)) return localBin;
1905
+ if (fs3.existsSync(localBin)) return localBin;
1906
1906
  if (sourceExt.includes(path3.extname(baseName))) return void 0;
1907
1907
  const foundExt = sourceExt.find(
1908
- (ext) => fs2.existsSync(`${localBin}${ext}`)
1908
+ (ext) => fs3.existsSync(`${localBin}${ext}`)
1909
1909
  );
1910
1910
  if (foundExt) return `${localBin}${foundExt}`;
1911
1911
  return void 0;
@@ -1917,7 +1917,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1917
1917
  if (this._scriptPath) {
1918
1918
  let resolvedScriptPath;
1919
1919
  try {
1920
- resolvedScriptPath = fs2.realpathSync(this._scriptPath);
1920
+ resolvedScriptPath = fs3.realpathSync(this._scriptPath);
1921
1921
  } catch (err2) {
1922
1922
  resolvedScriptPath = this._scriptPath;
1923
1923
  }
@@ -3029,11 +3029,11 @@ var require_commander = __commonJS({
3029
3029
  });
3030
3030
 
3031
3031
  // src/core/constants.ts
3032
- var INJECTED_VERSION, VERSION, CLI_NAME, NPM_PACKAGE, API_BASE_URL, API_ENDPOINTS, SOLANA_RPC_URL, SOLANA_CLUSTER, JUPITER_API_KEY, JUP_PAID_BASE, JUP_FREE_BASE, TITAN_API_URL, TITAN_AUTH_TOKEN, DFLOW_PAID_URL, DFLOW_FREE_URL, DFLOW_API_KEY, CONFIG_DIR, CONFIG_FILE, DEFAULTS, TABLE_CHARS, LOGO, EXPERIMENTAL_WARNING, DEFAULT_CONFIG, DIR_PERMISSIONS;
3032
+ var INJECTED_VERSION, VERSION, CLI_NAME, NPM_PACKAGE, API_BASE_URL, API_ENDPOINTS, SOLANA_RPC_URL, SOLANA_CLUSTER, JUPITER_API_KEY, JUP_PAID_BASE, JUP_FREE_BASE, TITAN_API_URL, TITAN_AUTH_TOKEN, DFLOW_PAID_URL, DFLOW_FREE_URL, DFLOW_API_KEY, CONFIG_DIR, CONFIG_FILE, SOLANA_MAINNET_CAIP2, PRIVY_API_BASE_PATH_DEFAULT, PRIVY_PROXY_URL_ENV, PRIVY_API_BASE_PATH_ENV, AGENT_TOKEN_ENV, REALCLAW_CONFIG_PATH, SKILL_AGENT_TOKEN_CONFIG_PATH, LEGACY_AGENT_TOKEN_PATH, PRIVY_STRATEGY_ID, PRIVY_STRATEGY_NAME, DEFAULTS, TABLE_CHARS, LOGO, EXPERIMENTAL_WARNING, DEFAULT_CONFIG, DIR_PERMISSIONS;
3033
3033
  var init_constants = __esm({
3034
3034
  "src/core/constants.ts"() {
3035
3035
  "use strict";
3036
- INJECTED_VERSION = true ? "0.3.12" : void 0;
3036
+ INJECTED_VERSION = true ? "0.4.1-beta.2" : void 0;
3037
3037
  VERSION = INJECTED_VERSION ?? process.env.npm_package_version ?? "0.0.0";
3038
3038
  CLI_NAME = "byreal-cli";
3039
3039
  NPM_PACKAGE = "@byreal-io/byreal-cli-realclaw";
@@ -3077,6 +3077,16 @@ var init_constants = __esm({
3077
3077
  DFLOW_API_KEY = process.env.DFLOW_API_KEY;
3078
3078
  CONFIG_DIR = "~/.config/byreal";
3079
3079
  CONFIG_FILE = "config.json";
3080
+ SOLANA_MAINNET_CAIP2 = "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp";
3081
+ PRIVY_API_BASE_PATH_DEFAULT = "/byreal/api/privy-proxy/v1";
3082
+ PRIVY_PROXY_URL_ENV = process.env.PRIVY_PROXY_URL;
3083
+ PRIVY_API_BASE_PATH_ENV = process.env.PRIVY_API_BASE_PATH;
3084
+ AGENT_TOKEN_ENV = process.env.AGENT_TOKEN;
3085
+ REALCLAW_CONFIG_PATH = "~/.openclaw/realclaw-config.json";
3086
+ SKILL_AGENT_TOKEN_CONFIG_PATH = "~/.openclaw/skills/agent-token/scripts/config.json";
3087
+ LEGACY_AGENT_TOKEN_PATH = "~/.openclaw/agent_token";
3088
+ PRIVY_STRATEGY_ID = "byreal_cli";
3089
+ PRIVY_STRATEGY_NAME = "Byreal CLI";
3080
3090
  DEFAULTS = {
3081
3091
  OUTPUT_FORMAT: "table",
3082
3092
  LIST_LIMIT: 100,
@@ -20229,7 +20239,7 @@ var require_constants = __commonJS({
20229
20239
  // node_modules/node-gyp-build/node-gyp-build.js
20230
20240
  var require_node_gyp_build = __commonJS({
20231
20241
  "node_modules/node-gyp-build/node-gyp-build.js"(exports2, module2) {
20232
- var fs2 = require("fs");
20242
+ var fs3 = require("fs");
20233
20243
  var path3 = require("path");
20234
20244
  var os3 = require("os");
20235
20245
  var runtimeRequire = typeof __webpack_require__ === "function" ? __non_webpack_require__ : require;
@@ -20290,7 +20300,7 @@ var require_node_gyp_build = __commonJS({
20290
20300
  };
20291
20301
  function readdirSync(dir) {
20292
20302
  try {
20293
- return fs2.readdirSync(dir);
20303
+ return fs3.readdirSync(dir);
20294
20304
  } catch (err2) {
20295
20305
  return [];
20296
20306
  }
@@ -20384,7 +20394,7 @@ var require_node_gyp_build = __commonJS({
20384
20394
  return typeof window !== "undefined" && window.process && window.process.type === "renderer";
20385
20395
  }
20386
20396
  function isAlpine(platform2) {
20387
- return platform2 === "linux" && fs2.existsSync("/etc/alpine-release");
20397
+ return platform2 === "linux" && fs3.existsSync("/etc/alpine-release");
20388
20398
  }
20389
20399
  load.parseTags = parseTags;
20390
20400
  load.matchTags = matchTags;
@@ -26993,7 +27003,7 @@ var require_index_cjs = __commonJS({
26993
27003
  return value._bn !== void 0;
26994
27004
  }
26995
27005
  var uniquePublicKeyCounter = 1;
26996
- var PublicKey51 = class _PublicKey2 extends Struct {
27006
+ var PublicKey52 = class _PublicKey2 extends Struct {
26997
27007
  /**
26998
27008
  * Create a new PublicKey object
26999
27009
  * @param value ed25519 public key as buffer or base-58 encoded string
@@ -27155,9 +27165,9 @@ var require_index_cjs = __commonJS({
27155
27165
  return isOnCurve(pubkey.toBytes());
27156
27166
  }
27157
27167
  };
27158
- _PublicKey = PublicKey51;
27159
- PublicKey51.default = new _PublicKey("11111111111111111111111111111111");
27160
- SOLANA_SCHEMA.set(PublicKey51, {
27168
+ _PublicKey = PublicKey52;
27169
+ PublicKey52.default = new _PublicKey("11111111111111111111111111111111");
27170
+ SOLANA_SCHEMA.set(PublicKey52, {
27161
27171
  kind: "struct",
27162
27172
  fields: [["_bn", "u256"]]
27163
27173
  });
@@ -27189,7 +27199,7 @@ var require_index_cjs = __commonJS({
27189
27199
  * The public key for this account
27190
27200
  */
27191
27201
  get publicKey() {
27192
- return new PublicKey51(this._publicKey);
27202
+ return new PublicKey52(this._publicKey);
27193
27203
  }
27194
27204
  /**
27195
27205
  * The **unencrypted** secret key for this account. The first 32 bytes
@@ -27200,7 +27210,7 @@ var require_index_cjs = __commonJS({
27200
27210
  return buffer.Buffer.concat([this._secretKey, this._publicKey], 64);
27201
27211
  }
27202
27212
  };
27203
- var BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey51("BPFLoader1111111111111111111111111111111111");
27213
+ var BPF_LOADER_DEPRECATED_PROGRAM_ID = new PublicKey52("BPFLoader1111111111111111111111111111111111");
27204
27214
  var PACKET_DATA_SIZE = 1280 - 40 - 8;
27205
27215
  var VERSION_PREFIX_MASK = 127;
27206
27216
  var SIGNATURE_LENGTH_IN_BYTES = 64;
@@ -27431,7 +27441,7 @@ var require_index_cjs = __commonJS({
27431
27441
  const [payerAddress] = writableSigners[0];
27432
27442
  assert(payerAddress === this.payer.toBase58(), "Expected first writable signer key to be the fee payer");
27433
27443
  }
27434
- const staticAccountKeys = [...writableSigners.map(([address]) => new PublicKey51(address)), ...readonlySigners.map(([address]) => new PublicKey51(address)), ...writableNonSigners.map(([address]) => new PublicKey51(address)), ...readonlyNonSigners.map(([address]) => new PublicKey51(address))];
27444
+ const staticAccountKeys = [...writableSigners.map(([address]) => new PublicKey52(address)), ...readonlySigners.map(([address]) => new PublicKey52(address)), ...writableNonSigners.map(([address]) => new PublicKey52(address)), ...readonlyNonSigners.map(([address]) => new PublicKey52(address))];
27435
27445
  return [header, staticAccountKeys];
27436
27446
  }
27437
27447
  extractTableLookup(lookupTable) {
@@ -27455,7 +27465,7 @@ var require_index_cjs = __commonJS({
27455
27465
  const drainedKeys = new Array();
27456
27466
  for (const [address, keyMeta] of this.keyMetaMap.entries()) {
27457
27467
  if (keyMetaFilter(keyMeta)) {
27458
- const key = new PublicKey51(address);
27468
+ const key = new PublicKey52(address);
27459
27469
  const lookupTableIndex = lookupTableEntries.findIndex((entry) => entry.equals(key));
27460
27470
  if (lookupTableIndex >= 0) {
27461
27471
  assert(lookupTableIndex < 256, "Max lookup table index exceeded");
@@ -27490,7 +27500,7 @@ var require_index_cjs = __commonJS({
27490
27500
  this.instructions = void 0;
27491
27501
  this.indexToProgramIds = /* @__PURE__ */ new Map();
27492
27502
  this.header = args.header;
27493
- this.accountKeys = args.accountKeys.map((account) => new PublicKey51(account));
27503
+ this.accountKeys = args.accountKeys.map((account) => new PublicKey52(account));
27494
27504
  this.recentBlockhash = args.recentBlockhash;
27495
27505
  this.instructions = args.instructions;
27496
27506
  this.instructions.forEach((ix) => this.indexToProgramIds.set(ix.programIdIndex, this.accountKeys[ix.programIdIndex]));
@@ -27616,7 +27626,7 @@ var require_index_cjs = __commonJS({
27616
27626
  let accountKeys = [];
27617
27627
  for (let i = 0; i < accountCount; i++) {
27618
27628
  const account = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2);
27619
- accountKeys.push(new PublicKey51(buffer.Buffer.from(account)));
27629
+ accountKeys.push(new PublicKey52(buffer.Buffer.from(account)));
27620
27630
  }
27621
27631
  const recentBlockhash = guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2);
27622
27632
  const instructionCount = decodeLength(byteArray);
@@ -27840,7 +27850,7 @@ var require_index_cjs = __commonJS({
27840
27850
  const staticAccountKeys = [];
27841
27851
  const staticAccountKeysLength = decodeLength(byteArray);
27842
27852
  for (let i = 0; i < staticAccountKeysLength; i++) {
27843
- staticAccountKeys.push(new PublicKey51(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2)));
27853
+ staticAccountKeys.push(new PublicKey52(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2)));
27844
27854
  }
27845
27855
  const recentBlockhash = bs58__default.default.encode(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2));
27846
27856
  const instructionCount = decodeLength(byteArray);
@@ -27860,7 +27870,7 @@ var require_index_cjs = __commonJS({
27860
27870
  const addressTableLookupsCount = decodeLength(byteArray);
27861
27871
  const addressTableLookups = [];
27862
27872
  for (let i = 0; i < addressTableLookupsCount; i++) {
27863
- const accountKey = new PublicKey51(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2));
27873
+ const accountKey = new PublicKey52(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2));
27864
27874
  const writableIndexesLength = decodeLength(byteArray);
27865
27875
  const writableIndexes = guardedSplice(byteArray, 0, writableIndexesLength);
27866
27876
  const readonlyIndexesLength = decodeLength(byteArray);
@@ -28100,7 +28110,7 @@ var require_index_cjs = __commonJS({
28100
28110
  });
28101
28111
  programIds.forEach((programId) => {
28102
28112
  accountMetas.push({
28103
- pubkey: new PublicKey51(programId),
28113
+ pubkey: new PublicKey52(programId),
28104
28114
  isSigner: false,
28105
28115
  isWritable: false
28106
28116
  });
@@ -28693,15 +28703,15 @@ Missing signature for public key${sigErrors.missing.length === 1 ? "" : "(s)"} [
28693
28703
  var DEFAULT_TICKS_PER_SLOT = 64;
28694
28704
  var NUM_SLOTS_PER_SECOND = NUM_TICKS_PER_SECOND / DEFAULT_TICKS_PER_SLOT;
28695
28705
  var MS_PER_SLOT = 1e3 / NUM_SLOTS_PER_SECOND;
28696
- var SYSVAR_CLOCK_PUBKEY2 = new PublicKey51("SysvarC1ock11111111111111111111111111111111");
28697
- var SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey51("SysvarEpochSchedu1e111111111111111111111111");
28698
- var SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey51("Sysvar1nstructions1111111111111111111111111");
28699
- var SYSVAR_RECENT_BLOCKHASHES_PUBKEY = new PublicKey51("SysvarRecentB1ockHashes11111111111111111111");
28700
- var SYSVAR_RENT_PUBKEY5 = new PublicKey51("SysvarRent111111111111111111111111111111111");
28701
- var SYSVAR_REWARDS_PUBKEY = new PublicKey51("SysvarRewards111111111111111111111111111111");
28702
- var SYSVAR_SLOT_HASHES_PUBKEY = new PublicKey51("SysvarS1otHashes111111111111111111111111111");
28703
- var SYSVAR_SLOT_HISTORY_PUBKEY = new PublicKey51("SysvarS1otHistory11111111111111111111111111");
28704
- var SYSVAR_STAKE_HISTORY_PUBKEY = new PublicKey51("SysvarStakeHistory1111111111111111111111111");
28706
+ var SYSVAR_CLOCK_PUBKEY2 = new PublicKey52("SysvarC1ock11111111111111111111111111111111");
28707
+ var SYSVAR_EPOCH_SCHEDULE_PUBKEY = new PublicKey52("SysvarEpochSchedu1e111111111111111111111111");
28708
+ var SYSVAR_INSTRUCTIONS_PUBKEY = new PublicKey52("Sysvar1nstructions1111111111111111111111111");
28709
+ var SYSVAR_RECENT_BLOCKHASHES_PUBKEY = new PublicKey52("SysvarRecentB1ockHashes11111111111111111111");
28710
+ var SYSVAR_RENT_PUBKEY5 = new PublicKey52("SysvarRent111111111111111111111111111111111");
28711
+ var SYSVAR_REWARDS_PUBKEY = new PublicKey52("SysvarRewards111111111111111111111111111111");
28712
+ var SYSVAR_SLOT_HASHES_PUBKEY = new PublicKey52("SysvarS1otHashes111111111111111111111111111");
28713
+ var SYSVAR_SLOT_HISTORY_PUBKEY = new PublicKey52("SysvarS1otHistory11111111111111111111111111");
28714
+ var SYSVAR_STAKE_HISTORY_PUBKEY = new PublicKey52("SysvarStakeHistory1111111111111111111111111");
28705
28715
  var SendTransactionError = class extends Error {
28706
28716
  constructor({
28707
28717
  action,
@@ -28892,8 +28902,8 @@ Message: ${transactionMessage}.
28892
28902
  static fromAccountData(buffer2) {
28893
28903
  const nonceAccount = NonceAccountLayout.decode(toBuffer(buffer2), 0);
28894
28904
  return new _NonceAccount({
28895
- authorizedPubkey: new PublicKey51(nonceAccount.authorizedPubkey),
28896
- nonce: new PublicKey51(nonceAccount.nonce).toString(),
28905
+ authorizedPubkey: new PublicKey52(nonceAccount.authorizedPubkey),
28906
+ nonce: new PublicKey52(nonceAccount.nonce).toString(),
28897
28907
  feeCalculator: nonceAccount.feeCalculator
28898
28908
  });
28899
28909
  }
@@ -28955,7 +28965,7 @@ Message: ${transactionMessage}.
28955
28965
  newAccountPubkey: instruction.keys[1].pubkey,
28956
28966
  lamports,
28957
28967
  space,
28958
- programId: new PublicKey51(programId)
28968
+ programId: new PublicKey52(programId)
28959
28969
  };
28960
28970
  }
28961
28971
  /**
@@ -28990,7 +29000,7 @@ Message: ${transactionMessage}.
28990
29000
  toPubkey: instruction.keys[2].pubkey,
28991
29001
  lamports,
28992
29002
  seed,
28993
- programId: new PublicKey51(programId)
29003
+ programId: new PublicKey52(programId)
28994
29004
  };
28995
29005
  }
28996
29006
  /**
@@ -29021,10 +29031,10 @@ Message: ${transactionMessage}.
29021
29031
  } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AllocateWithSeed, instruction.data);
29022
29032
  return {
29023
29033
  accountPubkey: instruction.keys[0].pubkey,
29024
- basePubkey: new PublicKey51(base),
29034
+ basePubkey: new PublicKey52(base),
29025
29035
  seed,
29026
29036
  space,
29027
- programId: new PublicKey51(programId)
29037
+ programId: new PublicKey52(programId)
29028
29038
  };
29029
29039
  }
29030
29040
  /**
@@ -29038,7 +29048,7 @@ Message: ${transactionMessage}.
29038
29048
  } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.Assign, instruction.data);
29039
29049
  return {
29040
29050
  accountPubkey: instruction.keys[0].pubkey,
29041
- programId: new PublicKey51(programId)
29051
+ programId: new PublicKey52(programId)
29042
29052
  };
29043
29053
  }
29044
29054
  /**
@@ -29054,9 +29064,9 @@ Message: ${transactionMessage}.
29054
29064
  } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.AssignWithSeed, instruction.data);
29055
29065
  return {
29056
29066
  accountPubkey: instruction.keys[0].pubkey,
29057
- basePubkey: new PublicKey51(base),
29067
+ basePubkey: new PublicKey52(base),
29058
29068
  seed,
29059
- programId: new PublicKey51(programId)
29069
+ programId: new PublicKey52(programId)
29060
29070
  };
29061
29071
  }
29062
29072
  /**
@@ -29075,11 +29085,11 @@ Message: ${transactionMessage}.
29075
29085
  return {
29076
29086
  fromPubkey: instruction.keys[0].pubkey,
29077
29087
  newAccountPubkey: instruction.keys[1].pubkey,
29078
- basePubkey: new PublicKey51(base),
29088
+ basePubkey: new PublicKey52(base),
29079
29089
  seed,
29080
29090
  lamports,
29081
29091
  space,
29082
- programId: new PublicKey51(programId)
29092
+ programId: new PublicKey52(programId)
29083
29093
  };
29084
29094
  }
29085
29095
  /**
@@ -29093,7 +29103,7 @@ Message: ${transactionMessage}.
29093
29103
  } = decodeData$1(SYSTEM_INSTRUCTION_LAYOUTS.InitializeNonceAccount, instruction.data);
29094
29104
  return {
29095
29105
  noncePubkey: instruction.keys[0].pubkey,
29096
- authorizedPubkey: new PublicKey51(authorized2)
29106
+ authorizedPubkey: new PublicKey52(authorized2)
29097
29107
  };
29098
29108
  }
29099
29109
  /**
@@ -29136,7 +29146,7 @@ Message: ${transactionMessage}.
29136
29146
  return {
29137
29147
  noncePubkey: instruction.keys[0].pubkey,
29138
29148
  authorizedPubkey: instruction.keys[1].pubkey,
29139
- newAuthorizedPubkey: new PublicKey51(authorized2)
29149
+ newAuthorizedPubkey: new PublicKey52(authorized2)
29140
29150
  };
29141
29151
  }
29142
29152
  /**
@@ -29545,7 +29555,7 @@ Message: ${transactionMessage}.
29545
29555
  });
29546
29556
  }
29547
29557
  };
29548
- SystemProgram13.programId = new PublicKey51("11111111111111111111111111111111");
29558
+ SystemProgram13.programId = new PublicKey52("11111111111111111111111111111111");
29549
29559
  var CHUNK_SIZE = PACKET_DATA_SIZE - 300;
29550
29560
  var Loader = class _Loader {
29551
29561
  /**
@@ -29712,7 +29722,7 @@ Message: ${transactionMessage}.
29712
29722
  }
29713
29723
  };
29714
29724
  Loader.chunkSize = CHUNK_SIZE;
29715
- var BPF_LOADER_PROGRAM_ID = new PublicKey51("BPFLoader2111111111111111111111111111111111");
29725
+ var BPF_LOADER_PROGRAM_ID = new PublicKey52("BPFLoader2111111111111111111111111111111111");
29716
29726
  var BpfLoader = class {
29717
29727
  /**
29718
29728
  * Minimum number of signatures required to load a program not including
@@ -30508,8 +30518,8 @@ Message: ${transactionMessage}.
30508
30518
  deactivationSlot: meta.deactivationSlot,
30509
30519
  lastExtendedSlot: meta.lastExtendedSlot,
30510
30520
  lastExtendedSlotStartIndex: meta.lastExtendedStartIndex,
30511
- authority: meta.authority.length !== 0 ? new PublicKey51(meta.authority[0]) : void 0,
30512
- addresses: addresses.map((address) => new PublicKey51(address))
30521
+ authority: meta.authority.length !== 0 ? new PublicKey52(meta.authority[0]) : void 0,
30522
+ addresses: addresses.map((address) => new PublicKey52(address))
30513
30523
  };
30514
30524
  }
30515
30525
  };
@@ -30551,7 +30561,7 @@ Message: ${transactionMessage}.
30551
30561
  );
30552
30562
  return `${protocol}//${hostish}${websocketPort}${rest}`;
30553
30563
  }
30554
- var PublicKeyFromString = superstruct.coerce(superstruct.instance(PublicKey51), superstruct.string(), (value) => new PublicKey51(value));
30564
+ var PublicKeyFromString = superstruct.coerce(superstruct.instance(PublicKey52), superstruct.string(), (value) => new PublicKey52(value));
30555
30565
  var RawAccountDataResult = superstruct.tuple([superstruct.string(), superstruct.literal("base64")]);
30556
30566
  var BufferFromRawAccountData = superstruct.coerce(superstruct.instance(buffer.Buffer), RawAccountDataResult, (value) => buffer.Buffer.from(value[0], "base64"));
30557
30567
  var BLOCKHASH_CACHE_TIMEOUT_MS = 30 * 1e3;
@@ -30636,7 +30646,7 @@ Message: ${transactionMessage}.
30636
30646
  if (version2 === 0) {
30637
30647
  return new MessageV0({
30638
30648
  header: response.header,
30639
- staticAccountKeys: response.accountKeys.map((accountKey) => new PublicKey51(accountKey)),
30649
+ staticAccountKeys: response.accountKeys.map((accountKey) => new PublicKey52(accountKey)),
30640
30650
  recentBlockhash: response.recentBlockhash,
30641
30651
  compiledInstructions: response.instructions.map((ix) => ({
30642
30652
  programIdIndex: ix.programIdIndex,
@@ -31300,7 +31310,7 @@ Message: ${transactionMessage}.
31300
31310
  var COMMON_HTTP_HEADERS = {
31301
31311
  "solana-client": `js/${"1.0.0-maintenance"}`
31302
31312
  };
31303
- var Connection5 = class {
31313
+ var Connection6 = class {
31304
31314
  /**
31305
31315
  * Establish a JSON RPC connection
31306
31316
  *
@@ -34076,7 +34086,7 @@ Message: ${transactionMessage}.
34076
34086
  * @returns {PublicKey} PublicKey
34077
34087
  */
34078
34088
  get publicKey() {
34079
- return new PublicKey51(this._keypair.publicKey);
34089
+ return new PublicKey52(this._keypair.publicKey);
34080
34090
  }
34081
34091
  /**
34082
34092
  * The raw secret key for this keypair
@@ -34154,7 +34164,7 @@ Message: ${transactionMessage}.
34154
34164
  lookupTable: instruction.keys[0].pubkey,
34155
34165
  authority: instruction.keys[1].pubkey,
34156
34166
  payer: instruction.keys.length > 2 ? instruction.keys[2].pubkey : void 0,
34157
- addresses: addresses.map((buffer2) => new PublicKey51(buffer2))
34167
+ addresses: addresses.map((buffer2) => new PublicKey52(buffer2))
34158
34168
  };
34159
34169
  }
34160
34170
  static decodeCloseLookupTable(instruction) {
@@ -34206,7 +34216,7 @@ Message: ${transactionMessage}.
34206
34216
  constructor() {
34207
34217
  }
34208
34218
  static createLookupTable(params) {
34209
- const [lookupTableAddress, bumpSeed] = PublicKey51.findProgramAddressSync([params.authority.toBuffer(), codecsNumbers.getU64Encoder().encode(params.recentSlot)], this.programId);
34219
+ const [lookupTableAddress, bumpSeed] = PublicKey52.findProgramAddressSync([params.authority.toBuffer(), codecsNumbers.getU64Encoder().encode(params.recentSlot)], this.programId);
34210
34220
  const type = LOOKUP_TABLE_INSTRUCTION_LAYOUTS.CreateLookupTable;
34211
34221
  const data = encodeData(type, {
34212
34222
  recentSlot: BigInt(params.recentSlot),
@@ -34325,7 +34335,7 @@ Message: ${transactionMessage}.
34325
34335
  });
34326
34336
  }
34327
34337
  };
34328
- AddressLookupTableProgram.programId = new PublicKey51("AddressLookupTab1e1111111111111111111111111");
34338
+ AddressLookupTableProgram.programId = new PublicKey52("AddressLookupTab1e1111111111111111111111111");
34329
34339
  var ComputeBudgetInstruction = class {
34330
34340
  /**
34331
34341
  * @internal
@@ -34479,7 +34489,7 @@ Message: ${transactionMessage}.
34479
34489
  });
34480
34490
  }
34481
34491
  };
34482
- ComputeBudgetProgram4.programId = new PublicKey51("ComputeBudget111111111111111111111111111111");
34492
+ ComputeBudgetProgram4.programId = new PublicKey52("ComputeBudget111111111111111111111111111111");
34483
34493
  var PRIVATE_KEY_BYTES$1 = 64;
34484
34494
  var PUBLIC_KEY_BYTES$1 = 32;
34485
34495
  var SIGNATURE_BYTES = 64;
@@ -34559,7 +34569,7 @@ Message: ${transactionMessage}.
34559
34569
  }
34560
34570
  }
34561
34571
  };
34562
- Ed25519Program.programId = new PublicKey51("Ed25519SigVerify111111111111111111111111111");
34572
+ Ed25519Program.programId = new PublicKey52("Ed25519SigVerify111111111111111111111111111");
34563
34573
  var ecdsaSign = (msgHash, privKey) => {
34564
34574
  const signature2 = secp256k1.secp256k1.sign(msgHash, privKey);
34565
34575
  return [signature2.toCompactRawBytes(), signature2.recovery];
@@ -34693,9 +34703,9 @@ Message: ${transactionMessage}.
34693
34703
  }
34694
34704
  }
34695
34705
  };
34696
- Secp256k1Program.programId = new PublicKey51("KeccakSecp256k11111111111111111111111111111");
34706
+ Secp256k1Program.programId = new PublicKey52("KeccakSecp256k11111111111111111111111111111");
34697
34707
  var _Lockup;
34698
- var STAKE_CONFIG_ID = new PublicKey51("StakeConfig11111111111111111111111111111111");
34708
+ var STAKE_CONFIG_ID = new PublicKey52("StakeConfig11111111111111111111111111111111");
34699
34709
  var Authorized = class {
34700
34710
  /**
34701
34711
  * Create a new Authorized object
@@ -34726,7 +34736,7 @@ Message: ${transactionMessage}.
34726
34736
  */
34727
34737
  };
34728
34738
  _Lockup = Lockup;
34729
- Lockup.default = new _Lockup(0, 0, PublicKey51.default);
34739
+ Lockup.default = new _Lockup(0, 0, PublicKey52.default);
34730
34740
  var StakeInstruction = class {
34731
34741
  /**
34732
34742
  * @internal
@@ -34764,8 +34774,8 @@ Message: ${transactionMessage}.
34764
34774
  } = decodeData$1(STAKE_INSTRUCTION_LAYOUTS.Initialize, instruction.data);
34765
34775
  return {
34766
34776
  stakePubkey: instruction.keys[0].pubkey,
34767
- authorized: new Authorized(new PublicKey51(authorized2.staker), new PublicKey51(authorized2.withdrawer)),
34768
- lockup: new Lockup(lockup2.unixTimestamp, lockup2.epoch, new PublicKey51(lockup2.custodian))
34777
+ authorized: new Authorized(new PublicKey52(authorized2.staker), new PublicKey52(authorized2.withdrawer)),
34778
+ lockup: new Lockup(lockup2.unixTimestamp, lockup2.epoch, new PublicKey52(lockup2.custodian))
34769
34779
  };
34770
34780
  }
34771
34781
  /**
@@ -34794,7 +34804,7 @@ Message: ${transactionMessage}.
34794
34804
  const o = {
34795
34805
  stakePubkey: instruction.keys[0].pubkey,
34796
34806
  authorizedPubkey: instruction.keys[2].pubkey,
34797
- newAuthorizedPubkey: new PublicKey51(newAuthorized),
34807
+ newAuthorizedPubkey: new PublicKey52(newAuthorized),
34798
34808
  stakeAuthorizationType: {
34799
34809
  index: stakeAuthorizationType
34800
34810
  }
@@ -34820,8 +34830,8 @@ Message: ${transactionMessage}.
34820
34830
  stakePubkey: instruction.keys[0].pubkey,
34821
34831
  authorityBase: instruction.keys[1].pubkey,
34822
34832
  authoritySeed,
34823
- authorityOwner: new PublicKey51(authorityOwner),
34824
- newAuthorizedPubkey: new PublicKey51(newAuthorized),
34833
+ authorityOwner: new PublicKey52(authorityOwner),
34834
+ newAuthorizedPubkey: new PublicKey52(newAuthorized),
34825
34835
  stakeAuthorizationType: {
34826
34836
  index: stakeAuthorizationType
34827
34837
  }
@@ -35375,7 +35385,7 @@ Message: ${transactionMessage}.
35375
35385
  });
35376
35386
  }
35377
35387
  };
35378
- StakeProgram.programId = new PublicKey51("Stake11111111111111111111111111111111111111");
35388
+ StakeProgram.programId = new PublicKey52("Stake11111111111111111111111111111111111111");
35379
35389
  StakeProgram.space = 200;
35380
35390
  var VoteInit = class {
35381
35391
  /** [0, 100] */
@@ -35427,7 +35437,7 @@ Message: ${transactionMessage}.
35427
35437
  return {
35428
35438
  votePubkey: instruction.keys[0].pubkey,
35429
35439
  nodePubkey: instruction.keys[3].pubkey,
35430
- voteInit: new VoteInit(new PublicKey51(voteInit2.nodePubkey), new PublicKey51(voteInit2.authorizedVoter), new PublicKey51(voteInit2.authorizedWithdrawer), voteInit2.commission)
35440
+ voteInit: new VoteInit(new PublicKey52(voteInit2.nodePubkey), new PublicKey52(voteInit2.authorizedVoter), new PublicKey52(voteInit2.authorizedWithdrawer), voteInit2.commission)
35431
35441
  };
35432
35442
  }
35433
35443
  /**
@@ -35443,7 +35453,7 @@ Message: ${transactionMessage}.
35443
35453
  return {
35444
35454
  votePubkey: instruction.keys[0].pubkey,
35445
35455
  authorizedPubkey: instruction.keys[2].pubkey,
35446
- newAuthorizedPubkey: new PublicKey51(newAuthorized),
35456
+ newAuthorizedPubkey: new PublicKey52(newAuthorized),
35447
35457
  voteAuthorizationType: {
35448
35458
  index: voteAuthorizationType
35449
35459
  }
@@ -35465,9 +35475,9 @@ Message: ${transactionMessage}.
35465
35475
  } = decodeData$1(VOTE_INSTRUCTION_LAYOUTS.AuthorizeWithSeed, instruction.data);
35466
35476
  return {
35467
35477
  currentAuthorityDerivedKeyBasePubkey: instruction.keys[2].pubkey,
35468
- currentAuthorityDerivedKeyOwnerPubkey: new PublicKey51(currentAuthorityDerivedKeyOwnerPubkey),
35478
+ currentAuthorityDerivedKeyOwnerPubkey: new PublicKey52(currentAuthorityDerivedKeyOwnerPubkey),
35469
35479
  currentAuthorityDerivedKeySeed,
35470
- newAuthorizedPubkey: new PublicKey51(newAuthorized),
35480
+ newAuthorizedPubkey: new PublicKey52(newAuthorized),
35471
35481
  voteAuthorizationType: {
35472
35482
  index: voteAuthorizationType
35473
35483
  },
@@ -35758,9 +35768,9 @@ Message: ${transactionMessage}.
35758
35768
  });
35759
35769
  }
35760
35770
  };
35761
- VoteProgram.programId = new PublicKey51("Vote111111111111111111111111111111111111111");
35771
+ VoteProgram.programId = new PublicKey52("Vote111111111111111111111111111111111111111");
35762
35772
  VoteProgram.space = 3762;
35763
- var VALIDATOR_INFO_KEY = new PublicKey51("Va1idator1nfo111111111111111111111111111111");
35773
+ var VALIDATOR_INFO_KEY = new PublicKey52("Va1idator1nfo111111111111111111111111111111");
35764
35774
  var InfoString = superstruct.type({
35765
35775
  name: superstruct.string(),
35766
35776
  website: superstruct.optional(superstruct.string()),
@@ -35794,7 +35804,7 @@ Message: ${transactionMessage}.
35794
35804
  if (configKeyCount !== 2) return null;
35795
35805
  const configKeys = [];
35796
35806
  for (let i = 0; i < 2; i++) {
35797
- const publicKey4 = new PublicKey51(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2));
35807
+ const publicKey4 = new PublicKey52(guardedSplice(byteArray, 0, PUBLIC_KEY_LENGTH2));
35798
35808
  const isSigner = guardedShift(byteArray) === 1;
35799
35809
  configKeys.push({
35800
35810
  publicKey: publicKey4,
@@ -35812,7 +35822,7 @@ Message: ${transactionMessage}.
35812
35822
  return null;
35813
35823
  }
35814
35824
  };
35815
- var VOTE_PROGRAM_ID = new PublicKey51("Vote111111111111111111111111111111111111111");
35825
+ var VOTE_PROGRAM_ID = new PublicKey52("Vote111111111111111111111111111111111111111");
35816
35826
  var VoteAccountLayout = BufferLayout__namespace.struct([
35817
35827
  publicKey3("nodePubkey"),
35818
35828
  publicKey3("authorizedWithdrawer"),
@@ -35869,8 +35879,8 @@ Message: ${transactionMessage}.
35869
35879
  rootSlot = null;
35870
35880
  }
35871
35881
  return new _VoteAccount({
35872
- nodePubkey: new PublicKey51(va.nodePubkey),
35873
- authorizedWithdrawer: new PublicKey51(va.authorizedWithdrawer),
35882
+ nodePubkey: new PublicKey52(va.nodePubkey),
35883
+ authorizedWithdrawer: new PublicKey52(va.authorizedWithdrawer),
35874
35884
  commission: va.commission,
35875
35885
  votes: va.votes,
35876
35886
  rootSlot,
@@ -35887,7 +35897,7 @@ Message: ${transactionMessage}.
35887
35897
  }) {
35888
35898
  return {
35889
35899
  epoch,
35890
- authorizedVoter: new PublicKey51(authorizedVoter)
35900
+ authorizedVoter: new PublicKey52(authorizedVoter)
35891
35901
  };
35892
35902
  }
35893
35903
  function parsePriorVoters({
@@ -35896,7 +35906,7 @@ Message: ${transactionMessage}.
35896
35906
  targetEpoch
35897
35907
  }) {
35898
35908
  return {
35899
- authorizedPubkey: new PublicKey51(authorizedPubkey),
35909
+ authorizedPubkey: new PublicKey52(authorizedPubkey),
35900
35910
  epochOfLastAuthorizedSwitch,
35901
35911
  targetEpoch
35902
35912
  };
@@ -35980,7 +35990,7 @@ Message: ${transactionMessage}.
35980
35990
  exports2.COMPUTE_BUDGET_INSTRUCTION_LAYOUTS = COMPUTE_BUDGET_INSTRUCTION_LAYOUTS;
35981
35991
  exports2.ComputeBudgetInstruction = ComputeBudgetInstruction;
35982
35992
  exports2.ComputeBudgetProgram = ComputeBudgetProgram4;
35983
- exports2.Connection = Connection5;
35993
+ exports2.Connection = Connection6;
35984
35994
  exports2.Ed25519Program = Ed25519Program;
35985
35995
  exports2.Enum = Enum;
35986
35996
  exports2.EpochSchedule = EpochSchedule;
@@ -35998,7 +36008,7 @@ Message: ${transactionMessage}.
35998
36008
  exports2.NonceAccount = NonceAccount;
35999
36009
  exports2.PACKET_DATA_SIZE = PACKET_DATA_SIZE;
36000
36010
  exports2.PUBLIC_KEY_LENGTH = PUBLIC_KEY_LENGTH2;
36001
- exports2.PublicKey = PublicKey51;
36011
+ exports2.PublicKey = PublicKey52;
36002
36012
  exports2.SIGNATURE_LENGTH_IN_BYTES = SIGNATURE_LENGTH_IN_BYTES;
36003
36013
  exports2.SOLANA_SCHEMA = SOLANA_SCHEMA;
36004
36014
  exports2.STAKE_CONFIG_ID = STAKE_CONFIG_ID;
@@ -36092,19 +36102,19 @@ var require_file_uri_to_path = __commonJS({
36092
36102
  // node_modules/bindings/bindings.js
36093
36103
  var require_bindings = __commonJS({
36094
36104
  "node_modules/bindings/bindings.js"(exports2, module2) {
36095
- var fs2 = require("fs");
36105
+ var fs3 = require("fs");
36096
36106
  var path3 = require("path");
36097
36107
  var fileURLToPath = require_file_uri_to_path();
36098
36108
  var join4 = path3.join;
36099
36109
  var dirname = path3.dirname;
36100
- var exists = fs2.accessSync && function(path4) {
36110
+ var exists = fs3.accessSync && function(path4) {
36101
36111
  try {
36102
- fs2.accessSync(path4);
36112
+ fs3.accessSync(path4);
36103
36113
  } catch (e) {
36104
36114
  return false;
36105
36115
  }
36106
36116
  return true;
36107
- } || fs2.existsSync || path3.existsSync;
36117
+ } || fs3.existsSync || path3.existsSync;
36108
36118
  var defaults = {
36109
36119
  arrow: process.env.NODE_BINDINGS_ARROW || " \u2192 ",
36110
36120
  compiled: process.env.NODE_BINDINGS_COMPILED_DIR || "compiled",
@@ -37826,6 +37836,117 @@ function configInvalidError(reason) {
37826
37836
  retryable: false
37827
37837
  });
37828
37838
  }
37839
+ function privyNotConfiguredError() {
37840
+ return new ByrealError({
37841
+ code: ErrorCodes.PRIVY_NOT_CONFIGURED,
37842
+ type: "AUTH",
37843
+ message: "Privy signing is not configured. The --execute flag requires a Privy agent token and proxy URL.",
37844
+ suggestions: [
37845
+ {
37846
+ action: "setup-realclaw",
37847
+ description: "Place ~/.openclaw/realclaw-config.json with baseUrl and wallets[]"
37848
+ },
37849
+ {
37850
+ action: "setup-legacy",
37851
+ description: "Or place ~/.openclaw/agent_token plus a Privy proxy URL in ~/.config/byreal/config.json",
37852
+ command: "byreal-cli config set privy_proxy_url <url>"
37853
+ },
37854
+ {
37855
+ action: "fallback-unsigned",
37856
+ description: "Or drop --execute to keep the default behavior of emitting an unsigned transaction for an external signer"
37857
+ }
37858
+ ],
37859
+ retryable: false
37860
+ });
37861
+ }
37862
+ function privyWalletNotFoundError(walletAddress) {
37863
+ return new ByrealError({
37864
+ code: ErrorCodes.PRIVY_WALLET_NOT_FOUND,
37865
+ type: "AUTH",
37866
+ message: `No Privy agent token found for wallet address ${walletAddress}.`,
37867
+ details: { walletAddress },
37868
+ suggestions: [
37869
+ {
37870
+ action: "check-config",
37871
+ description: 'Confirm ~/.openclaw/realclaw-config.json has a wallets[] entry with type="solana" matching this address'
37872
+ },
37873
+ {
37874
+ action: "fallback-unsigned",
37875
+ description: "Or drop --execute to skip Privy signing and emit an unsigned transaction (the default)"
37876
+ }
37877
+ ],
37878
+ retryable: false
37879
+ });
37880
+ }
37881
+ function privyAuthError(message) {
37882
+ return new ByrealError({
37883
+ code: ErrorCodes.PRIVY_AUTH_FAILED,
37884
+ type: "AUTH",
37885
+ message: `Privy authentication failed: ${message}`,
37886
+ suggestions: [
37887
+ {
37888
+ action: "check-token",
37889
+ description: "Verify that your agent token is valid and not expired. Tokens are revoked after grant revocation."
37890
+ }
37891
+ ],
37892
+ retryable: false
37893
+ });
37894
+ }
37895
+ function privyBadRequestError(message) {
37896
+ return new ByrealError({
37897
+ code: ErrorCodes.PRIVY_BAD_REQUEST,
37898
+ type: "VALIDATION",
37899
+ message: `Privy proxy rejected request: ${message}`,
37900
+ retryable: false
37901
+ });
37902
+ }
37903
+ function privyRateLimitedError() {
37904
+ return new ByrealError({
37905
+ code: ErrorCodes.PRIVY_RATE_LIMITED,
37906
+ type: "NETWORK",
37907
+ message: "Privy proxy rate-limited the request. Please retry later.",
37908
+ retryable: true
37909
+ });
37910
+ }
37911
+ function privyUpstreamError(message, retryable = true) {
37912
+ return new ByrealError({
37913
+ code: ErrorCodes.PRIVY_UPSTREAM_ERROR,
37914
+ type: "NETWORK",
37915
+ message: `Privy proxy upstream error: ${message}`,
37916
+ retryable
37917
+ });
37918
+ }
37919
+ function privyTimeoutError(timeoutMs) {
37920
+ return new ByrealError({
37921
+ code: ErrorCodes.PRIVY_TIMEOUT,
37922
+ type: "NETWORK",
37923
+ message: `Privy proxy did not respond within ${timeoutMs}ms.`,
37924
+ retryable: true
37925
+ });
37926
+ }
37927
+ function privyBusinessError(retCode, retMsg) {
37928
+ return new ByrealError({
37929
+ code: ErrorCodes.PRIVY_BUSINESS_ERROR,
37930
+ type: "BUSINESS",
37931
+ message: `Privy business error retCode=${retCode}: ${retMsg}`,
37932
+ details: { retCode, retMsg },
37933
+ retryable: false
37934
+ });
37935
+ }
37936
+ function conflictingFlagsError(flagA, flagB) {
37937
+ return new ByrealError({
37938
+ code: ErrorCodes.INVALID_PARAMETER,
37939
+ type: "VALIDATION",
37940
+ message: `Conflicting flags: ${flagA} and ${flagB} cannot be used together.`,
37941
+ suggestions: [
37942
+ {
37943
+ action: "pick-one",
37944
+ description: `Use either ${flagA} or ${flagB}, not both.`
37945
+ }
37946
+ ],
37947
+ retryable: false
37948
+ });
37949
+ }
37829
37950
  function formatErrorForOutput(error) {
37830
37951
  if (error instanceof ByrealError) {
37831
37952
  return {
@@ -37860,6 +37981,15 @@ var init_errors = __esm({
37860
37981
  POSITION_NOT_FOUND: "POSITION_NOT_FOUND",
37861
37982
  // Auth errors
37862
37983
  MISSING_WALLET_ADDRESS: "MISSING_WALLET_ADDRESS",
37984
+ // Privy signing errors
37985
+ PRIVY_NOT_CONFIGURED: "PRIVY_NOT_CONFIGURED",
37986
+ PRIVY_WALLET_NOT_FOUND: "PRIVY_WALLET_NOT_FOUND",
37987
+ PRIVY_AUTH_FAILED: "PRIVY_AUTH_FAILED",
37988
+ PRIVY_BAD_REQUEST: "PRIVY_BAD_REQUEST",
37989
+ PRIVY_RATE_LIMITED: "PRIVY_RATE_LIMITED",
37990
+ PRIVY_UPSTREAM_ERROR: "PRIVY_UPSTREAM_ERROR",
37991
+ PRIVY_TIMEOUT: "PRIVY_TIMEOUT",
37992
+ PRIVY_BUSINESS_ERROR: "PRIVY_BUSINESS_ERROR",
37863
37993
  // Config errors
37864
37994
  CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
37865
37995
  CONFIG_INVALID: "CONFIG_INVALID",
@@ -37956,6 +38086,12 @@ function loadConfig() {
37956
38086
  ...parsed.defaults || {}
37957
38087
  }
37958
38088
  };
38089
+ if (typeof parsed.privy_proxy_url === "string" && parsed.privy_proxy_url) {
38090
+ config3.privy_proxy_url = parsed.privy_proxy_url;
38091
+ }
38092
+ if (typeof parsed.privy_api_base_path === "string" && parsed.privy_api_base_path) {
38093
+ config3.privy_api_base_path = parsed.privy_api_base_path;
38094
+ }
37959
38095
  return ok(config3);
37960
38096
  } catch (e) {
37961
38097
  if (e instanceof SyntaxError) {
@@ -38044,6 +38180,20 @@ function validateConfigValue(key, value) {
38044
38180
  }
38045
38181
  return ok(num);
38046
38182
  }
38183
+ case "privy_proxy_url": {
38184
+ try {
38185
+ new URL(value);
38186
+ return ok(value.replace(/\/+$/, ""));
38187
+ } catch {
38188
+ return err(validationError("privy_proxy_url must be a valid URL", "privy_proxy_url"));
38189
+ }
38190
+ }
38191
+ case "privy_api_base_path": {
38192
+ if (!value.startsWith("/")) {
38193
+ return err(validationError("privy_api_base_path must start with /", "privy_api_base_path"));
38194
+ }
38195
+ return ok(value.replace(/\/+$/, ""));
38196
+ }
38047
38197
  default:
38048
38198
  return ok(value);
38049
38199
  }
@@ -38062,7 +38212,9 @@ var init_config = __esm({
38062
38212
  "rpc_url",
38063
38213
  "cluster",
38064
38214
  "defaults.priority_fee_micro_lamports",
38065
- "defaults.slippage_bps"
38215
+ "defaults.slippage_bps",
38216
+ "privy_proxy_url",
38217
+ "privy_api_base_path"
38066
38218
  ]);
38067
38219
  }
38068
38220
  });
@@ -42376,33 +42528,33 @@ var init_constants4 = __esm({
42376
42528
  });
42377
42529
 
42378
42530
  // node_modules/@byreal-io/byreal-clmm-sdk/node_modules/@solana/spl-token/lib/esm/errors.js
42379
- var TokenError, TokenAccountNotFoundError, TokenInvalidAccountOwnerError, TokenInvalidAccountSizeError, TokenInvalidMintError;
42531
+ var TokenError2, TokenAccountNotFoundError2, TokenInvalidAccountOwnerError2, TokenInvalidAccountSizeError2, TokenInvalidMintError2;
42380
42532
  var init_errors2 = __esm({
42381
42533
  "node_modules/@byreal-io/byreal-clmm-sdk/node_modules/@solana/spl-token/lib/esm/errors.js"() {
42382
- TokenError = class extends Error {
42534
+ TokenError2 = class extends Error {
42383
42535
  constructor(message) {
42384
42536
  super(message);
42385
42537
  }
42386
42538
  };
42387
- TokenAccountNotFoundError = class extends TokenError {
42539
+ TokenAccountNotFoundError2 = class extends TokenError2 {
42388
42540
  constructor() {
42389
42541
  super(...arguments);
42390
42542
  this.name = "TokenAccountNotFoundError";
42391
42543
  }
42392
42544
  };
42393
- TokenInvalidAccountOwnerError = class extends TokenError {
42545
+ TokenInvalidAccountOwnerError2 = class extends TokenError2 {
42394
42546
  constructor() {
42395
42547
  super(...arguments);
42396
42548
  this.name = "TokenInvalidAccountOwnerError";
42397
42549
  }
42398
42550
  };
42399
- TokenInvalidAccountSizeError = class extends TokenError {
42551
+ TokenInvalidAccountSizeError2 = class extends TokenError2 {
42400
42552
  constructor() {
42401
42553
  super(...arguments);
42402
42554
  this.name = "TokenInvalidAccountSizeError";
42403
42555
  }
42404
42556
  };
42405
- TokenInvalidMintError = class extends TokenError {
42557
+ TokenInvalidMintError2 = class extends TokenError2 {
42406
42558
  constructor() {
42407
42559
  super(...arguments);
42408
42560
  this.name = "TokenInvalidMintError";
@@ -43237,20 +43389,20 @@ var init_extensionType = __esm({
43237
43389
  // node_modules/@byreal-io/byreal-clmm-sdk/node_modules/@solana/spl-token/lib/esm/state/mint.js
43238
43390
  function unpackMint(address, info, programId = TOKEN_PROGRAM_ID2) {
43239
43391
  if (!info)
43240
- throw new TokenAccountNotFoundError();
43392
+ throw new TokenAccountNotFoundError2();
43241
43393
  if (!info.owner.equals(programId))
43242
- throw new TokenInvalidAccountOwnerError();
43394
+ throw new TokenInvalidAccountOwnerError2();
43243
43395
  if (info.data.length < MINT_SIZE2)
43244
- throw new TokenInvalidAccountSizeError();
43396
+ throw new TokenInvalidAccountSizeError2();
43245
43397
  const rawMint = MintLayout2.decode(info.data.slice(0, MINT_SIZE2));
43246
43398
  let tlvData = Buffer.alloc(0);
43247
43399
  if (info.data.length > MINT_SIZE2) {
43248
43400
  if (info.data.length <= ACCOUNT_SIZE2)
43249
- throw new TokenInvalidAccountSizeError();
43401
+ throw new TokenInvalidAccountSizeError2();
43250
43402
  if (info.data.length === MULTISIG_SIZE)
43251
- throw new TokenInvalidAccountSizeError();
43403
+ throw new TokenInvalidAccountSizeError2();
43252
43404
  if (info.data[ACCOUNT_SIZE2] != AccountType.Mint)
43253
- throw new TokenInvalidMintError();
43405
+ throw new TokenInvalidMintError2();
43254
43406
  tlvData = info.data.slice(ACCOUNT_SIZE2 + ACCOUNT_TYPE_SIZE);
43255
43407
  }
43256
43408
  return {
@@ -62373,9 +62525,9 @@ var require_workspace = __commonJS({
62373
62525
  programName = (0, camelcase_1.default)(programName);
62374
62526
  if (workspaceCache[programName])
62375
62527
  return workspaceCache[programName];
62376
- const fs2 = require("fs");
62528
+ const fs3 = require("fs");
62377
62529
  const path3 = require("path");
62378
- const anchorToml = toml.parse(fs2.readFileSync("Anchor.toml"));
62530
+ const anchorToml = toml.parse(fs3.readFileSync("Anchor.toml"));
62379
62531
  const clusterId = anchorToml.provider.cluster;
62380
62532
  const programs = (_a = anchorToml.programs) === null || _a === void 0 ? void 0 : _a[clusterId];
62381
62533
  let programEntry;
@@ -62389,16 +62541,16 @@ var require_workspace = __commonJS({
62389
62541
  programId = programEntry.address;
62390
62542
  } else {
62391
62543
  const idlDirPath = path3.join("target", "idl");
62392
- const fileName = fs2.readdirSync(idlDirPath).find((name) => (0, camelcase_1.default)(path3.parse(name).name) === programName);
62544
+ const fileName = fs3.readdirSync(idlDirPath).find((name) => (0, camelcase_1.default)(path3.parse(name).name) === programName);
62393
62545
  if (!fileName) {
62394
62546
  throw new Error(`Failed to find IDL of program \`${programName}\``);
62395
62547
  }
62396
62548
  idlPath = path3.join(idlDirPath, fileName);
62397
62549
  }
62398
- if (!fs2.existsSync(idlPath)) {
62550
+ if (!fs3.existsSync(idlPath)) {
62399
62551
  throw new Error(`${idlPath} doesn't exist. Did you run \`anchor build\`?`);
62400
62552
  }
62401
- const idl = JSON.parse(fs2.readFileSync(idlPath));
62553
+ const idl = JSON.parse(fs3.readFileSync(idlPath));
62402
62554
  if (programId) {
62403
62555
  idl.address = programId;
62404
62556
  }
@@ -83198,6 +83350,19 @@ var ASSOCIATED_TOKEN_PROGRAM_ID = new import_web3.PublicKey("ATokenGPvbdGVxr1b2h
83198
83350
  var NATIVE_MINT = new import_web3.PublicKey("So11111111111111111111111111111111111111112");
83199
83351
  var NATIVE_MINT_2022 = new import_web3.PublicKey("9pan9bMn5HatX4EJdBwg9VgCa7Uz5HL8N1m5D3NdXejP");
83200
83352
 
83353
+ // node_modules/@solana/spl-token/lib/esm/errors.js
83354
+ var TokenError = class extends Error {
83355
+ constructor(message) {
83356
+ super(message);
83357
+ }
83358
+ };
83359
+ var TokenOwnerOffCurveError = class extends TokenError {
83360
+ constructor() {
83361
+ super(...arguments);
83362
+ this.name = "TokenOwnerOffCurveError";
83363
+ }
83364
+ };
83365
+
83201
83366
  // node_modules/@solana/spl-token/lib/esm/instructions/types.js
83202
83367
  var TokenInstruction;
83203
83368
  (function(TokenInstruction3) {
@@ -83303,6 +83468,12 @@ var MintLayout = (0, import_buffer_layout5.struct)([
83303
83468
  publicKey("freezeAuthority")
83304
83469
  ]);
83305
83470
  var MINT_SIZE = MintLayout.span;
83471
+ function getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve = false, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
83472
+ if (!allowOwnerOffCurve && !import_web34.PublicKey.isOnCurve(owner.toBuffer()))
83473
+ throw new TokenOwnerOffCurveError();
83474
+ const [address] = import_web34.PublicKey.findProgramAddressSync([owner.toBuffer(), programId.toBuffer(), mint.toBuffer()], associatedTokenProgramId);
83475
+ return address;
83476
+ }
83306
83477
 
83307
83478
  // node_modules/@solana/spl-token/lib/esm/instructions/closeAccount.js
83308
83479
  var import_buffer_layout6 = __toESM(require_Layout(), 1);
@@ -84761,6 +84932,30 @@ init_config();
84761
84932
  var import_cli_table3 = __toESM(require_cli_table3(), 1);
84762
84933
  init_constants();
84763
84934
 
84935
+ // src/core/confirm.ts
84936
+ init_errors();
84937
+ function resolveExecutionMode(options) {
84938
+ if (options.dryRun && options.execute) {
84939
+ throw conflictingFlagsError("--dry-run", "--execute");
84940
+ }
84941
+ if (options.dryRun) return "dry-run";
84942
+ if (options.execute) return "execute";
84943
+ return "unsigned-tx";
84944
+ }
84945
+ function printDryRunBanner() {
84946
+ console.error(source_default.yellow.bold("\n[DRY RUN] No transaction will be generated\n"));
84947
+ }
84948
+ function printPrivySignBanner() {
84949
+ console.error(
84950
+ source_default.green.bold(
84951
+ "\n[PRIVY SIGN] Signing and broadcasting via Privy wallet\n"
84952
+ )
84953
+ );
84954
+ }
84955
+
84956
+ // src/cli/output/formatters.ts
84957
+ init_errors();
84958
+
84764
84959
  // src/core/amounts.ts
84765
84960
  function uiToRaw(uiAmount, decimals) {
84766
84961
  const parts = uiAmount.split(".");
@@ -84797,6 +84992,18 @@ function outputJson(data, startTime) {
84797
84992
  function outputErrorJson(error) {
84798
84993
  console.log(JSON.stringify({ success: false, error }, null, 2));
84799
84994
  }
84995
+ function safeResolveExecutionMode(options, format) {
84996
+ try {
84997
+ return resolveExecutionMode(options);
84998
+ } catch (e) {
84999
+ if (e instanceof ByrealError) {
85000
+ if (format === "json") outputErrorJson(e.toJSON());
85001
+ else outputErrorTable(e.toJSON());
85002
+ process.exit(1);
85003
+ }
85004
+ throw e;
85005
+ }
85006
+ }
84800
85007
  function createTable(headers) {
84801
85008
  return new import_cli_table3.default({
84802
85009
  head: headers.map((h) => source_default.cyan.bold(h)),
@@ -85032,6 +85239,12 @@ function outputConfigList(config3) {
85032
85239
  ["defaults.priority_fee_micro_lamports", String(config3.defaults.priority_fee_micro_lamports)],
85033
85240
  ["defaults.slippage_bps", String(config3.defaults.slippage_bps)]
85034
85241
  );
85242
+ if (config3.privy_proxy_url) {
85243
+ table.push(["privy_proxy_url", config3.privy_proxy_url]);
85244
+ }
85245
+ if (config3.privy_api_base_path) {
85246
+ table.push(["privy_api_base_path", config3.privy_api_base_path]);
85247
+ }
85035
85248
  console.log(table.toString());
85036
85249
  }
85037
85250
  function outputConfigValue(key, value) {
@@ -85528,6 +85741,31 @@ function outputRewardOrderResult(result) {
85528
85741
  console.log();
85529
85742
  }
85530
85743
  }
85744
+ function outputTransactionResult(signature) {
85745
+ console.log(source_default.green("\n Transaction submitted (not yet finalized)"));
85746
+ console.log(source_default.gray(` Signature: ${signature}`));
85747
+ console.log(source_default.blue(` https://solscan.io/tx/${signature}
85748
+ `));
85749
+ }
85750
+ function outputMultiBroadcastResult(result) {
85751
+ const total = result.results.length;
85752
+ const headline = result.failCount === 0 ? source_default.green(`
85753
+ ${total} transactions submitted (not yet finalized)`) : source_default.yellow(
85754
+ `
85755
+ ${result.successCount}/${total} transactions submitted (${result.failCount} failed at submission)`
85756
+ );
85757
+ console.log(headline);
85758
+ for (const r of result.results) {
85759
+ const idx = `[${r.index + 1}/${total}]`;
85760
+ if (r.signature) {
85761
+ console.log(source_default.gray(` ${idx} ${r.signature}`));
85762
+ console.log(source_default.blue(` ${idx} https://solscan.io/tx/${r.signature}`));
85763
+ } else {
85764
+ console.log(source_default.red(` ${idx} failed: ${r.error ?? "unknown error"}`));
85765
+ }
85766
+ }
85767
+ console.log();
85768
+ }
85531
85769
 
85532
85770
  // src/cli/commands/pools.ts
85533
85771
  async function listPools2(options, globalOptions) {
@@ -86085,12 +86323,38 @@ byreal-cli catalog show dex.pool.list
86085
86323
  | -v, --version | Show version |
86086
86324
  | -h, --help | Show help |
86087
86325
 
86326
+ ## Three Execution Modes (write commands)
86327
+
86328
+ Every write command (\`swap execute\`, \`positions open/close/increase/decrease/claim/claim-rewards/claim-bonus/copy\`, all plugin write commands like \`jup swap\` / \`dflow swap\` / \`titan swap\` / \`kamino deposit/withdraw\` / \`rent reclaim\` / \`sweep execute\`) supports three modes:
86329
+
86330
+ | Mode | Flag | What it does | Output |
86331
+ |------|------|--------------|--------|
86332
+ | **unsigned-tx** (default) | (none) | Emit base64 unsigned transaction(s) so an external signer can take over | \`{ unsignedTransactions: [...] }\` (identical to the pre-Privy CLI) |
86333
+ | **execute** | \`--execute\` | Sign + broadcast on-chain via Privy proxy | \`{ signature: "<txid>", explorer: "https://solscan.io/tx/<txid>" }\` (single tx) or \`{ results: [{index, signature?, error?}], successCount, failCount }\` (multi-tx) |
86334
+ | **dry-run** | \`--dry-run\` | Preview only \u2014 no transaction generated, no signing | Preview JSON / table |
86335
+
86336
+ \`--dry-run\` and \`--execute\` are mutually exclusive (CLI errors on both).
86337
+
86338
+ **Backward-compatible default**: every write command still emits unsigned transactions by default. To sign + broadcast through the Byreal Privy proxy, add \`--execute\` explicitly.
86339
+
86340
+ ### Privy Configuration
86341
+
86342
+ \`--execute\` requires a Privy agent token + proxy URL. Sources (highest precedence first):
86343
+
86344
+ 1. Env vars: \`AGENT_TOKEN\`, \`PRIVY_PROXY_URL\`, \`PRIVY_API_BASE_PATH\`
86345
+ 2. \`~/.openclaw/realclaw-config.json\` \u2014 \`{ baseUrl, apiBasePath?, wallets: [{ address, token, type: "solana" | "evm" }] }\`. The CLI picks the wallet whose \`address\` matches \`--wallet-address\` and whose \`type === "solana"\`.
86346
+ 3. Legacy: \`~/.openclaw/agent_token\` (single-token file) plus \`~/.config/byreal/config.json#privy_proxy_url\` (or \`byreal-cli config set privy_proxy_url <url>\`).
86347
+
86348
+ If Privy is not configured, \`--execute\` fails with \`PRIVY_NOT_CONFIGURED\` and includes actionable suggestions (configure realclaw / configure legacy / drop \`--execute\` to keep the default unsigned output). The CLI never silently degrades.
86349
+
86350
+ If \`--wallet-address\` does not match any \`type=solana\` entry in \`realclaw-config.json\`, the CLI fails with \`PRIVY_WALLET_NOT_FOUND\` (rather than fall back to a different wallet's token).
86351
+
86088
86352
  ## Hard Constraints (Do NOT violate)
86089
86353
 
86090
86354
  1. **\`-o json\` only for parsing** \u2014 when you need to extract values for the next command. When the user wants to **see** results, omit it \u2014 the CLI has built-in tables, K-line charts, and formatted analysis. Never fetch JSON then re-draw them yourself.
86091
86355
  2. **Never truncate on-chain data** \u2014 always display the FULL string for: transaction signatures, mint addresses, pool addresses, NFT addresses, wallet addresses. Never use \`xxx...yyy\`.
86092
- 3. **Never request or display private keys** \u2014 the CLI does not handle private keys. All write commands output unsigned transactions.
86093
- 4. **\`--wallet-address\` required for all write commands** \u2014 the user must provide their Solana wallet public key. No local wallet setup or keypair storage. Preview with \`--dry-run\` first, remove \`--dry-run\` to generate the unsigned transaction.
86356
+ 3. **Never request or display private keys** \u2014 the CLI does not store private keys locally. Signing is performed by the Privy proxy via the agent token; private keys live in Privy.
86357
+ 4. **\`--wallet-address\` required for all write commands** \u2014 the user must provide their Solana wallet public key. Default mode emits an unsigned transaction (back-compat); add \`--execute\` to sign + broadcast via Privy, or \`--dry-run\` to preview.
86094
86358
  5. **Large amounts (> $10,000)**: Require explicit user confirmation
86095
86359
  6. **High slippage (> 200 bps)**: Warn user before proceeding
86096
86360
  7. **Token amounts use UI format** \u2014 \`--amount 0.1\` means 0.1 tokens, not lamports. The CLI auto-resolves decimals from mint address. Never convert manually. Use \`--raw\` only for raw units.
@@ -86117,7 +86381,8 @@ Present on-chain data first, then external context, then synthesize how external
86117
86381
  | List tokens | \`byreal-cli tokens list\` |
86118
86382
  | Global stats | \`byreal-cli overview\` |
86119
86383
  | Swap preview | \`byreal-cli swap execute --input-mint <mint> --output-mint <mint> --amount <amount> --dry-run\` |
86120
- | Swap execute | \`byreal-cli swap execute --input-mint <mint> --output-mint <mint> --amount <amount> --wallet-address <addr>\` |
86384
+ | Swap (unsigned) | \`byreal-cli swap execute --input-mint <mint> --output-mint <mint> --amount <amount> --wallet-address <addr>\` |
86385
+ | Swap (sign + broadcast) | \`byreal-cli swap execute --input-mint <mint> --output-mint <mint> --amount <amount> --wallet-address <addr> --execute\` |
86121
86386
  | List positions | \`byreal-cli positions list\` |
86122
86387
  | Open position (USD) | \`byreal-cli positions open --pool <addr> --price-lower <p> --price-upper <p> --amount-usd <usd> --wallet-address <addr>\` |
86123
86388
  | Open position (token) | \`byreal-cli positions open --pool <addr> --price-lower <p> --price-upper <p> --base <token> --amount <amount> --wallet-address <addr>\` |
@@ -86175,13 +86440,23 @@ For detailed parameter info on any command, run: \`byreal-cli catalog show <capa
86175
86440
  - **Incentive rewards** \u2192 \`positions claim-rewards\` (team-added pool incentives)
86176
86441
  - **Copy bonus** \u2192 \`positions claim-bonus\` (referral rewards from copy trading)
86177
86442
 
86178
- ### Claim Rewards / Bonus: 3-Step Flow
86179
- \`claim-rewards\` and \`claim-bonus\` require a multi-step flow (backend co-signs):
86180
- 1. **Preview**: \`positions claim-rewards --dry-run --wallet-address <addr> -o json\`
86181
- 2. **Generate unsigned tx**: \`positions claim-rewards --wallet-address <addr> -o json\` \u2192 returns \`orderCode\` + \`unsignedTransactions\` (each with \`txPayload\`, \`txCode\`)
86182
- 3. **Submit signed tx**: After wallet signs each \`txPayload\`, call \`positions submit-rewards --order-code "ORD_xxx" --signed-payloads '[{"txCode":"TX_xxx","poolAddress":"...","signedTx":"<base64>"}]' --wallet-address <addr>\`
86443
+ ### Claim Rewards / Bonus: One-Shot Atomic Command (with --execute)
86444
+
86445
+ When \`--execute\` is set, \`claim-rewards\` and \`claim-bonus\` are atomic. The CLI internally does encode \u2192 Privy sign \u2192 backend submit, returns the final order result. **Do not chain skills or call \`submit-rewards\` manually when running with \`--execute\`.**
86446
+
86447
+ \`\`\`
86448
+ byreal-cli positions claim-rewards --wallet-address <addr> --execute -o json
86449
+ # \u2192 { orderCode, txList: [...], claimTokenList: [...] }
86450
+ \`\`\`
86451
+
86452
+ \`txList\` contains the on-chain signatures the backend broadcast. \`claimTokenList\` shows which tokens were claimed.
86183
86453
 
86184
- **Critical**: Do NOT skip Step 3 \u2014 without \`submit-rewards\`, signed transactions are never broadcast. The \`orderCode\` ties steps together. For \`claim-bonus\`: same flow, replace \`claim-rewards\` with \`claim-bonus\` in Step 1-2.
86454
+ **Default multi-step flow** (no \`--execute\` flag \u2014 back-compat for external signers):
86455
+ 1. \`positions claim-rewards --wallet-address <addr> -o json\` \u2192 returns \`{ orderCode, unsignedTransactions: [{ poolAddress, txPayload, txCode, tokens }] }\`
86456
+ 2. External signer signs each \`txPayload\`
86457
+ 3. \`positions submit-rewards --order-code <orderCode> --signed-payloads '[{"txCode":"...","poolAddress":"...","signedTx":"<base64>"}]' --wallet-address <addr>\`
86458
+
86459
+ The multi-step flow is the default for backward compatibility; if Privy is configured, prefer \`--execute\` for the one-shot atomic command.
86185
86460
 
86186
86461
  ### Copy Bonus Epochs
86187
86462
  - **Accruing**: Current epoch, bonus accumulating
@@ -86192,7 +86467,7 @@ For detailed parameter info on any command, run: \`byreal-cli catalog show <capa
86192
86467
  \`positions open --dry-run\` and \`positions increase --dry-run\` automatically check wallet balance. If insufficient, response includes \`balanceWarnings\` (deficit) and \`walletBalances\` (all available tokens) \u2014 no need to run \`wallet balance\` separately.
86193
86468
 
86194
86469
  ### Config Keys
86195
- Supported keys for \`config get/set\`: rpc_url, cluster, defaults.slippage_bps, defaults.priority_fee_micro_lamports
86470
+ Supported keys for \`config get/set\`: rpc_url, cluster, defaults.slippage_bps, defaults.priority_fee_micro_lamports, privy_proxy_url, privy_api_base_path
86196
86471
 
86197
86472
  ## Workflow: Finding Investment Opportunities
86198
86473
 
@@ -86210,7 +86485,7 @@ When the user asks about investment opportunities, potential pools, or yield far
86210
86485
  - USD budget: \`positions open --pool <id> --price-lower <p> --price-upper <p> --amount-usd <usd> --dry-run -o json\`
86211
86486
  - Token amount: \`positions open --pool <id> --price-lower <p> --price-upper <p> --base MintA --amount <amt> --dry-run -o json\`
86212
86487
  4. **If insufficient balance**: dry-run response includes \`balanceWarnings\` (deficit) + \`walletBalances\` (all tokens). Pick a swap source from ANY token in the wallet (prefer highest USD balance, stablecoins/SOL for lower slippage), swap to cover the deficit. **Wait 3-5 seconds** after swap before re-running dry-run (RPC propagation delay).
86213
- 5. **Execute**: remove \`--dry-run\`, add \`--wallet-address <addr>\` to generate the unsigned transaction
86488
+ 5. **Run for real**: drop \`--dry-run\` (keep \`--wallet-address <addr>\`). The default emits an unsigned base64 transaction \`{ unsignedTransactions: [...] }\` for an external signer (back-compat). Add \`--execute\` to sign + broadcast via Privy directly \u2192 \`{ signature, explorer }\`.
86214
86489
 
86215
86490
  ## Workflow: Increase/Decrease Liquidity
86216
86491
 
@@ -86220,12 +86495,12 @@ When user wants to add more liquidity to an existing position or partially withd
86220
86495
  1. \`byreal-cli positions list -o json\` \u2014 find the position's NFT mint address
86221
86496
  2. \`byreal-cli positions increase --nft-mint <nft-mint> --amount-usd <usd> --dry-run -o json\` \u2014 preview (includes balance check)
86222
86497
  3. If insufficient balance \u2192 swap to get required tokens (see "Insufficient Balance" workflow)
86223
- 4. \`byreal-cli positions increase --nft-mint <nft-mint> --amount-usd <usd> --wallet-address <addr> -o json\` \u2014 generate unsigned transaction
86498
+ 4. \`byreal-cli positions increase --nft-mint <nft-mint> --amount-usd <usd> --wallet-address <addr> -o json\` \u2014 emit unsigned tx (default). Add \`--execute\` to sign + broadcast via Privy.
86224
86499
 
86225
86500
  **Decrease liquidity** (partial withdrawal):
86226
86501
  1. \`byreal-cli positions list -o json\` \u2014 find the position's NFT mint address
86227
86502
  2. \`byreal-cli positions decrease --nft-mint <nft-mint> --percentage 50 --dry-run -o json\` \u2014 preview how much you'll receive
86228
- 3. \`byreal-cli positions decrease --nft-mint <nft-mint> --percentage 50 --wallet-address <addr> -o json\` \u2014 generate unsigned transaction
86503
+ 3. \`byreal-cli positions decrease --nft-mint <nft-mint> --percentage 50 --wallet-address <addr> -o json\` \u2014 emit unsigned tx (default). Add \`--execute\` to sign + broadcast via Privy.
86229
86504
 
86230
86505
  **Key distinction**: Use \`decrease\` to partially withdraw while keeping the position open. Use \`close\` to fully exit and burn the NFT.
86231
86506
 
@@ -86271,14 +86546,15 @@ When user asks vague questions like "\u6709\u4EC0\u4E48\u4ED3\u4F4D\u53EF\u4EE5
86271
86546
 
86272
86547
  Default to \`byreal-cli swap execute\`. Fall back to \`jup swap\` / \`dflow swap\` only if Byreal returns no route, or the user names an aggregator explicitly.
86273
86548
 
86274
- ## Workflow: Jupiter / DFlow Swap
86549
+ ## Workflow: Jupiter / Titan / DFlow Swap
86275
86550
 
86276
86551
  \`\`\`
86277
- byreal-cli jup swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run] --wallet-address <addr>
86278
- byreal-cli dflow swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run] --wallet-address <addr>
86552
+ byreal-cli jup swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run|--execute] --wallet-address <addr>
86553
+ byreal-cli titan swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run|--execute] --wallet-address <addr>
86554
+ byreal-cli dflow swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run|--execute] --wallet-address <addr>
86279
86555
  \`\`\`
86280
86556
 
86281
- Output: \`{ unsignedTransactions: [base64] }\`. DFlow optionally reads \`DFLOW_API_KEY\`.
86557
+ Default (no flag) emits \`{ unsignedTransactions: [base64] }\` for back-compat. \`--execute\` signs + broadcasts via Privy \u2192 output \`{ signature, explorer }\`. DFlow optionally reads \`DFLOW_API_KEY\`. Titan reads \`TITAN_AUTH_TOKEN\` if proxy unreachable.
86282
86558
 
86283
86559
  ## Workflow: Idle Yield with Kamino
86284
86560
 
@@ -86342,7 +86618,7 @@ init_constants();
86342
86618
 
86343
86619
  // src/plugins/jupiter/commands.ts
86344
86620
  var import_cli_table32 = __toESM(require_cli_table3(), 1);
86345
- var import_web3113 = __toESM(require_index_cjs(), 1);
86621
+ var import_web3114 = __toESM(require_index_cjs(), 1);
86346
86622
  init_solana();
86347
86623
 
86348
86624
  // src/core/token-registry.ts
@@ -86391,17 +86667,311 @@ async function resolveDecimals(mint) {
86391
86667
  return decimals;
86392
86668
  }
86393
86669
 
86394
- // src/core/confirm.ts
86395
- function resolveExecutionMode(options) {
86396
- if (options.dryRun) return "dry-run";
86397
- return "execute";
86670
+ // src/plugins/jupiter/commands.ts
86671
+ init_errors();
86672
+
86673
+ // src/privy/config.ts
86674
+ var fs2 = __toESM(require("node:fs"), 1);
86675
+ init_constants();
86676
+ init_config();
86677
+ init_security();
86678
+ function loadRealclawConfig() {
86679
+ const path3 = expandTilde(REALCLAW_CONFIG_PATH);
86680
+ if (!fs2.existsSync(path3)) return null;
86681
+ try {
86682
+ const content = fs2.readFileSync(path3, "utf-8");
86683
+ const parsed = JSON.parse(content);
86684
+ if (!parsed || typeof parsed !== "object") return null;
86685
+ const out = {};
86686
+ const obj = parsed;
86687
+ if (typeof obj.baseUrl === "string" && obj.baseUrl) out.baseUrl = obj.baseUrl;
86688
+ if (typeof obj.apiBasePath === "string" && obj.apiBasePath)
86689
+ out.apiBasePath = obj.apiBasePath;
86690
+ if (Array.isArray(obj.wallets)) {
86691
+ const wallets = [];
86692
+ for (const raw of obj.wallets) {
86693
+ if (!raw || typeof raw !== "object") continue;
86694
+ const w = raw;
86695
+ if (typeof w.address === "string" && typeof w.token === "string" && (w.type === "solana" || w.type === "evm")) {
86696
+ wallets.push({
86697
+ address: w.address,
86698
+ token: w.token,
86699
+ type: w.type
86700
+ });
86701
+ }
86702
+ }
86703
+ if (wallets.length > 0) out.wallets = wallets;
86704
+ }
86705
+ return out;
86706
+ } catch {
86707
+ return null;
86708
+ }
86398
86709
  }
86399
- function printDryRunBanner() {
86400
- console.log(source_default.yellow.bold("\n[DRY RUN] No transaction will be generated\n"));
86710
+ function loadSkillAgentTokenConfig() {
86711
+ const path3 = expandTilde(SKILL_AGENT_TOKEN_CONFIG_PATH);
86712
+ if (!fs2.existsSync(path3)) return null;
86713
+ try {
86714
+ const content = fs2.readFileSync(path3, "utf-8");
86715
+ const parsed = JSON.parse(content);
86716
+ if (!parsed || typeof parsed !== "object") return null;
86717
+ const obj = parsed;
86718
+ const out = {};
86719
+ if (typeof obj.baseUrl === "string" && obj.baseUrl) out.baseUrl = obj.baseUrl;
86720
+ if (typeof obj.apiBasePath === "string" && obj.apiBasePath)
86721
+ out.apiBasePath = obj.apiBasePath;
86722
+ return out;
86723
+ } catch {
86724
+ return null;
86725
+ }
86726
+ }
86727
+ function loadAgentToken(walletAddress) {
86728
+ const envToken = AGENT_TOKEN_ENV?.trim();
86729
+ if (envToken) return envToken;
86730
+ const realclaw = loadRealclawConfig();
86731
+ if (realclaw?.wallets && realclaw.wallets.length > 0) {
86732
+ const solWallets = realclaw.wallets.filter((w) => w.type === "solana");
86733
+ if (solWallets.length > 0) {
86734
+ if (walletAddress) {
86735
+ const match = solWallets.find((w) => w.address === walletAddress);
86736
+ if (match) return match.token;
86737
+ return null;
86738
+ }
86739
+ return solWallets[0].token;
86740
+ }
86741
+ }
86742
+ try {
86743
+ const path3 = expandTilde(LEGACY_AGENT_TOKEN_PATH);
86744
+ if (fs2.existsSync(path3)) {
86745
+ const content = fs2.readFileSync(path3, "utf-8").trim();
86746
+ if (content.length > 0) return content;
86747
+ }
86748
+ } catch {
86749
+ }
86750
+ return null;
86751
+ }
86752
+ function loadPrivyConfig() {
86753
+ let proxyUrl;
86754
+ let apiBasePath;
86755
+ if (PRIVY_PROXY_URL_ENV) proxyUrl = PRIVY_PROXY_URL_ENV;
86756
+ if (PRIVY_API_BASE_PATH_ENV) apiBasePath = PRIVY_API_BASE_PATH_ENV;
86757
+ if (!proxyUrl || !apiBasePath) {
86758
+ const realclaw = loadRealclawConfig();
86759
+ if (realclaw) {
86760
+ if (!proxyUrl && realclaw.baseUrl) proxyUrl = realclaw.baseUrl;
86761
+ if (!apiBasePath && realclaw.apiBasePath) apiBasePath = realclaw.apiBasePath;
86762
+ }
86763
+ }
86764
+ if (!proxyUrl || !apiBasePath) {
86765
+ const skill = loadSkillAgentTokenConfig();
86766
+ if (skill) {
86767
+ if (!proxyUrl && skill.baseUrl) proxyUrl = skill.baseUrl;
86768
+ if (!apiBasePath && skill.apiBasePath) apiBasePath = skill.apiBasePath;
86769
+ }
86770
+ }
86771
+ if (!proxyUrl || !apiBasePath) {
86772
+ const cfgResult = loadConfig();
86773
+ if (cfgResult.ok) {
86774
+ const cfg = cfgResult.value;
86775
+ if (!proxyUrl && cfg.privy_proxy_url) proxyUrl = cfg.privy_proxy_url;
86776
+ if (!apiBasePath && cfg.privy_api_base_path)
86777
+ apiBasePath = cfg.privy_api_base_path;
86778
+ }
86779
+ }
86780
+ if (!proxyUrl) return null;
86781
+ return {
86782
+ proxyUrl: proxyUrl.replace(/\/+$/, ""),
86783
+ apiBasePath: (apiBasePath || PRIVY_API_BASE_PATH_DEFAULT).replace(/\/+$/, "")
86784
+ };
86401
86785
  }
86402
86786
 
86403
- // src/plugins/jupiter/commands.ts
86787
+ // src/privy/client.ts
86788
+ init_constants();
86789
+ init_types();
86790
+ init_errors();
86791
+
86792
+ // src/privy/types.ts
86793
+ function isBgwEnvelope(env2) {
86794
+ return env2 !== null && typeof env2 === "object" && "result" in env2 && typeof env2.result === "object";
86795
+ }
86796
+ function unwrapEnvelope(env2) {
86797
+ if (isBgwEnvelope(env2)) return env2.result;
86798
+ return env2;
86799
+ }
86800
+
86801
+ // src/privy/client.ts
86802
+ var SIGN_PATH = "/sign/solana-transaction";
86803
+ var SIGN_TIMEOUT_MS = DEFAULTS.REQUEST_TIMEOUT_MS;
86804
+ async function privyPost(token, config3, path3, body) {
86805
+ const url = `${config3.proxyUrl}${config3.apiBasePath}${path3}`;
86806
+ if (process.env.DEBUG) {
86807
+ console.error(`[DEBUG] Privy POST ${url}`);
86808
+ }
86809
+ let res;
86810
+ try {
86811
+ res = await fetch(url, {
86812
+ method: "POST",
86813
+ headers: {
86814
+ "Content-Type": "application/json",
86815
+ Authorization: `Bearer ${token}`,
86816
+ "User-Agent": "byreal-cli"
86817
+ },
86818
+ body: JSON.stringify(body),
86819
+ signal: AbortSignal.timeout(SIGN_TIMEOUT_MS)
86820
+ });
86821
+ } catch (e) {
86822
+ if (e instanceof DOMException && e.name === "TimeoutError") {
86823
+ return err(privyTimeoutError(SIGN_TIMEOUT_MS));
86824
+ }
86825
+ const msg = e?.message ?? "Network error";
86826
+ return err(privyUpstreamError(msg, true));
86827
+ }
86828
+ if (res.status === 401 || res.status === 403) {
86829
+ const text = await res.text().catch(() => "");
86830
+ return err(privyAuthError(text || `HTTP ${res.status}`));
86831
+ }
86832
+ if (res.status === 422) {
86833
+ const text = await res.text().catch(() => "");
86834
+ return err(privyBadRequestError(text || `HTTP ${res.status}`));
86835
+ }
86836
+ if (res.status === 429) {
86837
+ return err(privyRateLimitedError());
86838
+ }
86839
+ if (!res.ok) {
86840
+ const text = await res.text().catch(() => "");
86841
+ return err(privyUpstreamError(`HTTP ${res.status}: ${text}`, res.status >= 500));
86842
+ }
86843
+ let raw;
86844
+ try {
86845
+ raw = await res.json();
86846
+ } catch {
86847
+ return err(privyUpstreamError("Invalid JSON response from Privy proxy"));
86848
+ }
86849
+ const envelope = unwrapEnvelope(raw);
86850
+ if (process.env.DEBUG) {
86851
+ console.error(
86852
+ `[DEBUG] Privy response: success=${envelope.success} retCode=${envelope.retCode} retMsg=${envelope.retMsg ?? ""}`
86853
+ );
86854
+ }
86855
+ if (envelope.retCode !== 0 || envelope.success === false) {
86856
+ const retMsg = envelope.retMsg ?? "";
86857
+ return err(privyBusinessError(envelope.retCode, retMsg));
86858
+ }
86859
+ if (envelope.data === null || envelope.data === void 0) {
86860
+ return err(privyUpstreamError("Empty data in Privy proxy response"));
86861
+ }
86862
+ return ok(envelope.data);
86863
+ }
86864
+ async function signTransaction(token, config3, unsignedTx) {
86865
+ const body = {
86866
+ transaction: unsignedTx,
86867
+ broadcast: false,
86868
+ strategyId: PRIVY_STRATEGY_ID,
86869
+ strategyName: PRIVY_STRATEGY_NAME
86870
+ };
86871
+ const result = await privyPost(
86872
+ token,
86873
+ config3,
86874
+ SIGN_PATH,
86875
+ body
86876
+ );
86877
+ if (!result.ok) return result;
86878
+ const nested = result.value.data?.signed_transaction;
86879
+ if (nested) return ok(nested);
86880
+ const flat = result.value.signedTransaction;
86881
+ if (flat) return ok(flat);
86882
+ return err(privyUpstreamError("No signed_transaction in Privy response"));
86883
+ }
86884
+ async function signAndBroadcast(token, config3, unsignedTx, caip2) {
86885
+ const body = {
86886
+ transaction: unsignedTx,
86887
+ broadcast: true,
86888
+ caip2,
86889
+ strategyId: PRIVY_STRATEGY_ID,
86890
+ strategyName: PRIVY_STRATEGY_NAME
86891
+ };
86892
+ const result = await privyPost(
86893
+ token,
86894
+ config3,
86895
+ SIGN_PATH,
86896
+ body
86897
+ );
86898
+ if (!result.ok) return result;
86899
+ if (!result.value.hash) {
86900
+ return err(privyUpstreamError("No transaction hash in Privy broadcast response"));
86901
+ }
86902
+ return ok(result.value.hash);
86903
+ }
86904
+
86905
+ // src/privy/execute.ts
86906
+ init_constants();
86907
+ init_types();
86404
86908
  init_errors();
86909
+ function getPrivyContext(walletAddress) {
86910
+ const config3 = loadPrivyConfig();
86911
+ if (!config3) return null;
86912
+ const token = loadAgentToken(walletAddress);
86913
+ if (!token) {
86914
+ if (walletAddress) {
86915
+ const realclaw = loadRealclawConfig();
86916
+ const hasSolWallets = realclaw?.wallets?.some((w) => w.type === "solana") ?? false;
86917
+ if (hasSolWallets) {
86918
+ throw privyWalletNotFoundError(walletAddress);
86919
+ }
86920
+ }
86921
+ return null;
86922
+ }
86923
+ return { token, config: config3, caip2: SOLANA_MAINNET_CAIP2 };
86924
+ }
86925
+ function requirePrivyContext(walletAddress) {
86926
+ const ctx = getPrivyContext(walletAddress);
86927
+ if (!ctx) throw privyNotConfiguredError();
86928
+ return ctx;
86929
+ }
86930
+ async function privyBroadcastOne(ctx, unsignedTx) {
86931
+ if (process.env.DEBUG) {
86932
+ console.error(source_default.gray("[DEBUG] Privy: signing + broadcasting transaction..."));
86933
+ }
86934
+ const r = await signAndBroadcast(ctx.token, ctx.config, unsignedTx, ctx.caip2);
86935
+ if (!r.ok) return r;
86936
+ return ok({ signature: r.value });
86937
+ }
86938
+ async function privyBroadcastMany(ctx, unsignedTxs) {
86939
+ const results = [];
86940
+ let successCount = 0;
86941
+ let failCount = 0;
86942
+ for (let i = 0; i < unsignedTxs.length; i++) {
86943
+ if (process.env.DEBUG) {
86944
+ console.error(
86945
+ source_default.gray(`[DEBUG] Privy: broadcasting tx ${i + 1}/${unsignedTxs.length}...`)
86946
+ );
86947
+ }
86948
+ const r = await signAndBroadcast(ctx.token, ctx.config, unsignedTxs[i], ctx.caip2);
86949
+ if (r.ok) {
86950
+ results.push({ index: i, signature: r.value });
86951
+ successCount++;
86952
+ } else {
86953
+ results.push({ index: i, error: r.error.message });
86954
+ failCount++;
86955
+ }
86956
+ }
86957
+ return ok({ results, successCount, failCount });
86958
+ }
86959
+ async function privySignMany(ctx, unsignedTxs) {
86960
+ const signedTxs = [];
86961
+ for (let i = 0; i < unsignedTxs.length; i++) {
86962
+ if (process.env.DEBUG) {
86963
+ console.error(
86964
+ source_default.gray(`[DEBUG] Privy: signing tx ${i + 1}/${unsignedTxs.length} (no broadcast)...`)
86965
+ );
86966
+ }
86967
+ const r = await signTransaction(ctx.token, ctx.config, unsignedTxs[i]);
86968
+ if (!r.ok) return r;
86969
+ signedTxs.push({ index: i, signedTx: r.value });
86970
+ }
86971
+ return ok({ signedTxs });
86972
+ }
86973
+
86974
+ // src/plugins/jupiter/commands.ts
86405
86975
  init_constants();
86406
86976
 
86407
86977
  // src/plugins/jupiter/api.ts
@@ -86452,7 +87022,161 @@ async function probe() {
86452
87022
  });
86453
87023
  }
86454
87024
 
87025
+ // src/core/fee-config.ts
87026
+ var import_web3113 = __toESM(require_index_cjs(), 1);
87027
+ var DEFAULT_FEE_RECIPIENT_WALLET = "48fcHTG4Y2xLSNUyH3CtLEL67ZseJyQes1trLgLtNNSp";
87028
+ var DEFAULT_FEE_BPS = 50;
87029
+ var MAJOR_MINTS = /* @__PURE__ */ new Set([
87030
+ "So11111111111111111111111111111111111111112",
87031
+ // Wrapped SOL
87032
+ "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
87033
+ // USDC
87034
+ "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
87035
+ // USDT
87036
+ "USD1ttGY1N17NEEHLmELoaybftRBUSErhqYiQzvEmuB"
87037
+ // USD1
87038
+ ]);
87039
+ function pickFeeSide(inputMint, outputMint) {
87040
+ if (MAJOR_MINTS.has(inputMint)) return { mint: inputMint, side: "input" };
87041
+ if (MAJOR_MINTS.has(outputMint)) return { mint: outputMint, side: "output" };
87042
+ return { mint: inputMint, side: "input" };
87043
+ }
87044
+ var warnedKeys = /* @__PURE__ */ new Set();
87045
+ function warnOnce(key, message) {
87046
+ if (warnedKeys.has(key)) return;
87047
+ warnedKeys.add(key);
87048
+ if (process.env.DEBUG) {
87049
+ console.error(`[fee-config] ${message}`);
87050
+ }
87051
+ }
87052
+ var ataExistsCache = /* @__PURE__ */ new Map();
87053
+ var mintProgramCache = /* @__PURE__ */ new Map();
87054
+ async function resolveMintTokenProgram(mint, connection) {
87055
+ const cached2 = mintProgramCache.get(mint);
87056
+ if (cached2) return cached2;
87057
+ try {
87058
+ const info = await connection.getAccountInfo(
87059
+ new import_web3113.PublicKey(mint),
87060
+ "confirmed"
87061
+ );
87062
+ if (!info) {
87063
+ warnOnce(
87064
+ `mint-missing:${mint}`,
87065
+ `Mint ${mint} not found on-chain \u2014 assuming legacy SPL Token`
87066
+ );
87067
+ mintProgramCache.set(mint, TOKEN_PROGRAM_ID);
87068
+ return TOKEN_PROGRAM_ID;
87069
+ }
87070
+ const owner = info.owner;
87071
+ if (!owner.equals(TOKEN_PROGRAM_ID) && !owner.equals(TOKEN_2022_PROGRAM_ID)) {
87072
+ warnOnce(
87073
+ `mint-unknown-program:${mint}`,
87074
+ `Mint ${mint} owner ${owner.toBase58()} is not a known token program \u2014 falling back to legacy`
87075
+ );
87076
+ mintProgramCache.set(mint, TOKEN_PROGRAM_ID);
87077
+ return TOKEN_PROGRAM_ID;
87078
+ }
87079
+ mintProgramCache.set(mint, owner);
87080
+ return owner;
87081
+ } catch (error) {
87082
+ warnOnce(
87083
+ `mint-rpc-error:${mint}`,
87084
+ `Failed to query mint program for ${mint} (${error.message}) \u2014 assuming legacy SPL Token`
87085
+ );
87086
+ return TOKEN_PROGRAM_ID;
87087
+ }
87088
+ }
87089
+ function getFeeConfig() {
87090
+ const rawWallet = process.env.FEE_RECIPIENT_WALLET;
87091
+ const rawBps = process.env.FEE_BPS;
87092
+ const rawBpsTrimmed = typeof rawBps === "string" ? rawBps.trim() : "";
87093
+ if (rawBpsTrimmed === "0") return null;
87094
+ const walletStr = typeof rawWallet === "string" && rawWallet.trim().length > 0 ? rawWallet.trim() : DEFAULT_FEE_RECIPIENT_WALLET;
87095
+ const bpsStr = rawBpsTrimmed.length > 0 ? rawBpsTrimmed : String(DEFAULT_FEE_BPS);
87096
+ const bps = Number(bpsStr);
87097
+ if (!Number.isInteger(bps) || bps < 0) {
87098
+ warnOnce(
87099
+ `bad-bps:${bpsStr}`,
87100
+ `FEE_BPS must be a non-negative integer, got: ${bpsStr} \u2014 fee disabled`
87101
+ );
87102
+ return null;
87103
+ }
87104
+ if (bps > 1e4) {
87105
+ warnOnce(
87106
+ `bps-too-high:${bps}`,
87107
+ `FEE_BPS exceeds 10000 (100%), got: ${bps} \u2014 fee disabled`
87108
+ );
87109
+ return null;
87110
+ }
87111
+ let recipient;
87112
+ try {
87113
+ recipient = new import_web3113.PublicKey(walletStr);
87114
+ } catch {
87115
+ warnOnce(
87116
+ `bad-wallet:${walletStr}`,
87117
+ `FEE_RECIPIENT_WALLET is not a valid base58 pubkey: ${walletStr} \u2014 fee disabled`
87118
+ );
87119
+ return null;
87120
+ }
87121
+ return { recipient, bps };
87122
+ }
87123
+ function deriveFeeAccount(mint, config3, tokenProgramId) {
87124
+ const cfg = config3 ?? getFeeConfig();
87125
+ if (!cfg) {
87126
+ throw new Error("deriveFeeAccount called but fee is not enabled");
87127
+ }
87128
+ const mintPubkey = new import_web3113.PublicKey(mint);
87129
+ return getAssociatedTokenAddressSync(
87130
+ mintPubkey,
87131
+ cfg.recipient,
87132
+ true,
87133
+ tokenProgramId ?? TOKEN_PROGRAM_ID
87134
+ ).toBase58();
87135
+ }
87136
+ async function resolveFeeAccountForSwap(mint, connection, config3) {
87137
+ const cfg = config3 ?? getFeeConfig();
87138
+ if (!cfg) return null;
87139
+ const tokenProgram = await resolveMintTokenProgram(mint, connection);
87140
+ let ata;
87141
+ try {
87142
+ ata = deriveFeeAccount(mint, cfg, tokenProgram);
87143
+ } catch (error) {
87144
+ warnOnce(
87145
+ `ata-derive-error:${cfg.recipient.toBase58()}:${mint}`,
87146
+ `Failed to derive fee ATA for mint ${mint} (${error.message}) \u2014 fee disabled for this mint`
87147
+ );
87148
+ return null;
87149
+ }
87150
+ const cacheKey = `${cfg.recipient.toBase58()}:${mint}`;
87151
+ const cached2 = ataExistsCache.get(cacheKey);
87152
+ if (cached2 === true) return ata;
87153
+ if (cached2 === false) return null;
87154
+ try {
87155
+ const info = await connection.getAccountInfo(
87156
+ new import_web3113.PublicKey(ata),
87157
+ "confirmed"
87158
+ );
87159
+ const exists = info !== null;
87160
+ ataExistsCache.set(cacheKey, exists);
87161
+ if (!exists) {
87162
+ warnOnce(
87163
+ `ata-missing:${cacheKey}`,
87164
+ `Fee treasury ATA does not exist on-chain for mint ${mint} (ata=${ata}) \u2014 fee disabled for this mint`
87165
+ );
87166
+ return null;
87167
+ }
87168
+ return ata;
87169
+ } catch (error) {
87170
+ warnOnce(
87171
+ `ata-rpc-error:${cacheKey}`,
87172
+ `Failed to verify fee ATA on-chain (${error.message}) \u2014 assuming it exists`
87173
+ );
87174
+ return ata;
87175
+ }
87176
+ }
87177
+
86455
87178
  // src/plugins/jupiter/api.ts
87179
+ init_solana();
86456
87180
  var lastRoute = null;
86457
87181
  function getLastRoute() {
86458
87182
  return lastRoute;
@@ -86494,6 +87218,29 @@ async function getQuote(params) {
86494
87218
  if (params.slippageBps !== void 0) {
86495
87219
  searchParams.set("slippageBps", String(params.slippageBps));
86496
87220
  }
87221
+ const feeConfig = getFeeConfig();
87222
+ if (feeConfig) {
87223
+ const { mint: feeMint } = pickFeeSide(
87224
+ params.inputMint,
87225
+ params.outputMint
87226
+ );
87227
+ const feeAccount = await resolveFeeAccountForSwap(
87228
+ feeMint,
87229
+ getConnection(),
87230
+ feeConfig
87231
+ );
87232
+ if (feeAccount) {
87233
+ searchParams.set("platformFeeBps", String(feeConfig.bps));
87234
+ searchParams.set("feeAccount", feeAccount);
87235
+ const feeTokenProgram = await resolveMintTokenProgram(
87236
+ feeMint,
87237
+ getConnection()
87238
+ );
87239
+ if (feeTokenProgram.equals(TOKEN_2022_PROGRAM_ID)) {
87240
+ searchParams.set("instructionVersion", "V2");
87241
+ }
87242
+ }
87243
+ }
86497
87244
  const { url, headers } = await resolveRoute("/swap/v1/quote");
86498
87245
  const response = await fetch(`${url}?${searchParams}`, { headers });
86499
87246
  if (!response.ok) {
@@ -86508,6 +87255,15 @@ async function getQuote(params) {
86508
87255
  }
86509
87256
  async function getSwapTransaction(params) {
86510
87257
  try {
87258
+ const feeConfig = getFeeConfig();
87259
+ const feeAccount = feeConfig ? await resolveFeeAccountForSwap(
87260
+ pickFeeSide(
87261
+ params.quoteResponse.inputMint,
87262
+ params.quoteResponse.outputMint
87263
+ ).mint,
87264
+ getConnection(),
87265
+ feeConfig
87266
+ ) : null;
86511
87267
  const { url, headers } = await resolveRoute("/swap/v1/swap");
86512
87268
  const response = await fetch(url, {
86513
87269
  method: "POST",
@@ -86524,7 +87280,8 @@ async function getSwapTransaction(params) {
86524
87280
  global: false,
86525
87281
  priorityLevel: "medium"
86526
87282
  }
86527
- }
87283
+ },
87284
+ ...feeAccount ? { feeAccount } : {}
86528
87285
  })
86529
87286
  });
86530
87287
  if (!response.ok) {
@@ -86559,11 +87316,11 @@ function fallbackHint(route) {
86559
87316
  return null;
86560
87317
  }
86561
87318
  function createJupSwapCommand() {
86562
- return new Command("swap").description("Swap tokens via Jupiter aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").action(async (options, cmdObj) => {
87319
+ return new Command("swap").description("Swap tokens via Jupiter aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
86563
87320
  const globalOptions = cmdObj.optsWithGlobals();
86564
87321
  const format = globalOptions.output;
86565
87322
  const startTime = Date.now();
86566
- const mode = resolveExecutionMode(options);
87323
+ const mode = safeResolveExecutionMode(options, format);
86567
87324
  const walletAddress = globalOptions.walletAddress;
86568
87325
  if (!walletAddress) {
86569
87326
  const e = missingWalletAddressError();
@@ -86571,7 +87328,7 @@ function createJupSwapCommand() {
86571
87328
  process.exit(1);
86572
87329
  }
86573
87330
  try {
86574
- new import_web3113.PublicKey(walletAddress);
87331
+ new import_web3114.PublicKey(walletAddress);
86575
87332
  } catch {
86576
87333
  const msg = `Invalid wallet address: ${walletAddress}`;
86577
87334
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -86625,7 +87382,7 @@ Error: ${msg}`));
86625
87382
  console.log(table.toString());
86626
87383
  const hint = fallbackHint(getLastRoute());
86627
87384
  if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
86628
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
87385
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
86629
87386
  }
86630
87387
  return;
86631
87388
  }
@@ -86638,8 +87395,31 @@ Error: ${msg}`));
86638
87395
  format === "json" ? outputErrorJson(swapResult.error) : outputErrorTable(swapResult.error);
86639
87396
  process.exit(1);
86640
87397
  }
86641
- console.log(JSON.stringify({ unsignedTransactions: [swapResult.value.swapTransaction] }));
87398
+ const base64 = swapResult.value.swapTransaction;
87399
+ if (mode === "unsigned-tx") {
87400
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
87401
+ return;
87402
+ }
87403
+ const ctx = requirePrivyContext(walletAddress);
87404
+ printPrivySignBanner();
87405
+ const broadcast = await privyBroadcastOne(ctx, base64);
87406
+ if (!broadcast.ok) {
87407
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
87408
+ process.exit(1);
87409
+ }
87410
+ if (format === "json") {
87411
+ outputJson({
87412
+ signature: broadcast.value.signature,
87413
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
87414
+ }, startTime);
87415
+ } else {
87416
+ outputTransactionResult(broadcast.value.signature);
87417
+ }
86642
87418
  } catch (e) {
87419
+ if (e instanceof ByrealError) {
87420
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
87421
+ process.exit(1);
87422
+ }
86643
87423
  const message = e.message || "Jupiter swap failed";
86644
87424
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
86645
87425
  Error: ${message}`));
@@ -86727,7 +87507,7 @@ var jupiterPlugin = {
86727
87507
 
86728
87508
  // src/plugins/kamino/commands.ts
86729
87509
  var import_cli_table33 = __toESM(require_cli_table3(), 1);
86730
- var import_web3114 = __toESM(require_index_cjs(), 1);
87510
+ var import_web3115 = __toESM(require_index_cjs(), 1);
86731
87511
  init_errors();
86732
87512
  init_constants();
86733
87513
 
@@ -86980,7 +87760,7 @@ function validateWallet(walletAddress, format) {
86980
87760
  process.exit(1);
86981
87761
  }
86982
87762
  try {
86983
- new import_web3114.PublicKey(walletAddress);
87763
+ new import_web3115.PublicKey(walletAddress);
86984
87764
  } catch {
86985
87765
  const msg = `Invalid wallet address: ${walletAddress}`;
86986
87766
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -86990,11 +87770,11 @@ Error: ${msg}`));
86990
87770
  return walletAddress;
86991
87771
  }
86992
87772
  function createKaminoDepositCommand() {
86993
- return new Command("deposit").description("Deposit tokens to Kamino Lend").requiredOption("--amount <amount>", "Amount to deposit (UI amount, e.g. 2.0)").option("--mint <address>", "Token mint address", USDC_MINT).option("--reserve <address>", "Reserve address (auto-resolved from mint if omitted)").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).option("--dry-run", "Preview without generating a transaction").action(async (options, cmdObj) => {
87773
+ return new Command("deposit").description("Deposit tokens to Kamino Lend").requiredOption("--amount <amount>", "Amount to deposit (UI amount, e.g. 2.0)").option("--mint <address>", "Token mint address", USDC_MINT).option("--reserve <address>", "Reserve address (auto-resolved from mint if omitted)").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).option("--dry-run", "Preview without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
86994
87774
  const globalOptions = cmdObj.optsWithGlobals();
86995
87775
  const format = globalOptions.output;
86996
87776
  const startTime = Date.now();
86997
- const mode = resolveExecutionMode(options);
87777
+ const mode = safeResolveExecutionMode(options, format);
86998
87778
  const walletAddress = validateWallet(globalOptions.walletAddress, format);
86999
87779
  try {
87000
87780
  const reserve = options.reserve ?? resolveReserve(options.mint, options.market);
@@ -87020,7 +87800,7 @@ function createKaminoDepositCommand() {
87020
87800
  );
87021
87801
  console.log(source_default.cyan.bold("\n Kamino Deposit Preview\n"));
87022
87802
  console.log(table.toString());
87023
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
87803
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
87024
87804
  }
87025
87805
  return;
87026
87806
  }
@@ -87034,8 +87814,31 @@ function createKaminoDepositCommand() {
87034
87814
  format === "json" ? outputErrorJson(result.error) : outputErrorTable(result.error);
87035
87815
  process.exit(1);
87036
87816
  }
87037
- console.log(JSON.stringify({ unsignedTransactions: [result.value.transaction] }));
87817
+ const base64 = result.value.transaction;
87818
+ if (mode === "unsigned-tx") {
87819
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
87820
+ return;
87821
+ }
87822
+ const ctx = requirePrivyContext(walletAddress);
87823
+ printPrivySignBanner();
87824
+ const broadcast = await privyBroadcastOne(ctx, base64);
87825
+ if (!broadcast.ok) {
87826
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
87827
+ process.exit(1);
87828
+ }
87829
+ if (format === "json") {
87830
+ outputJson({
87831
+ signature: broadcast.value.signature,
87832
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
87833
+ }, startTime);
87834
+ } else {
87835
+ outputTransactionResult(broadcast.value.signature);
87836
+ }
87038
87837
  } catch (e) {
87838
+ if (e instanceof ByrealError) {
87839
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
87840
+ process.exit(1);
87841
+ }
87039
87842
  const message = e.message || "Kamino deposit failed";
87040
87843
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
87041
87844
  Error: ${message}`));
@@ -87044,11 +87847,11 @@ Error: ${message}`));
87044
87847
  });
87045
87848
  }
87046
87849
  function createKaminoWithdrawCommand() {
87047
- return new Command("withdraw").description("Withdraw tokens from Kamino Lend").requiredOption("--amount <amount>", "Amount to withdraw (UI amount, e.g. 2.0)").option("--mint <address>", "Token mint address", USDC_MINT).option("--reserve <address>", "Reserve address (auto-resolved from mint if omitted)").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).option("--dry-run", "Preview without generating a transaction").action(async (options, cmdObj) => {
87850
+ return new Command("withdraw").description("Withdraw tokens from Kamino Lend").requiredOption("--amount <amount>", "Amount to withdraw (UI amount, e.g. 2.0)").option("--mint <address>", "Token mint address", USDC_MINT).option("--reserve <address>", "Reserve address (auto-resolved from mint if omitted)").option("--market <address>", "Market address", KAMINO_MAIN_MARKET).option("--dry-run", "Preview without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
87048
87851
  const globalOptions = cmdObj.optsWithGlobals();
87049
87852
  const format = globalOptions.output;
87050
87853
  const startTime = Date.now();
87051
- const mode = resolveExecutionMode(options);
87854
+ const mode = safeResolveExecutionMode(options, format);
87052
87855
  const walletAddress = validateWallet(globalOptions.walletAddress, format);
87053
87856
  try {
87054
87857
  const reserve = options.reserve ?? resolveReserve(options.mint, options.market);
@@ -87074,7 +87877,7 @@ function createKaminoWithdrawCommand() {
87074
87877
  );
87075
87878
  console.log(source_default.cyan.bold("\n Kamino Withdraw Preview\n"));
87076
87879
  console.log(table.toString());
87077
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
87880
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
87078
87881
  }
87079
87882
  return;
87080
87883
  }
@@ -87088,8 +87891,31 @@ function createKaminoWithdrawCommand() {
87088
87891
  format === "json" ? outputErrorJson(result.error) : outputErrorTable(result.error);
87089
87892
  process.exit(1);
87090
87893
  }
87091
- console.log(JSON.stringify({ unsignedTransactions: [result.value.transaction] }));
87894
+ const base64 = result.value.transaction;
87895
+ if (mode === "unsigned-tx") {
87896
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
87897
+ return;
87898
+ }
87899
+ const ctx = requirePrivyContext(walletAddress);
87900
+ printPrivySignBanner();
87901
+ const broadcast = await privyBroadcastOne(ctx, base64);
87902
+ if (!broadcast.ok) {
87903
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
87904
+ process.exit(1);
87905
+ }
87906
+ if (format === "json") {
87907
+ outputJson({
87908
+ signature: broadcast.value.signature,
87909
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
87910
+ }, startTime);
87911
+ } else {
87912
+ outputTransactionResult(broadcast.value.signature);
87913
+ }
87092
87914
  } catch (e) {
87915
+ if (e instanceof ByrealError) {
87916
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
87917
+ process.exit(1);
87918
+ }
87093
87919
  const message = e.message || "Kamino withdraw failed";
87094
87920
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
87095
87921
  Error: ${message}`));
@@ -87311,12 +88137,12 @@ var kaminoPlugin = {
87311
88137
 
87312
88138
  // src/plugins/rent/commands.ts
87313
88139
  var import_cli_table34 = __toESM(require_cli_table3(), 1);
87314
- var import_web3116 = __toESM(require_index_cjs(), 1);
88140
+ var import_web3117 = __toESM(require_index_cjs(), 1);
87315
88141
  init_errors();
87316
88142
  init_constants();
87317
88143
 
87318
88144
  // src/plugins/rent/accounts.ts
87319
- var import_web3115 = __toESM(require_index_cjs(), 1);
88145
+ var import_web3116 = __toESM(require_index_cjs(), 1);
87320
88146
  init_solana();
87321
88147
  var ACCOUNT_EXCEPTIONS = /* @__PURE__ */ new Set([
87322
88148
  "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
@@ -87330,7 +88156,7 @@ var RENT_PER_ACCOUNT_SOL = 203928e-8;
87330
88156
  var MAX_INSTRUCTIONS_PER_TX = 5;
87331
88157
  async function scanEmptyAccounts(walletAddress, options = {}) {
87332
88158
  const connection = getConnection();
87333
- const owner = new import_web3115.PublicKey(walletAddress);
88159
+ const owner = new import_web3116.PublicKey(walletAddress);
87334
88160
  const exceptions = /* @__PURE__ */ new Set([...ACCOUNT_EXCEPTIONS, ...options.excludeMints ?? []]);
87335
88161
  const splAccounts = await findEmptyAccounts(connection, owner, TOKEN_PROGRAM_ID, exceptions);
87336
88162
  let token2022Accounts = [];
@@ -87348,19 +88174,19 @@ async function scanEmptyAccounts(walletAddress, options = {}) {
87348
88174
  async function buildCloseTransactions(walletAddress, emptyAccounts) {
87349
88175
  if (emptyAccounts.length === 0) return [];
87350
88176
  const connection = getConnection();
87351
- const owner = new import_web3115.PublicKey(walletAddress);
88177
+ const owner = new import_web3116.PublicKey(walletAddress);
87352
88178
  const { blockhash } = await connection.getLatestBlockhash();
87353
88179
  const transactions = [];
87354
88180
  for (let i = 0; i < emptyAccounts.length; i += MAX_INSTRUCTIONS_PER_TX) {
87355
88181
  const batch = emptyAccounts.slice(i, i + MAX_INSTRUCTIONS_PER_TX);
87356
- const tx = new import_web3115.Transaction();
88182
+ const tx = new import_web3116.Transaction();
87357
88183
  tx.recentBlockhash = blockhash;
87358
88184
  tx.feePayer = owner;
87359
88185
  for (const account of batch) {
87360
- const programId = new import_web3115.PublicKey(account.programId);
88186
+ const programId = new import_web3116.PublicKey(account.programId);
87361
88187
  tx.add(
87362
88188
  createCloseAccountInstruction(
87363
- new import_web3115.PublicKey(account.pubkey),
88189
+ new import_web3116.PublicKey(account.pubkey),
87364
88190
  owner,
87365
88191
  // destination: rent goes back to wallet
87366
88192
  owner,
@@ -87400,11 +88226,11 @@ async function findEmptyAccounts(connection, owner, programId, exceptions) {
87400
88226
 
87401
88227
  // src/plugins/rent/commands.ts
87402
88228
  function createRentReclaimCommand() {
87403
- return new Command("reclaim").description("Close empty token accounts to reclaim SOL rent").option("--dry-run", "Scan and report without generating transactions").option("--include-token2022", "Also close empty Token-2022 accounts").option("--exclude <mints>", "Comma-separated mint addresses to never close").action(async (options, cmdObj) => {
88229
+ return new Command("reclaim").description("Close empty token accounts to reclaim SOL rent").option("--dry-run", "Scan and report without generating transactions").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").option("--include-token2022", "Also close empty Token-2022 accounts").option("--exclude <mints>", "Comma-separated mint addresses to never close").action(async (options, cmdObj) => {
87404
88230
  const globalOptions = cmdObj.optsWithGlobals();
87405
88231
  const format = globalOptions.output;
87406
88232
  const startTime = Date.now();
87407
- const mode = resolveExecutionMode(options);
88233
+ const mode = safeResolveExecutionMode(options, format);
87408
88234
  const walletAddress = globalOptions.walletAddress;
87409
88235
  if (!walletAddress) {
87410
88236
  const e = missingWalletAddressError();
@@ -87412,7 +88238,7 @@ function createRentReclaimCommand() {
87412
88238
  process.exit(1);
87413
88239
  }
87414
88240
  try {
87415
- new import_web3116.PublicKey(walletAddress);
88241
+ new import_web3117.PublicKey(walletAddress);
87416
88242
  } catch {
87417
88243
  const msg = `Invalid wallet address: ${walletAddress}`;
87418
88244
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -87463,13 +88289,33 @@ Error: ${msg}`));
87463
88289
  acctTable.push([a.pubkey, a.mint, progLabel]);
87464
88290
  }
87465
88291
  console.log(acctTable.toString());
87466
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction(s)"));
88292
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
87467
88293
  }
87468
88294
  return;
87469
88295
  }
87470
88296
  const txs = await buildCloseTransactions(walletAddress, scan.emptyAccounts);
87471
- console.log(JSON.stringify({ unsignedTransactions: txs }));
88297
+ if (mode === "unsigned-tx") {
88298
+ console.log(JSON.stringify({ unsignedTransactions: txs }));
88299
+ return;
88300
+ }
88301
+ const ctx = requirePrivyContext(walletAddress);
88302
+ printPrivySignBanner();
88303
+ const broadcast = await privyBroadcastMany(ctx, txs);
88304
+ if (!broadcast.ok) {
88305
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
88306
+ process.exit(1);
88307
+ }
88308
+ if (format === "json") {
88309
+ outputJson(broadcast.value, startTime);
88310
+ } else {
88311
+ outputMultiBroadcastResult(broadcast.value);
88312
+ }
88313
+ if (broadcast.value.failCount > 0) process.exit(1);
87472
88314
  } catch (e) {
88315
+ if (e instanceof ByrealError) {
88316
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
88317
+ process.exit(1);
88318
+ }
87473
88319
  const message = e.message || "Rent reclaim failed";
87474
88320
  format === "json" ? outputErrorJson({ code: "RPC_ERROR", type: "SYSTEM", message, retryable: true }) : console.error(source_default.red(`
87475
88321
  Error: ${message}`));
@@ -87507,7 +88353,7 @@ var rentPlugin = {
87507
88353
 
87508
88354
  // src/plugins/consolidate/commands.ts
87509
88355
  var import_cli_table35 = __toESM(require_cli_table3(), 1);
87510
- var import_web3118 = __toESM(require_index_cjs(), 1);
88356
+ var import_web3119 = __toESM(require_index_cjs(), 1);
87511
88357
  init_errors();
87512
88358
  init_constants();
87513
88359
 
@@ -87515,7 +88361,7 @@ init_constants();
87515
88361
  init_types();
87516
88362
  init_errors();
87517
88363
  init_solana();
87518
- var import_web3117 = __toESM(require_index_cjs(), 1);
88364
+ var import_web3118 = __toESM(require_index_cjs(), 1);
87519
88365
  var USDC_MINT2 = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
87520
88366
  var SOL_MINT = "So11111111111111111111111111111111111111112";
87521
88367
  async function buildSweepPlan(params) {
@@ -87529,7 +88375,7 @@ async function buildSweepPlan(params) {
87529
88375
  ]);
87530
88376
  try {
87531
88377
  const connection = getConnection();
87532
- const owner = new import_web3117.PublicKey(params.walletAddress);
88378
+ const owner = new import_web3118.PublicKey(params.walletAddress);
87533
88379
  const [splAccounts, token2022Accounts] = await Promise.all([
87534
88380
  connection.getTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID }, "confirmed"),
87535
88381
  connection.getTokenAccountsByOwner(owner, { programId: TOKEN_2022_PROGRAM_ID }, "confirmed")
@@ -87549,7 +88395,7 @@ async function buildSweepPlan(params) {
87549
88395
  if (tokenBalances.length === 0) {
87550
88396
  return ok({ dustTokens: [], totalEstimatedUsd: 0, swapCount: 0, skipCount: 0 });
87551
88397
  }
87552
- const mintPubkeys = tokenBalances.map((t) => new import_web3117.PublicKey(t.mint));
88398
+ const mintPubkeys = tokenBalances.map((t) => new import_web3118.PublicKey(t.mint));
87553
88399
  const nftMints = /* @__PURE__ */ new Set();
87554
88400
  for (let i = 0; i < mintPubkeys.length; i += 100) {
87555
88401
  const batch = mintPubkeys.slice(i, i + 100);
@@ -87642,11 +88488,11 @@ async function executeSweep(params) {
87642
88488
 
87643
88489
  // src/plugins/consolidate/commands.ts
87644
88490
  function createSweepExecuteCommand() {
87645
- return new Command("execute").description("Consolidate dust tokens into USDC (or SOL)").option("--target-mint <address>", "Target token to consolidate into", "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").option("--max-value-usd <amount>", "Only sweep tokens below this USD value", "0.5").option("--exclude <mints>", "Comma-separated mint addresses to skip").option("--dry-run", "Preview consolidation plan without generating transactions").action(async (options, cmdObj) => {
88491
+ return new Command("execute").description("Consolidate dust tokens into USDC (or SOL)").option("--target-mint <address>", "Target token to consolidate into", "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v").option("--max-value-usd <amount>", "Only sweep tokens below this USD value", "0.5").option("--exclude <mints>", "Comma-separated mint addresses to skip").option("--dry-run", "Preview consolidation plan without generating transactions").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
87646
88492
  const globalOptions = cmdObj.optsWithGlobals();
87647
88493
  const format = globalOptions.output;
87648
88494
  const startTime = Date.now();
87649
- const mode = resolveExecutionMode(options);
88495
+ const mode = safeResolveExecutionMode(options, format);
87650
88496
  const walletAddress = globalOptions.walletAddress;
87651
88497
  if (!walletAddress) {
87652
88498
  const e = missingWalletAddressError();
@@ -87654,7 +88500,7 @@ function createSweepExecuteCommand() {
87654
88500
  process.exit(1);
87655
88501
  }
87656
88502
  try {
87657
- new import_web3118.PublicKey(walletAddress);
88503
+ new import_web3119.PublicKey(walletAddress);
87658
88504
  } catch {
87659
88505
  const msg = `Invalid wallet address: ${walletAddress}`;
87660
88506
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -87730,7 +88576,7 @@ Error: ${msg}`));
87730
88576
  ]);
87731
88577
  }
87732
88578
  console.log(tokenTable.toString());
87733
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transactions"));
88579
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
87734
88580
  }
87735
88581
  return;
87736
88582
  }
@@ -87755,12 +88601,36 @@ Error: ${msg}`));
87755
88601
  }
87756
88602
  return;
87757
88603
  }
87758
- console.log(JSON.stringify({
87759
- unsignedTransactions: swapTransactions,
87760
- swapCount: swapTransactions.length,
87761
- ...failures.length > 0 ? { failures } : {}
87762
- }));
88604
+ if (mode === "unsigned-tx") {
88605
+ console.log(JSON.stringify({
88606
+ unsignedTransactions: swapTransactions,
88607
+ swapCount: swapTransactions.length,
88608
+ ...failures.length > 0 ? { failures } : {}
88609
+ }));
88610
+ return;
88611
+ }
88612
+ const ctx = requirePrivyContext(walletAddress);
88613
+ printPrivySignBanner();
88614
+ const broadcast = await privyBroadcastMany(ctx, swapTransactions);
88615
+ if (!broadcast.ok) {
88616
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
88617
+ process.exit(1);
88618
+ }
88619
+ if (format === "json") {
88620
+ outputJson({ ...broadcast.value, ...failures.length > 0 ? { failures } : {} }, startTime);
88621
+ } else {
88622
+ outputMultiBroadcastResult(broadcast.value);
88623
+ if (failures.length > 0) {
88624
+ console.log(source_default.gray(` ${failures.length} token(s) skipped (failed to quote):`));
88625
+ for (const f of failures) console.log(source_default.gray(` ${f.mint}: ${f.reason}`));
88626
+ }
88627
+ }
88628
+ if (broadcast.value.failCount > 0) process.exit(1);
87763
88629
  } catch (e) {
88630
+ if (e instanceof ByrealError) {
88631
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
88632
+ process.exit(1);
88633
+ }
87764
88634
  const message = e.message || "Token consolidation failed";
87765
88635
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
87766
88636
  Error: ${message}`));
@@ -87799,13 +88669,13 @@ var consolidatePlugin = {
87799
88669
 
87800
88670
  // src/plugins/titan/commands.ts
87801
88671
  var import_cli_table36 = __toESM(require_cli_table3(), 1);
87802
- var import_web3120 = __toESM(require_index_cjs(), 1);
88672
+ var import_web3121 = __toESM(require_index_cjs(), 1);
87803
88673
  init_solana();
87804
88674
  init_errors();
87805
88675
  init_constants();
87806
88676
 
87807
88677
  // src/plugins/titan/api.ts
87808
- var import_web3119 = __toESM(require_index_cjs(), 1);
88678
+ var import_web3120 = __toESM(require_index_cjs(), 1);
87809
88679
  var import_msgpack = __toESM(require_dist5(), 1);
87810
88680
  init_errors();
87811
88681
  init_constants();
@@ -87845,6 +88715,14 @@ async function getSwapQuote2(params) {
87845
88715
  slippageBps: String(params.slippageBps),
87846
88716
  swapMode: params.swapMode
87847
88717
  });
88718
+ const feeConfig = getFeeConfig();
88719
+ const { mint: feeMint, side: feeSide } = pickFeeSide(params.inputMint, params.outputMint);
88720
+ const feeAccount = feeConfig ? await resolveFeeAccountForSwap(feeMint, getConnection(), feeConfig) : null;
88721
+ if (feeConfig && feeAccount) {
88722
+ query.set("feeAccount", feeAccount);
88723
+ query.set("feeBps", String(feeConfig.bps));
88724
+ query.set("feeFromInputMint", feeSide === "input" ? "true" : "false");
88725
+ }
87848
88726
  url = `${url}?${query.toString()}`;
87849
88727
  const controller = new AbortController();
87850
88728
  const timer = setTimeout(() => controller.abort(), TITAN_TIMEOUT_MS);
@@ -87955,24 +88833,24 @@ function pickBestRoute(quotes, swapMode) {
87955
88833
  }
87956
88834
  async function buildTransaction(instructions, altAddresses, userPublicKey, computeUnits) {
87957
88835
  const connection = getConnection();
87958
- const payer = new import_web3119.PublicKey(userPublicKey);
88836
+ const payer = new import_web3120.PublicKey(userPublicKey);
87959
88837
  const budgetInstructions = [];
87960
88838
  if (computeUnits && computeUnits > 2e5) {
87961
88839
  budgetInstructions.push(
87962
- import_web3119.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits })
88840
+ import_web3120.ComputeBudgetProgram.setComputeUnitLimit({ units: computeUnits })
87963
88841
  );
87964
88842
  }
87965
88843
  budgetInstructions.push(
87966
- import_web3119.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: DEFAULTS.PRIORITY_FEE_MICRO_LAMPORTS })
88844
+ import_web3120.ComputeBudgetProgram.setComputeUnitPrice({ microLamports: DEFAULTS.PRIORITY_FEE_MICRO_LAMPORTS })
87967
88845
  );
87968
88846
  const txInstructions = instructions.map((ix) => {
87969
88847
  const accounts = (ix.a || []).map((acc) => ({
87970
- pubkey: new import_web3119.PublicKey(acc.p),
88848
+ pubkey: new import_web3120.PublicKey(acc.p),
87971
88849
  isSigner: acc.s ?? false,
87972
88850
  isWritable: acc.w ?? false
87973
88851
  }));
87974
- return new import_web3119.TransactionInstruction({
87975
- programId: new import_web3119.PublicKey(ix.p),
88852
+ return new import_web3120.TransactionInstruction({
88853
+ programId: new import_web3120.PublicKey(ix.p),
87976
88854
  keys: accounts,
87977
88855
  data: Buffer.from(ix.d)
87978
88856
  });
@@ -87982,7 +88860,7 @@ async function buildTransaction(instructions, altAddresses, userPublicKey, compu
87982
88860
  const fetched = await Promise.all(
87983
88861
  altAddresses.map(async (addr) => {
87984
88862
  try {
87985
- const result = await connection.getAddressLookupTable(new import_web3119.PublicKey(addr));
88863
+ const result = await connection.getAddressLookupTable(new import_web3120.PublicKey(addr));
87986
88864
  return result.value;
87987
88865
  } catch {
87988
88866
  return null;
@@ -87994,12 +88872,12 @@ async function buildTransaction(instructions, altAddresses, userPublicKey, compu
87994
88872
  );
87995
88873
  }
87996
88874
  const { blockhash } = await connection.getLatestBlockhash("confirmed");
87997
- const messageV0 = new import_web3119.TransactionMessage({
88875
+ const messageV0 = new import_web3120.TransactionMessage({
87998
88876
  payerKey: payer,
87999
88877
  recentBlockhash: blockhash,
88000
88878
  instructions: [...budgetInstructions, ...txInstructions]
88001
88879
  }).compileToV0Message(lookupTableAccounts);
88002
- const tx = new import_web3119.VersionedTransaction(messageV0);
88880
+ const tx = new import_web3120.VersionedTransaction(messageV0);
88003
88881
  return Buffer.from(tx.serialize()).toString("base64");
88004
88882
  }
88005
88883
 
@@ -88009,11 +88887,11 @@ function fallbackHint2(route) {
88009
88887
  return null;
88010
88888
  }
88011
88889
  function createTitanSwapCommand() {
88012
- return new Command("swap").description("Swap tokens via Titan Exchange aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--swap-mode <mode>", "Swap mode: ExactIn or ExactOut", "ExactIn").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").action(async (options, cmdObj) => {
88890
+ return new Command("swap").description("Swap tokens via Titan Exchange aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--swap-mode <mode>", "Swap mode: ExactIn or ExactOut", "ExactIn").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
88013
88891
  const globalOptions = cmdObj.optsWithGlobals();
88014
88892
  const format = globalOptions.output;
88015
88893
  const startTime = Date.now();
88016
- const mode = resolveExecutionMode(options);
88894
+ const mode = safeResolveExecutionMode(options, format);
88017
88895
  const walletAddress = globalOptions.walletAddress;
88018
88896
  if (!walletAddress) {
88019
88897
  const e = missingWalletAddressError();
@@ -88021,7 +88899,7 @@ function createTitanSwapCommand() {
88021
88899
  process.exit(1);
88022
88900
  }
88023
88901
  try {
88024
- new import_web3120.PublicKey(walletAddress);
88902
+ new import_web3121.PublicKey(walletAddress);
88025
88903
  } catch {
88026
88904
  const msg = `Invalid wallet address: ${walletAddress}`;
88027
88905
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -88079,12 +88957,35 @@ Error: ${msg}`));
88079
88957
  console.log(table.toString());
88080
88958
  const hint = fallbackHint2(getLastRoute2());
88081
88959
  if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
88082
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
88960
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
88083
88961
  }
88084
88962
  return;
88085
88963
  }
88086
- console.log(JSON.stringify({ unsignedTransactions: [quote.transaction] }));
88964
+ const base64 = quote.transaction;
88965
+ if (mode === "unsigned-tx") {
88966
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
88967
+ return;
88968
+ }
88969
+ const ctx = requirePrivyContext(walletAddress);
88970
+ printPrivySignBanner();
88971
+ const broadcast = await privyBroadcastOne(ctx, base64);
88972
+ if (!broadcast.ok) {
88973
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
88974
+ process.exit(1);
88975
+ }
88976
+ if (format === "json") {
88977
+ outputJson({
88978
+ signature: broadcast.value.signature,
88979
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
88980
+ }, startTime);
88981
+ } else {
88982
+ outputTransactionResult(broadcast.value.signature);
88983
+ }
88087
88984
  } catch (e) {
88985
+ if (e instanceof ByrealError) {
88986
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
88987
+ process.exit(1);
88988
+ }
88088
88989
  const message = e.message || "Titan swap failed";
88089
88990
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
88090
88991
  Error: ${message}`));
@@ -88126,7 +89027,7 @@ var titanPlugin = {
88126
89027
 
88127
89028
  // src/plugins/dflow/commands.ts
88128
89029
  var import_cli_table37 = __toESM(require_cli_table3(), 1);
88129
- var import_web3121 = __toESM(require_index_cjs(), 1);
89030
+ var import_web3122 = __toESM(require_index_cjs(), 1);
88130
89031
  init_solana();
88131
89032
  init_errors();
88132
89033
  init_constants();
@@ -88134,6 +89035,7 @@ init_constants();
88134
89035
  // src/plugins/dflow/api.ts
88135
89036
  init_errors();
88136
89037
  init_constants();
89038
+ init_solana();
88137
89039
  var lastRoute3 = null;
88138
89040
  function getLastRoute3() {
88139
89041
  return lastRoute3;
@@ -88167,6 +89069,14 @@ async function getSwapQuote3(params) {
88167
89069
  amount: params.amount,
88168
89070
  slippageBps: slippageValue
88169
89071
  });
89072
+ const feeConfig = getFeeConfig();
89073
+ const { mint: feeMint, side: feeSide } = pickFeeSide(params.inputMint, params.outputMint);
89074
+ const feeAccount = feeConfig ? await resolveFeeAccountForSwap(feeMint, getConnection(), feeConfig) : null;
89075
+ if (feeConfig && feeAccount) {
89076
+ query.set("platformFeeBps", String(feeConfig.bps));
89077
+ query.set("platformFeeMode", feeSide === "input" ? "inputMint" : "outputMint");
89078
+ query.set("feeAccount", feeAccount);
89079
+ }
88170
89080
  const { base, headers } = await resolveOrderUrl();
88171
89081
  const url = `${base}/order?${query.toString()}`;
88172
89082
  if (process.env.DEBUG) {
@@ -88250,11 +89160,11 @@ function fallbackHint3(route) {
88250
89160
  return null;
88251
89161
  }
88252
89162
  function createDFlowSwapCommand() {
88253
- return new Command("swap").description("Swap tokens via DFlow order-flow aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").action(async (options, cmdObj) => {
89163
+ return new Command("swap").description("Swap tokens via DFlow order-flow aggregator").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
88254
89164
  const globalOptions = cmdObj.optsWithGlobals();
88255
89165
  const format = globalOptions.output;
88256
89166
  const startTime = Date.now();
88257
- const mode = resolveExecutionMode(options);
89167
+ const mode = safeResolveExecutionMode(options, format);
88258
89168
  const walletAddress = globalOptions.walletAddress;
88259
89169
  if (!walletAddress) {
88260
89170
  const e = missingWalletAddressError();
@@ -88262,7 +89172,7 @@ function createDFlowSwapCommand() {
88262
89172
  process.exit(1);
88263
89173
  }
88264
89174
  try {
88265
- new import_web3121.PublicKey(walletAddress);
89175
+ new import_web3122.PublicKey(walletAddress);
88266
89176
  } catch {
88267
89177
  const msg = `Invalid wallet address: ${walletAddress}`;
88268
89178
  format === "json" ? outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: msg, retryable: false }) : console.error(source_default.red(`
@@ -88320,12 +89230,35 @@ Error: ${msg}`));
88320
89230
  console.log(table.toString());
88321
89231
  const hint = fallbackHint3(getLastRoute3());
88322
89232
  if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
88323
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
89233
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
88324
89234
  }
88325
89235
  return;
88326
89236
  }
88327
- console.log(JSON.stringify({ unsignedTransactions: [quote.transaction] }));
89237
+ const base64 = quote.transaction;
89238
+ if (mode === "unsigned-tx") {
89239
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
89240
+ return;
89241
+ }
89242
+ const ctx = requirePrivyContext(walletAddress);
89243
+ printPrivySignBanner();
89244
+ const broadcast = await privyBroadcastOne(ctx, base64);
89245
+ if (!broadcast.ok) {
89246
+ format === "json" ? outputErrorJson(broadcast.error.toJSON()) : outputErrorTable(broadcast.error.toJSON());
89247
+ process.exit(1);
89248
+ }
89249
+ if (format === "json") {
89250
+ outputJson({
89251
+ signature: broadcast.value.signature,
89252
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
89253
+ }, startTime);
89254
+ } else {
89255
+ outputTransactionResult(broadcast.value.signature);
89256
+ }
88328
89257
  } catch (e) {
89258
+ if (e instanceof ByrealError) {
89259
+ format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
89260
+ process.exit(1);
89261
+ }
88329
89262
  const message = e.message || "DFlow swap failed";
88330
89263
  format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
88331
89264
  Error: ${message}`));
@@ -88850,7 +89783,7 @@ Available Capabilities (${all.length}):
88850
89783
  }
88851
89784
 
88852
89785
  // src/cli/commands/wallet.ts
88853
- var import_web3122 = __toESM(require_index_cjs(), 1);
89786
+ var import_web3123 = __toESM(require_index_cjs(), 1);
88854
89787
  init_constants();
88855
89788
  init_errors();
88856
89789
 
@@ -88887,7 +89820,7 @@ function createWalletCommand() {
88887
89820
  }
88888
89821
  let publicKey3;
88889
89822
  try {
88890
- publicKey3 = new import_web3122.PublicKey(walletAddress);
89823
+ publicKey3 = new import_web3123.PublicKey(walletAddress);
88891
89824
  } catch {
88892
89825
  outputError({
88893
89826
  code: "INVALID_PARAMETER",
@@ -88900,9 +89833,9 @@ function createWalletCommand() {
88900
89833
  try {
88901
89834
  const configResult = loadConfig();
88902
89835
  const rpcUrl = configResult.ok ? configResult.value.rpc_url : SOLANA_RPC_URL;
88903
- const connection = new import_web3122.Connection(rpcUrl);
89836
+ const connection = new import_web3123.Connection(rpcUrl);
88904
89837
  const lamports = await connection.getBalance(publicKey3);
88905
- const solBalance = lamports / import_web3122.LAMPORTS_PER_SOL;
89838
+ const solBalance = lamports / import_web3123.LAMPORTS_PER_SOL;
88906
89839
  const rawAccounts = [];
88907
89840
  const [splResult, t22Result] = await Promise.allSettled([
88908
89841
  connection.getTokenAccountsByOwner(publicKey3, { programId: TOKEN_PROGRAM_ID }),
@@ -88915,7 +89848,7 @@ function createWalletCommand() {
88915
89848
  if (result.status !== "fulfilled") continue;
88916
89849
  for (const { account } of result.value.value) {
88917
89850
  const data = account.data;
88918
- const mint = new import_web3122.PublicKey(data.subarray(0, 32)).toBase58();
89851
+ const mint = new import_web3123.PublicKey(data.subarray(0, 32)).toBase58();
88919
89852
  const amount = data.subarray(64, 72).readBigUInt64LE();
88920
89853
  if (amount === 0n) continue;
88921
89854
  rawAccounts.push({ mint, amount, isToken2022: isToken20222 });
@@ -88926,7 +89859,7 @@ function createWalletCommand() {
88926
89859
  if (uniqueMints.length > 0) {
88927
89860
  for (let i = 0; i < uniqueMints.length; i += 100) {
88928
89861
  const batch = uniqueMints.slice(i, i + 100);
88929
- const mintPubkeys = batch.map((m) => new import_web3122.PublicKey(m));
89862
+ const mintPubkeys = batch.map((m) => new import_web3123.PublicKey(m));
88930
89863
  const mintInfos = await connection.getMultipleAccountsInfo(mintPubkeys);
88931
89864
  for (let j = 0; j < batch.length; j++) {
88932
89865
  const info = mintInfos[j];
@@ -89076,7 +90009,7 @@ Configuration updated: ${key} = ${value}`);
89076
90009
  }
89077
90010
 
89078
90011
  // src/cli/commands/swap.ts
89079
- var import_web3123 = __toESM(require_index_cjs(), 1);
90012
+ var import_web3124 = __toESM(require_index_cjs(), 1);
89080
90013
  init_solana();
89081
90014
  init_errors();
89082
90015
  async function resolveRawAmount(amount, swapMode, inputMint, outputMint, isRaw) {
@@ -89093,24 +90026,41 @@ async function resolveUiAmounts(quote) {
89093
90026
  uiOutAmount: rawToUi(quote.outAmount, outputDecimals)
89094
90027
  };
89095
90028
  }
90029
+ function emitError(format, error) {
90030
+ if (error instanceof ByrealError) {
90031
+ if (format === "json") {
90032
+ outputErrorJson(error.toJSON());
90033
+ } else {
90034
+ outputErrorTable(error.toJSON());
90035
+ }
90036
+ } else {
90037
+ const message = error?.message ?? "Unknown error";
90038
+ if (format === "json") {
90039
+ outputErrorJson({ code: "UNKNOWN_ERROR", type: "SYSTEM", message, retryable: false });
90040
+ } else {
90041
+ console.error(source_default.red(`
90042
+ Error: ${message}`));
90043
+ }
90044
+ }
90045
+ process.exit(1);
90046
+ }
89096
90047
  function createSwapExecuteCommand() {
89097
- return new Command("execute").description("Preview or generate a swap transaction").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--swap-mode <mode>", "Swap mode: in or out", "in").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").action(async (options, cmdObj) => {
90048
+ return new Command("execute").description("Preview, sign, or emit a swap transaction").requiredOption("--input-mint <address>", "Input token mint address").requiredOption("--output-mint <address>", "Output token mint address").requiredOption("--amount <amount>", "Amount to swap (UI amount, decimals auto-resolved)").option("--swap-mode <mode>", "Swap mode: in or out", "in").option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the swap without generating a transaction").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
89098
90049
  const globalOptions = cmdObj.optsWithGlobals();
89099
90050
  const format = globalOptions.output;
89100
90051
  const startTime = Date.now();
89101
- const mode = resolveExecutionMode(options);
90052
+ let mode;
90053
+ try {
90054
+ mode = resolveExecutionMode(options);
90055
+ } catch (e) {
90056
+ emitError(format, e);
90057
+ }
89102
90058
  const userPublicKey = globalOptions.walletAddress;
89103
90059
  if (!userPublicKey) {
89104
- const err2 = missingWalletAddressError();
89105
- if (format === "json") {
89106
- outputErrorJson(err2.toJSON());
89107
- } else {
89108
- outputErrorTable(err2.toJSON());
89109
- }
89110
- process.exit(1);
90060
+ emitError(format, missingWalletAddressError());
89111
90061
  }
89112
90062
  try {
89113
- new import_web3123.PublicKey(userPublicKey);
90063
+ new import_web3124.PublicKey(userPublicKey);
89114
90064
  } catch {
89115
90065
  if (format === "json") {
89116
90066
  outputErrorJson({ code: "INVALID_PARAMETER", type: "VALIDATION", message: `Invalid wallet address: ${userPublicKey}`, retryable: false });
@@ -89138,12 +90088,12 @@ Error: Invalid wallet address: ${userPublicKey}`));
89138
90088
  userPublicKey
89139
90089
  });
89140
90090
  if (!quoteResult.ok) {
89141
- if (format === "json") {
89142
- outputErrorJson(quoteResult.error);
89143
- } else {
89144
- outputErrorTable(quoteResult.error);
89145
- }
89146
- process.exit(1);
90091
+ emitError(format, new ByrealError({
90092
+ code: quoteResult.error.code,
90093
+ type: quoteResult.error.type,
90094
+ message: quoteResult.error.message,
90095
+ retryable: quoteResult.error.retryable
90096
+ }));
89147
90097
  }
89148
90098
  const quote = quoteResult.value;
89149
90099
  const { uiInAmount, uiOutAmount } = await resolveUiAmounts(quote);
@@ -89166,7 +90116,7 @@ Error: Invalid wallet address: ${userPublicKey}`));
89166
90116
  outputJson({ mode: "dry-run", ...quote, uiInAmount, uiOutAmount, inAmountUsd, outAmountUsd }, startTime);
89167
90117
  } else {
89168
90118
  outputSwapQuoteTable(quote, uiInAmount, uiOutAmount);
89169
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction"));
90119
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
89170
90120
  }
89171
90121
  return;
89172
90122
  }
@@ -89180,16 +90130,30 @@ Error: ${errMsg}`));
89180
90130
  }
89181
90131
  process.exit(1);
89182
90132
  }
89183
- console.log(JSON.stringify({ unsignedTransactions: [quote.transaction] }));
89184
- } catch (e) {
89185
- const message = e.message || "Failed to resolve token decimals";
90133
+ if (mode === "unsigned-tx") {
90134
+ console.log(JSON.stringify({ unsignedTransactions: [quote.transaction] }));
90135
+ return;
90136
+ }
90137
+ const ctx = requirePrivyContext(userPublicKey);
90138
+ printPrivySignBanner();
90139
+ const broadcast = await privyBroadcastOne(ctx, quote.transaction);
90140
+ if (!broadcast.ok) {
90141
+ emitError(format, broadcast.error);
90142
+ }
89186
90143
  if (format === "json") {
89187
- outputErrorJson({ code: "VALIDATION_ERROR", type: "VALIDATION", message, retryable: false });
90144
+ outputJson(
90145
+ {
90146
+ signature: broadcast.value.signature,
90147
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`,
90148
+ quote: { ...quote, uiInAmount, uiOutAmount }
90149
+ },
90150
+ startTime
90151
+ );
89188
90152
  } else {
89189
- console.error(source_default.red(`
89190
- Error: ${message}`));
90153
+ outputTransactionResult(broadcast.value.signature);
89191
90154
  }
89192
- process.exit(1);
90155
+ } catch (e) {
90156
+ emitError(format, e);
89193
90157
  }
89194
90158
  });
89195
90159
  }
@@ -89201,11 +90165,11 @@ function createSwapCommand() {
89201
90165
 
89202
90166
  // src/cli/commands/positions.ts
89203
90167
  var import_bn19 = __toESM(require_bn(), 1);
89204
- var import_web3125 = __toESM(require_index_cjs(), 1);
90168
+ var import_web3126 = __toESM(require_index_cjs(), 1);
89205
90169
  init_solana();
89206
90170
 
89207
90171
  // src/core/transaction.ts
89208
- var import_web3124 = __toESM(require_index_cjs(), 1);
90172
+ var import_web3125 = __toESM(require_index_cjs(), 1);
89209
90173
  init_types();
89210
90174
  init_errors();
89211
90175
  function serializeTransaction(tx) {
@@ -89288,7 +90252,7 @@ var KNOWN_SYMBOLS = {
89288
90252
  async function fetchWalletBalanceSummary(owner) {
89289
90253
  const connection = getConnection();
89290
90254
  const lamports = await connection.getBalance(owner);
89291
- const solUi = (lamports / import_web3125.LAMPORTS_PER_SOL).toString();
90255
+ const solUi = (lamports / import_web3126.LAMPORTS_PER_SOL).toString();
89292
90256
  const rawAccounts = [];
89293
90257
  const [splResult, t22Result] = await Promise.allSettled([
89294
90258
  connection.getTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID }),
@@ -89300,7 +90264,7 @@ async function fetchWalletBalanceSummary(owner) {
89300
90264
  if (result.status !== "fulfilled") continue;
89301
90265
  for (const { account } of result.value.value) {
89302
90266
  const data = account.data;
89303
- const mint = new import_web3125.PublicKey(data.subarray(0, 32)).toBase58();
90267
+ const mint = new import_web3126.PublicKey(data.subarray(0, 32)).toBase58();
89304
90268
  const amount = data.subarray(64, 72).readBigUInt64LE();
89305
90269
  if (amount === 0n) continue;
89306
90270
  rawAccounts.push({ mint, amount });
@@ -89311,7 +90275,7 @@ async function fetchWalletBalanceSummary(owner) {
89311
90275
  if (uniqueMints.length > 0) {
89312
90276
  for (let i = 0; i < uniqueMints.length; i += 100) {
89313
90277
  const batch = uniqueMints.slice(i, i + 100);
89314
- const mintPubkeys = batch.map((m) => new import_web3125.PublicKey(m));
90278
+ const mintPubkeys = batch.map((m) => new import_web3126.PublicKey(m));
89315
90279
  const mintInfos = await connection.getMultipleAccountsInfo(mintPubkeys);
89316
90280
  for (let j = 0; j < batch.length; j++) {
89317
90281
  const info = mintInfos[j];
@@ -89332,11 +90296,11 @@ async function fetchWalletBalanceSummary(owner) {
89332
90296
  }
89333
90297
  return { sol: solUi, tokens };
89334
90298
  }
89335
- var ASSOCIATED_TOKEN_PROGRAM = new import_web3125.PublicKey(
90299
+ var ASSOCIATED_TOKEN_PROGRAM = new import_web3126.PublicKey(
89336
90300
  "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL"
89337
90301
  );
89338
90302
  function getAtaAddress(owner, mint, tokenProgramId) {
89339
- const [address] = import_web3125.PublicKey.findProgramAddressSync(
90303
+ const [address] = import_web3126.PublicKey.findProgramAddressSync(
89340
90304
  [owner.toBuffer(), tokenProgramId.toBuffer(), mint.toBuffer()],
89341
90305
  ASSOCIATED_TOKEN_PROGRAM
89342
90306
  );
@@ -89348,7 +90312,7 @@ async function getTokenBalance(owner, mint) {
89348
90312
  const lamports = await connection.getBalance(owner);
89349
90313
  return new import_bn19.default(lamports.toString());
89350
90314
  }
89351
- const mintPk = new import_web3125.PublicKey(mint);
90315
+ const mintPk = new import_web3126.PublicKey(mint);
89352
90316
  const ataSpl = getAtaAddress(owner, mintPk, TOKEN_PROGRAM_ID);
89353
90317
  const ataT22 = getAtaAddress(owner, mintPk, TOKEN_2022_PROGRAM_ID);
89354
90318
  const [splInfo, t22Info] = await Promise.allSettled([
@@ -89405,11 +90369,11 @@ function createPositionsOpenCommand() {
89405
90369
  ).option(
89406
90370
  "--amount-usd <usd>",
89407
90371
  "Investment amount in USD (auto-calculates token split, mutually exclusive with --amount)"
89408
- ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the position without opening").action(async (options, cmdObj) => {
90372
+ ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview the position without opening").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
89409
90373
  const globalOptions = cmdObj.optsWithGlobals();
89410
90374
  const format = globalOptions.output;
89411
90375
  const startTime = Date.now();
89412
- const mode = resolveExecutionMode(options);
90376
+ const mode = safeResolveExecutionMode(options, format);
89413
90377
  const walletAddress = globalOptions.walletAddress;
89414
90378
  if (!walletAddress) {
89415
90379
  const err2 = missingWalletAddressError();
@@ -89420,7 +90384,7 @@ function createPositionsOpenCommand() {
89420
90384
  }
89421
90385
  process.exit(1);
89422
90386
  }
89423
- const publicKey3 = new import_web3125.PublicKey(walletAddress);
90387
+ const publicKey3 = new import_web3126.PublicKey(walletAddress);
89424
90388
  const useAmountUsd = !!options.amountUsd;
89425
90389
  const useTokenAmount = !!options.amount;
89426
90390
  if (useAmountUsd && useTokenAmount) {
@@ -89653,7 +90617,7 @@ function createPositionsOpenCommand() {
89653
90617
  } else {
89654
90618
  console.log(source_default.green("\n Balance check: sufficient"));
89655
90619
  console.log(
89656
- source_default.yellow("\n Remove --dry-run to generate the unsigned transaction")
90620
+ source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
89657
90621
  );
89658
90622
  }
89659
90623
  }
@@ -89669,7 +90633,29 @@ function createPositionsOpenCommand() {
89669
90633
  otherAmountMax
89670
90634
  });
89671
90635
  const base64 = serializeTransaction(result.transaction);
89672
- console.log(JSON.stringify({ unsignedTransactions: [base64] }));
90636
+ if (mode === "unsigned-tx") {
90637
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
90638
+ return;
90639
+ }
90640
+ const ctx = requirePrivyContext(walletAddress);
90641
+ printPrivySignBanner();
90642
+ const broadcast = await privyBroadcastOne(ctx, base64);
90643
+ if (!broadcast.ok) {
90644
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
90645
+ else outputErrorTable(broadcast.error.toJSON());
90646
+ process.exit(1);
90647
+ }
90648
+ if (format === "json") {
90649
+ outputJson(
90650
+ {
90651
+ signature: broadcast.value.signature,
90652
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
90653
+ },
90654
+ startTime
90655
+ );
90656
+ } else {
90657
+ outputTransactionResult(broadcast.value.signature);
90658
+ }
89673
90659
  } catch (e) {
89674
90660
  const message = e.message || "Unknown SDK error";
89675
90661
  if (format === "json") {
@@ -89700,11 +90686,11 @@ function createPositionsIncreaseCommand() {
89700
90686
  ).option(
89701
90687
  "--amount-usd <usd>",
89702
90688
  "Investment amount in USD (auto-calculates token split, mutually exclusive with --amount)"
89703
- ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview without executing").action(async (options, cmdObj) => {
90689
+ ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--raw", "Amount is already in raw (smallest unit) format").option("--dry-run", "Preview without executing").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
89704
90690
  const globalOptions = cmdObj.optsWithGlobals();
89705
90691
  const format = globalOptions.output;
89706
90692
  const startTime = Date.now();
89707
- const mode = resolveExecutionMode(options);
90693
+ const mode = safeResolveExecutionMode(options, format);
89708
90694
  const walletAddress = globalOptions.walletAddress;
89709
90695
  if (!walletAddress) {
89710
90696
  const err2 = missingWalletAddressError();
@@ -89715,7 +90701,7 @@ function createPositionsIncreaseCommand() {
89715
90701
  }
89716
90702
  process.exit(1);
89717
90703
  }
89718
- const publicKey3 = new import_web3125.PublicKey(walletAddress);
90704
+ const publicKey3 = new import_web3126.PublicKey(walletAddress);
89719
90705
  const useAmountUsd = !!options.amountUsd;
89720
90706
  const useTokenAmount = !!options.amount;
89721
90707
  if (useAmountUsd && useTokenAmount) {
@@ -89768,7 +90754,7 @@ function createPositionsIncreaseCommand() {
89768
90754
  getAmountAFromAmountB: getAmountAFromAmountB2
89769
90755
  } = await Promise.resolve().then(() => (init_esm4(), esm_exports));
89770
90756
  const chain = getChain2();
89771
- const nftMint = new import_web3125.PublicKey(options.nftMint);
90757
+ const nftMint = new import_web3126.PublicKey(options.nftMint);
89772
90758
  const positionInfo = await chain.getPositionInfoByNftMint(nftMint);
89773
90759
  if (!positionInfo) {
89774
90760
  const errMsg = `Position not found for NFT mint: ${options.nftMint}`;
@@ -89951,7 +90937,7 @@ Error: ${errMsg}`));
89951
90937
  } else {
89952
90938
  console.log(source_default.green("\n Balance check: sufficient"));
89953
90939
  console.log(
89954
- source_default.yellow("\n Remove --dry-run to generate the unsigned transaction")
90940
+ source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
89955
90941
  );
89956
90942
  }
89957
90943
  }
@@ -89965,7 +90951,29 @@ Error: ${errMsg}`));
89965
90951
  otherAmountMax
89966
90952
  });
89967
90953
  const base64 = serializeTransaction(result.transaction);
89968
- console.log(JSON.stringify({ unsignedTransactions: [base64] }));
90954
+ if (mode === "unsigned-tx") {
90955
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
90956
+ return;
90957
+ }
90958
+ const ctx = requirePrivyContext(walletAddress);
90959
+ printPrivySignBanner();
90960
+ const broadcast = await privyBroadcastOne(ctx, base64);
90961
+ if (!broadcast.ok) {
90962
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
90963
+ else outputErrorTable(broadcast.error.toJSON());
90964
+ process.exit(1);
90965
+ }
90966
+ if (format === "json") {
90967
+ outputJson(
90968
+ {
90969
+ signature: broadcast.value.signature,
90970
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
90971
+ },
90972
+ startTime
90973
+ );
90974
+ } else {
90975
+ outputTransactionResult(broadcast.value.signature);
90976
+ }
89969
90977
  } catch (e) {
89970
90978
  const message = e.message || "Unknown SDK error";
89971
90979
  if (format === "json") {
@@ -89990,11 +90998,11 @@ function createPositionsDecreaseCommand() {
89990
90998
  return new Command("decrease").description("Remove part of the liquidity from a position (keeps position open)").requiredOption("--nft-mint <address>", "Position NFT mint address").option("--percentage <1-100>", "Percentage of liquidity to remove").option(
89991
90999
  "--amount-usd <usd>",
89992
91000
  "USD amount of liquidity to remove (mutually exclusive with --percentage)"
89993
- ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview without executing").action(async (options, cmdObj) => {
91001
+ ).option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview without executing").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
89994
91002
  const globalOptions = cmdObj.optsWithGlobals();
89995
91003
  const format = globalOptions.output;
89996
91004
  const startTime = Date.now();
89997
- const mode = resolveExecutionMode(options);
91005
+ const mode = safeResolveExecutionMode(options, format);
89998
91006
  const hasPercentage = options.percentage !== void 0;
89999
91007
  const hasAmountUsd = options.amountUsd !== void 0;
90000
91008
  if (hasPercentage && hasAmountUsd) {
@@ -90052,11 +91060,11 @@ function createPositionsDecreaseCommand() {
90052
91060
  }
90053
91061
  process.exit(1);
90054
91062
  }
90055
- const publicKey3 = new import_web3125.PublicKey(walletAddress);
91063
+ const publicKey3 = new import_web3126.PublicKey(walletAddress);
90056
91064
  try {
90057
91065
  const { getChain: getChain2 } = await Promise.resolve().then(() => (init_init(), init_exports));
90058
91066
  const chain = getChain2();
90059
- const nftMint = new import_web3125.PublicKey(options.nftMint);
91067
+ const nftMint = new import_web3126.PublicKey(options.nftMint);
90060
91068
  const positionInfo = await chain.getPositionInfoByNftMint(nftMint);
90061
91069
  if (!positionInfo) {
90062
91070
  const errMsg = `Position not found for NFT mint: ${options.nftMint}`;
@@ -90180,7 +91188,7 @@ Error: ${errMsg}`));
90180
91188
  } else {
90181
91189
  outputPositionDecreasePreview(previewData);
90182
91190
  console.log(
90183
- source_default.yellow("\n Remove --dry-run to generate the unsigned transaction")
91191
+ source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
90184
91192
  );
90185
91193
  }
90186
91194
  return;
@@ -90202,7 +91210,29 @@ Error: ${errMsg}`));
90202
91210
  });
90203
91211
  }
90204
91212
  const base64 = serializeTransaction(result.transaction);
90205
- console.log(JSON.stringify({ unsignedTransactions: [base64] }));
91213
+ if (mode === "unsigned-tx") {
91214
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
91215
+ return;
91216
+ }
91217
+ const ctx = requirePrivyContext(walletAddress);
91218
+ printPrivySignBanner();
91219
+ const broadcast = await privyBroadcastOne(ctx, base64);
91220
+ if (!broadcast.ok) {
91221
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
91222
+ else outputErrorTable(broadcast.error.toJSON());
91223
+ process.exit(1);
91224
+ }
91225
+ if (format === "json") {
91226
+ outputJson(
91227
+ {
91228
+ signature: broadcast.value.signature,
91229
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
91230
+ },
91231
+ startTime
91232
+ );
91233
+ } else {
91234
+ outputTransactionResult(broadcast.value.signature);
91235
+ }
90206
91236
  } catch (e) {
90207
91237
  const message = e.message || "Unknown SDK error";
90208
91238
  if (format === "json") {
@@ -90224,11 +91254,11 @@ SDK Error: ${message}`));
90224
91254
  });
90225
91255
  }
90226
91256
  function createPositionsCloseCommand() {
90227
- return new Command("close").description("Close a position (remove all liquidity)").requiredOption("--nft-mint <address>", "Position NFT mint address").option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview the close without executing").action(async (options, cmdObj) => {
91257
+ return new Command("close").description("Close a position (remove all liquidity)").requiredOption("--nft-mint <address>", "Position NFT mint address").option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview the close without executing").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
90228
91258
  const globalOptions = cmdObj.optsWithGlobals();
90229
91259
  const format = globalOptions.output;
90230
91260
  const startTime = Date.now();
90231
- const mode = resolveExecutionMode(options);
91261
+ const mode = safeResolveExecutionMode(options, format);
90232
91262
  const walletAddress = globalOptions.walletAddress;
90233
91263
  if (!walletAddress) {
90234
91264
  const err2 = missingWalletAddressError();
@@ -90239,11 +91269,11 @@ function createPositionsCloseCommand() {
90239
91269
  }
90240
91270
  process.exit(1);
90241
91271
  }
90242
- const publicKey3 = new import_web3125.PublicKey(walletAddress);
91272
+ const publicKey3 = new import_web3126.PublicKey(walletAddress);
90243
91273
  try {
90244
91274
  const { getChain: getChain2 } = await Promise.resolve().then(() => (init_init(), init_exports));
90245
91275
  const chain = getChain2();
90246
- const nftMint = new import_web3125.PublicKey(options.nftMint);
91276
+ const nftMint = new import_web3126.PublicKey(options.nftMint);
90247
91277
  const positionInfo = await chain.getPositionInfoByNftMint(nftMint);
90248
91278
  if (!positionInfo) {
90249
91279
  const errMsg = `Position not found for NFT mint: ${options.nftMint}`;
@@ -90302,7 +91332,7 @@ Error: ${errMsg}`));
90302
91332
  } else {
90303
91333
  outputPositionClosePreview(previewData);
90304
91334
  console.log(
90305
- source_default.yellow("\n Remove --dry-run to generate the unsigned transaction")
91335
+ source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
90306
91336
  );
90307
91337
  }
90308
91338
  return;
@@ -90315,7 +91345,29 @@ Error: ${errMsg}`));
90315
91345
  slippage
90316
91346
  });
90317
91347
  const base64 = serializeTransaction(result.transaction);
90318
- console.log(JSON.stringify({ unsignedTransactions: [base64] }));
91348
+ if (mode === "unsigned-tx") {
91349
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
91350
+ return;
91351
+ }
91352
+ const ctx = requirePrivyContext(walletAddress);
91353
+ printPrivySignBanner();
91354
+ const broadcast = await privyBroadcastOne(ctx, base64);
91355
+ if (!broadcast.ok) {
91356
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
91357
+ else outputErrorTable(broadcast.error.toJSON());
91358
+ process.exit(1);
91359
+ }
91360
+ if (format === "json") {
91361
+ outputJson(
91362
+ {
91363
+ signature: broadcast.value.signature,
91364
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
91365
+ },
91366
+ startTime
91367
+ );
91368
+ } else {
91369
+ outputTransactionResult(broadcast.value.signature);
91370
+ }
90319
91371
  } catch (e) {
90320
91372
  const message = e.message || "Unknown SDK error";
90321
91373
  if (format === "json") {
@@ -90340,11 +91392,11 @@ function createPositionsClaimCommand() {
90340
91392
  return new Command("claim").description("Claim accumulated fees from positions").requiredOption(
90341
91393
  "--nft-mints <addresses>",
90342
91394
  "Comma-separated NFT mint addresses (from positions list)"
90343
- ).option("--dry-run", "Preview the claim without executing").action(async (options, cmdObj) => {
91395
+ ).option("--dry-run", "Preview the claim without executing").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
90344
91396
  const globalOptions = cmdObj.optsWithGlobals();
90345
91397
  const format = globalOptions.output;
90346
91398
  const startTime = Date.now();
90347
- const mode = resolveExecutionMode(options);
91399
+ const mode = safeResolveExecutionMode(options, format);
90348
91400
  const walletAddress = globalOptions.walletAddress;
90349
91401
  if (!walletAddress) {
90350
91402
  const err2 = missingWalletAddressError();
@@ -90448,20 +91500,53 @@ Error: ${errMsg}`));
90448
91500
  outputJson({ mode: "dry-run", entries: enrichedEntries }, startTime);
90449
91501
  } else {
90450
91502
  outputPositionClaimPreview(enrichedEntries);
90451
- console.log(source_default.yellow("\n Remove --dry-run to generate the unsigned transaction(s)"));
91503
+ console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
90452
91504
  }
90453
91505
  return;
90454
91506
  }
90455
91507
  const unsignedTransactions = entries.map((entry) => entry.txPayload);
90456
- console.log(JSON.stringify({ unsignedTransactions }));
91508
+ if (mode === "unsigned-tx") {
91509
+ console.log(JSON.stringify({ unsignedTransactions }));
91510
+ return;
91511
+ }
91512
+ try {
91513
+ const ctx = requirePrivyContext(walletAddress);
91514
+ printPrivySignBanner();
91515
+ const broadcast = await privyBroadcastMany(ctx, unsignedTransactions);
91516
+ if (!broadcast.ok) {
91517
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
91518
+ else outputErrorTable(broadcast.error.toJSON());
91519
+ process.exit(1);
91520
+ }
91521
+ if (format === "json") {
91522
+ outputJson(broadcast.value, startTime);
91523
+ } else {
91524
+ outputMultiBroadcastResult(broadcast.value);
91525
+ }
91526
+ if (broadcast.value.failCount > 0) process.exit(1);
91527
+ } catch (e) {
91528
+ if (e instanceof ByrealError) {
91529
+ if (format === "json") outputErrorJson(e.toJSON());
91530
+ else outputErrorTable(e.toJSON());
91531
+ } else {
91532
+ const message = e.message || "Unknown error";
91533
+ if (format === "json") {
91534
+ outputErrorJson({ code: "UNKNOWN_ERROR", type: "SYSTEM", message, retryable: false });
91535
+ } else {
91536
+ console.error(source_default.red(`
91537
+ Error: ${message}`));
91538
+ }
91539
+ }
91540
+ process.exit(1);
91541
+ }
90457
91542
  });
90458
91543
  }
90459
91544
  function createPositionsClaimRewardsCommand() {
90460
- return new Command("claim-rewards").description("Claim incentive rewards from positions").option("--dry-run", "Preview unclaimed rewards without claiming").action(async (options, cmdObj) => {
91545
+ return new Command("claim-rewards").description("Claim incentive rewards from positions").option("--dry-run", "Preview unclaimed rewards without claiming").option("--execute", "Sign via Privy and submit to backend (default emits unsigned tx for external signers)").action(async (options, cmdObj) => {
90461
91546
  const globalOptions = cmdObj.optsWithGlobals();
90462
91547
  const format = globalOptions.output;
90463
91548
  const startTime = Date.now();
90464
- const mode = resolveExecutionMode(options);
91549
+ const mode = safeResolveExecutionMode(options, format);
90465
91550
  const walletAddress = globalOptions.walletAddress;
90466
91551
  if (!walletAddress) {
90467
91552
  const err2 = missingWalletAddressError();
@@ -90521,7 +91606,7 @@ function createPositionsClaimRewardsCommand() {
90521
91606
  console.log(source_default.gray("\n No unclaimed incentive rewards.\n"));
90522
91607
  } else {
90523
91608
  console.log(
90524
- source_default.yellow("\n Remove --dry-run to generate the unsigned transaction(s)")
91609
+ source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
90525
91610
  );
90526
91611
  }
90527
91612
  }
@@ -90539,6 +91624,7 @@ function createPositionsClaimRewardsCommand() {
90539
91624
  return;
90540
91625
  }
90541
91626
  const positionAddresses = [...new Set(allRewards.map((r) => r.positionAddress))];
91627
+ if (mode === "execute") requirePrivyContext(walletAddress);
90542
91628
  const encodeResult = await api.encodeReward({
90543
91629
  walletAddress,
90544
91630
  positionAddresses,
@@ -90564,14 +91650,52 @@ function createPositionsClaimRewardsCommand() {
90564
91650
  }
90565
91651
  return;
90566
91652
  }
90567
- const txPayloads = rewardEncodeItems.map((item) => ({
90568
- poolAddress: item.poolAddress,
90569
- txPayload: item.txPayload,
90570
- txCode: item.txCode,
90571
- tokens: item.rewardClaimInfo
90572
- }));
90573
- console.log(JSON.stringify({ orderCode, unsignedTransactions: txPayloads }));
91653
+ if (mode === "unsigned-tx") {
91654
+ const txPayloads = rewardEncodeItems.map((item) => ({
91655
+ poolAddress: item.poolAddress,
91656
+ txPayload: item.txPayload,
91657
+ txCode: item.txCode,
91658
+ tokens: item.rewardClaimInfo
91659
+ }));
91660
+ console.log(JSON.stringify({ orderCode, unsignedTransactions: txPayloads }));
91661
+ return;
91662
+ }
91663
+ const ctx = requirePrivyContext(walletAddress);
91664
+ printPrivySignBanner();
91665
+ const signResult = await privySignMany(
91666
+ ctx,
91667
+ rewardEncodeItems.map((item) => item.txPayload)
91668
+ );
91669
+ if (!signResult.ok) {
91670
+ if (format === "json") outputErrorJson(signResult.error.toJSON());
91671
+ else outputErrorTable(signResult.error.toJSON());
91672
+ process.exit(1);
91673
+ }
91674
+ const submitResult = await api.submitRewardOrder({
91675
+ orderCode,
91676
+ walletAddress,
91677
+ signedTxPayload: rewardEncodeItems.map((item, i) => ({
91678
+ txCode: item.txCode,
91679
+ poolAddress: item.poolAddress,
91680
+ signedTx: signResult.value.signedTxs[i].signedTx
91681
+ }))
91682
+ });
91683
+ if (!submitResult.ok) {
91684
+ if (format === "json") outputErrorJson(submitResult.error);
91685
+ else outputErrorTable(submitResult.error);
91686
+ process.exit(1);
91687
+ }
91688
+ if (format === "json") {
91689
+ outputJson(submitResult.value, startTime);
91690
+ } else {
91691
+ outputRewardOrderResult(submitResult.value);
91692
+ }
90574
91693
  } catch (e) {
91694
+ if (e instanceof ByrealError) {
91695
+ if (format === "json") outputErrorJson(e.toJSON());
91696
+ else outputErrorTable(e.toJSON());
91697
+ process.exit(1);
91698
+ }
90575
91699
  const message = e.message || "Unknown error";
90576
91700
  if (format === "json") {
90577
91701
  outputErrorJson({ code: "SDK_ERROR", type: "SYSTEM", message, retryable: false });
@@ -90587,11 +91711,11 @@ Error: ${message}`));
90587
91711
  });
90588
91712
  }
90589
91713
  function createPositionsClaimBonusCommand() {
90590
- return new Command("claim-bonus").description("Claim CopyFarmer bonus rewards").option("--dry-run", "Preview claimable bonus without claiming").action(async (options, cmdObj) => {
91714
+ return new Command("claim-bonus").description("Claim CopyFarmer bonus rewards").option("--dry-run", "Preview claimable bonus without claiming").option("--execute", "Sign via Privy and submit to backend (default emits unsigned tx for external signers)").action(async (options, cmdObj) => {
90591
91715
  const globalOptions = cmdObj.optsWithGlobals();
90592
91716
  const format = globalOptions.output;
90593
91717
  const startTime = Date.now();
90594
- const mode = resolveExecutionMode(options);
91718
+ const mode = safeResolveExecutionMode(options, format);
90595
91719
  const walletAddress = globalOptions.walletAddress;
90596
91720
  if (!walletAddress) {
90597
91721
  const err2 = missingWalletAddressError();
@@ -90642,7 +91766,7 @@ function createPositionsClaimBonusCommand() {
90642
91766
  outputBonusPreview(overview, epochs);
90643
91767
  if (canClaim) {
90644
91768
  console.log(
90645
- source_default.yellow(` Remove --dry-run to claim $${claimableEpoch.totalBonusUsd} bonus
91769
+ source_default.yellow(` Remove --dry-run to emit an unsigned tx; add --execute to claim $${claimableEpoch.totalBonusUsd} bonus via Privy.
90646
91770
  `)
90647
91771
  );
90648
91772
  } else {
@@ -90662,6 +91786,7 @@ function createPositionsClaimBonusCommand() {
90662
91786
  }
90663
91787
  return;
90664
91788
  }
91789
+ if (mode === "execute") requirePrivyContext(walletAddress);
90665
91790
  const encodeResult = await api.encodeReward({
90666
91791
  walletAddress,
90667
91792
  positionAddresses: [],
@@ -90687,14 +91812,52 @@ function createPositionsClaimBonusCommand() {
90687
91812
  }
90688
91813
  return;
90689
91814
  }
90690
- const txPayloads = rewardEncodeItems.map((item) => ({
90691
- poolAddress: item.poolAddress,
90692
- txPayload: item.txPayload,
90693
- txCode: item.txCode,
90694
- tokens: item.rewardClaimInfo
90695
- }));
90696
- console.log(JSON.stringify({ orderCode, unsignedTransactions: txPayloads }));
91815
+ if (mode === "unsigned-tx") {
91816
+ const txPayloads = rewardEncodeItems.map((item) => ({
91817
+ poolAddress: item.poolAddress,
91818
+ txPayload: item.txPayload,
91819
+ txCode: item.txCode,
91820
+ tokens: item.rewardClaimInfo
91821
+ }));
91822
+ console.log(JSON.stringify({ orderCode, unsignedTransactions: txPayloads }));
91823
+ return;
91824
+ }
91825
+ const ctx = requirePrivyContext(walletAddress);
91826
+ printPrivySignBanner();
91827
+ const signResult = await privySignMany(
91828
+ ctx,
91829
+ rewardEncodeItems.map((item) => item.txPayload)
91830
+ );
91831
+ if (!signResult.ok) {
91832
+ if (format === "json") outputErrorJson(signResult.error.toJSON());
91833
+ else outputErrorTable(signResult.error.toJSON());
91834
+ process.exit(1);
91835
+ }
91836
+ const submitResult = await api.submitRewardOrder({
91837
+ orderCode,
91838
+ walletAddress,
91839
+ signedTxPayload: rewardEncodeItems.map((item, i) => ({
91840
+ txCode: item.txCode,
91841
+ poolAddress: item.poolAddress,
91842
+ signedTx: signResult.value.signedTxs[i].signedTx
91843
+ }))
91844
+ });
91845
+ if (!submitResult.ok) {
91846
+ if (format === "json") outputErrorJson(submitResult.error);
91847
+ else outputErrorTable(submitResult.error);
91848
+ process.exit(1);
91849
+ }
91850
+ if (format === "json") {
91851
+ outputJson(submitResult.value, startTime);
91852
+ } else {
91853
+ outputRewardOrderResult(submitResult.value);
91854
+ }
90697
91855
  } catch (e) {
91856
+ if (e instanceof ByrealError) {
91857
+ if (format === "json") outputErrorJson(e.toJSON());
91858
+ else outputErrorTable(e.toJSON());
91859
+ process.exit(1);
91860
+ }
90698
91861
  const message = e.message || "Unknown error";
90699
91862
  if (format === "json") {
90700
91863
  outputErrorJson({ code: "SDK_ERROR", type: "SYSTEM", message, retryable: false });
@@ -90775,7 +91938,7 @@ Error: ${errMsg}`));
90775
91938
  const pool = poolResult.value;
90776
91939
  const { getChain: getChain2 } = await Promise.resolve().then(() => (init_init(), init_exports));
90777
91940
  const chain = getChain2();
90778
- const nftMint = new import_web3125.PublicKey(nftMintStr);
91941
+ const nftMint = new import_web3126.PublicKey(nftMintStr);
90779
91942
  const positionInfo = await chain.getPositionInfoByNftMint(nftMint);
90780
91943
  if (!positionInfo) {
90781
91944
  const errMsg = `Position not found on-chain for NFT mint: ${nftMintStr}`;
@@ -90958,11 +92121,11 @@ function createTopPositionsCommand() {
90958
92121
  function createCopyPositionCommand() {
90959
92122
  return new Command("copy").description(
90960
92123
  "Copy an existing position with referral bonus"
90961
- ).requiredOption("--position <address>", "Position PDA address to copy").requiredOption("--amount-usd <usd>", "Investment amount in USD").option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview the copy without executing").action(async (options, cmdObj) => {
92124
+ ).requiredOption("--position <address>", "Position PDA address to copy").requiredOption("--amount-usd <usd>", "Investment amount in USD").option("--slippage <bps>", "Slippage tolerance in basis points").option("--dry-run", "Preview the copy without executing").option("--execute", "Sign + broadcast on-chain via Privy (default emits unsigned tx for back-compat)").action(async (options, cmdObj) => {
90962
92125
  const globalOptions = cmdObj.optsWithGlobals();
90963
92126
  const format = globalOptions.output;
90964
92127
  const startTime = Date.now();
90965
- const mode = resolveExecutionMode(options);
92128
+ const mode = safeResolveExecutionMode(options, format);
90966
92129
  const walletAddress = globalOptions.walletAddress;
90967
92130
  if (!walletAddress) {
90968
92131
  const err2 = missingWalletAddressError();
@@ -90973,9 +92136,9 @@ function createCopyPositionCommand() {
90973
92136
  }
90974
92137
  process.exit(1);
90975
92138
  }
90976
- const publicKey3 = new import_web3125.PublicKey(walletAddress);
92139
+ const publicKey3 = new import_web3126.PublicKey(walletAddress);
90977
92140
  try {
90978
- const positionAddress = new import_web3125.PublicKey(options.position);
92141
+ const positionAddress = new import_web3126.PublicKey(options.position);
90979
92142
  const { getChain: getChain2 } = await Promise.resolve().then(() => (init_init(), init_exports));
90980
92143
  const { calculateTokenAmountsFromUsd: calculateTokenAmountsFromUsd2, getRawPositionInfoByAddress: getRawPositionInfoByAddress2 } = await Promise.resolve().then(() => (init_calculate(), calculate_exports));
90981
92144
  const chain = getChain2();
@@ -91145,7 +92308,7 @@ Error: ${errMsg}`));
91145
92308
  console.log(source_default.green("\n Balance check: sufficient"));
91146
92309
  console.log(
91147
92310
  source_default.yellow(
91148
- "\n Remove --dry-run to generate the unsigned transaction"
92311
+ "\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."
91149
92312
  )
91150
92313
  );
91151
92314
  }
@@ -91163,7 +92326,29 @@ Error: ${errMsg}`));
91163
92326
  refererPosition: options.position
91164
92327
  });
91165
92328
  const base64 = serializeTransaction(result.transaction);
91166
- console.log(JSON.stringify({ unsignedTransactions: [base64] }));
92329
+ if (mode === "unsigned-tx") {
92330
+ console.log(JSON.stringify({ unsignedTransactions: [base64] }));
92331
+ return;
92332
+ }
92333
+ const ctx = requirePrivyContext(walletAddress);
92334
+ printPrivySignBanner();
92335
+ const broadcast = await privyBroadcastOne(ctx, base64);
92336
+ if (!broadcast.ok) {
92337
+ if (format === "json") outputErrorJson(broadcast.error.toJSON());
92338
+ else outputErrorTable(broadcast.error.toJSON());
92339
+ process.exit(1);
92340
+ }
92341
+ if (format === "json") {
92342
+ outputJson(
92343
+ {
92344
+ signature: broadcast.value.signature,
92345
+ explorer: `https://solscan.io/tx/${broadcast.value.signature}`
92346
+ },
92347
+ startTime
92348
+ );
92349
+ } else {
92350
+ outputTransactionResult(broadcast.value.signature);
92351
+ }
91167
92352
  } catch (e) {
91168
92353
  const message = e.message || "Unknown SDK error";
91169
92354
  if (format === "json") {