@byreal-io/byreal-cli-realclaw 0.3.13 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -4
- package/dist/index.cjs +1104 -142
- 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
|
|
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 (
|
|
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) =>
|
|
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 =
|
|
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.
|
|
3036
|
+
INJECTED_VERSION = true ? "0.4.1" : 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
|
|
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
|
|
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" &&
|
|
20397
|
+
return platform2 === "linux" && fs3.existsSync("/etc/alpine-release");
|
|
20388
20398
|
}
|
|
20389
20399
|
load.parseTags = parseTags;
|
|
20390
20400
|
load.matchTags = matchTags;
|
|
@@ -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
|
|
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 =
|
|
36110
|
+
var exists = fs3.accessSync && function(path4) {
|
|
36101
36111
|
try {
|
|
36102
|
-
|
|
36112
|
+
fs3.accessSync(path4);
|
|
36103
36113
|
} catch (e) {
|
|
36104
36114
|
return false;
|
|
36105
36115
|
}
|
|
36106
36116
|
return true;
|
|
36107
|
-
} ||
|
|
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
|
});
|
|
@@ -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
|
|
62528
|
+
const fs3 = require("fs");
|
|
62377
62529
|
const path3 = require("path");
|
|
62378
|
-
const anchorToml = toml.parse(
|
|
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 =
|
|
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 (!
|
|
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(
|
|
62553
|
+
const idl = JSON.parse(fs3.readFileSync(idlPath));
|
|
62402
62554
|
if (programId) {
|
|
62403
62555
|
idl.address = programId;
|
|
62404
62556
|
}
|
|
@@ -84780,6 +84932,30 @@ init_config();
|
|
|
84780
84932
|
var import_cli_table3 = __toESM(require_cli_table3(), 1);
|
|
84781
84933
|
init_constants();
|
|
84782
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
|
+
|
|
84783
84959
|
// src/core/amounts.ts
|
|
84784
84960
|
function uiToRaw(uiAmount, decimals) {
|
|
84785
84961
|
const parts = uiAmount.split(".");
|
|
@@ -84816,6 +84992,18 @@ function outputJson(data, startTime) {
|
|
|
84816
84992
|
function outputErrorJson(error) {
|
|
84817
84993
|
console.log(JSON.stringify({ success: false, error }, null, 2));
|
|
84818
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
|
+
}
|
|
84819
85007
|
function createTable(headers) {
|
|
84820
85008
|
return new import_cli_table3.default({
|
|
84821
85009
|
head: headers.map((h) => source_default.cyan.bold(h)),
|
|
@@ -85051,6 +85239,12 @@ function outputConfigList(config3) {
|
|
|
85051
85239
|
["defaults.priority_fee_micro_lamports", String(config3.defaults.priority_fee_micro_lamports)],
|
|
85052
85240
|
["defaults.slippage_bps", String(config3.defaults.slippage_bps)]
|
|
85053
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
|
+
}
|
|
85054
85248
|
console.log(table.toString());
|
|
85055
85249
|
}
|
|
85056
85250
|
function outputConfigValue(key, value) {
|
|
@@ -85547,6 +85741,31 @@ function outputRewardOrderResult(result) {
|
|
|
85547
85741
|
console.log();
|
|
85548
85742
|
}
|
|
85549
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
|
+
}
|
|
85550
85769
|
|
|
85551
85770
|
// src/cli/commands/pools.ts
|
|
85552
85771
|
async function listPools2(options, globalOptions) {
|
|
@@ -86104,12 +86323,38 @@ byreal-cli catalog show dex.pool.list
|
|
|
86104
86323
|
| -v, --version | Show version |
|
|
86105
86324
|
| -h, --help | Show help |
|
|
86106
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
|
+
|
|
86107
86352
|
## Hard Constraints (Do NOT violate)
|
|
86108
86353
|
|
|
86109
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.
|
|
86110
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\`.
|
|
86111
|
-
3. **Never request or display private keys** \u2014 the CLI does not
|
|
86112
|
-
4. **\`--wallet-address\` required for all write commands** \u2014 the user must provide their Solana wallet public key.
|
|
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.
|
|
86113
86358
|
5. **Large amounts (> $10,000)**: Require explicit user confirmation
|
|
86114
86359
|
6. **High slippage (> 200 bps)**: Warn user before proceeding
|
|
86115
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.
|
|
@@ -86136,7 +86381,8 @@ Present on-chain data first, then external context, then synthesize how external
|
|
|
86136
86381
|
| List tokens | \`byreal-cli tokens list\` |
|
|
86137
86382
|
| Global stats | \`byreal-cli overview\` |
|
|
86138
86383
|
| Swap preview | \`byreal-cli swap execute --input-mint <mint> --output-mint <mint> --amount <amount> --dry-run\` |
|
|
86139
|
-
| Swap
|
|
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\` |
|
|
86140
86386
|
| List positions | \`byreal-cli positions list\` |
|
|
86141
86387
|
| Open position (USD) | \`byreal-cli positions open --pool <addr> --price-lower <p> --price-upper <p> --amount-usd <usd> --wallet-address <addr>\` |
|
|
86142
86388
|
| Open position (token) | \`byreal-cli positions open --pool <addr> --price-lower <p> --price-upper <p> --base <token> --amount <amount> --wallet-address <addr>\` |
|
|
@@ -86194,13 +86440,23 @@ For detailed parameter info on any command, run: \`byreal-cli catalog show <capa
|
|
|
86194
86440
|
- **Incentive rewards** \u2192 \`positions claim-rewards\` (team-added pool incentives)
|
|
86195
86441
|
- **Copy bonus** \u2192 \`positions claim-bonus\` (referral rewards from copy trading)
|
|
86196
86442
|
|
|
86197
|
-
### Claim Rewards / Bonus:
|
|
86198
|
-
|
|
86199
|
-
|
|
86200
|
-
|
|
86201
|
-
|
|
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.
|
|
86453
|
+
|
|
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>\`
|
|
86202
86458
|
|
|
86203
|
-
|
|
86459
|
+
The multi-step flow is the default for backward compatibility; if Privy is configured, prefer \`--execute\` for the one-shot atomic command.
|
|
86204
86460
|
|
|
86205
86461
|
### Copy Bonus Epochs
|
|
86206
86462
|
- **Accruing**: Current epoch, bonus accumulating
|
|
@@ -86211,7 +86467,7 @@ For detailed parameter info on any command, run: \`byreal-cli catalog show <capa
|
|
|
86211
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.
|
|
86212
86468
|
|
|
86213
86469
|
### Config Keys
|
|
86214
|
-
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
|
|
86215
86471
|
|
|
86216
86472
|
## Workflow: Finding Investment Opportunities
|
|
86217
86473
|
|
|
@@ -86229,7 +86485,7 @@ When the user asks about investment opportunities, potential pools, or yield far
|
|
|
86229
86485
|
- USD budget: \`positions open --pool <id> --price-lower <p> --price-upper <p> --amount-usd <usd> --dry-run -o json\`
|
|
86230
86486
|
- Token amount: \`positions open --pool <id> --price-lower <p> --price-upper <p> --base MintA --amount <amt> --dry-run -o json\`
|
|
86231
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).
|
|
86232
|
-
5. **
|
|
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 }\`.
|
|
86233
86489
|
|
|
86234
86490
|
## Workflow: Increase/Decrease Liquidity
|
|
86235
86491
|
|
|
@@ -86239,12 +86495,12 @@ When user wants to add more liquidity to an existing position or partially withd
|
|
|
86239
86495
|
1. \`byreal-cli positions list -o json\` \u2014 find the position's NFT mint address
|
|
86240
86496
|
2. \`byreal-cli positions increase --nft-mint <nft-mint> --amount-usd <usd> --dry-run -o json\` \u2014 preview (includes balance check)
|
|
86241
86497
|
3. If insufficient balance \u2192 swap to get required tokens (see "Insufficient Balance" workflow)
|
|
86242
|
-
4. \`byreal-cli positions increase --nft-mint <nft-mint> --amount-usd <usd> --wallet-address <addr> -o json\` \u2014
|
|
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.
|
|
86243
86499
|
|
|
86244
86500
|
**Decrease liquidity** (partial withdrawal):
|
|
86245
86501
|
1. \`byreal-cli positions list -o json\` \u2014 find the position's NFT mint address
|
|
86246
86502
|
2. \`byreal-cli positions decrease --nft-mint <nft-mint> --percentage 50 --dry-run -o json\` \u2014 preview how much you'll receive
|
|
86247
|
-
3. \`byreal-cli positions decrease --nft-mint <nft-mint> --percentage 50 --wallet-address <addr> -o json\` \u2014
|
|
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.
|
|
86248
86504
|
|
|
86249
86505
|
**Key distinction**: Use \`decrease\` to partially withdraw while keeping the position open. Use \`close\` to fully exit and burn the NFT.
|
|
86250
86506
|
|
|
@@ -86290,14 +86546,15 @@ When user asks vague questions like "\u6709\u4EC0\u4E48\u4ED3\u4F4D\u53EF\u4EE5
|
|
|
86290
86546
|
|
|
86291
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.
|
|
86292
86548
|
|
|
86293
|
-
## Workflow: Jupiter / DFlow Swap
|
|
86549
|
+
## Workflow: Jupiter / Titan / DFlow Swap
|
|
86294
86550
|
|
|
86295
86551
|
\`\`\`
|
|
86296
|
-
byreal-cli jup swap --input-mint <mint> --output-mint <mint> --amount <amt> [--dry-run] --wallet-address <addr>
|
|
86297
|
-
byreal-cli
|
|
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>
|
|
86298
86555
|
\`\`\`
|
|
86299
86556
|
|
|
86300
|
-
|
|
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.
|
|
86301
86558
|
|
|
86302
86559
|
## Workflow: Idle Yield with Kamino
|
|
86303
86560
|
|
|
@@ -86410,17 +86667,311 @@ async function resolveDecimals(mint) {
|
|
|
86410
86667
|
return decimals;
|
|
86411
86668
|
}
|
|
86412
86669
|
|
|
86413
|
-
// src/
|
|
86414
|
-
|
|
86415
|
-
|
|
86416
|
-
|
|
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
|
+
}
|
|
86417
86709
|
}
|
|
86418
|
-
function
|
|
86419
|
-
|
|
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
|
+
};
|
|
86420
86785
|
}
|
|
86421
86786
|
|
|
86422
|
-
// src/
|
|
86787
|
+
// src/privy/client.ts
|
|
86788
|
+
init_constants();
|
|
86789
|
+
init_types();
|
|
86423
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();
|
|
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
|
|
86424
86975
|
init_constants();
|
|
86425
86976
|
|
|
86426
86977
|
// src/plugins/jupiter/api.ts
|
|
@@ -86765,11 +87316,11 @@ function fallbackHint(route) {
|
|
|
86765
87316
|
return null;
|
|
86766
87317
|
}
|
|
86767
87318
|
function createJupSwapCommand() {
|
|
86768
|
-
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) => {
|
|
86769
87320
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
86770
87321
|
const format = globalOptions.output;
|
|
86771
87322
|
const startTime = Date.now();
|
|
86772
|
-
const mode =
|
|
87323
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
86773
87324
|
const walletAddress = globalOptions.walletAddress;
|
|
86774
87325
|
if (!walletAddress) {
|
|
86775
87326
|
const e = missingWalletAddressError();
|
|
@@ -86831,7 +87382,7 @@ Error: ${msg}`));
|
|
|
86831
87382
|
console.log(table.toString());
|
|
86832
87383
|
const hint = fallbackHint(getLastRoute());
|
|
86833
87384
|
if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
|
|
86834
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
87385
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
86835
87386
|
}
|
|
86836
87387
|
return;
|
|
86837
87388
|
}
|
|
@@ -86844,8 +87395,31 @@ Error: ${msg}`));
|
|
|
86844
87395
|
format === "json" ? outputErrorJson(swapResult.error) : outputErrorTable(swapResult.error);
|
|
86845
87396
|
process.exit(1);
|
|
86846
87397
|
}
|
|
86847
|
-
|
|
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
|
+
}
|
|
86848
87418
|
} catch (e) {
|
|
87419
|
+
if (e instanceof ByrealError) {
|
|
87420
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
87421
|
+
process.exit(1);
|
|
87422
|
+
}
|
|
86849
87423
|
const message = e.message || "Jupiter swap failed";
|
|
86850
87424
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
86851
87425
|
Error: ${message}`));
|
|
@@ -87196,11 +87770,11 @@ Error: ${msg}`));
|
|
|
87196
87770
|
return walletAddress;
|
|
87197
87771
|
}
|
|
87198
87772
|
function createKaminoDepositCommand() {
|
|
87199
|
-
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) => {
|
|
87200
87774
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
87201
87775
|
const format = globalOptions.output;
|
|
87202
87776
|
const startTime = Date.now();
|
|
87203
|
-
const mode =
|
|
87777
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
87204
87778
|
const walletAddress = validateWallet(globalOptions.walletAddress, format);
|
|
87205
87779
|
try {
|
|
87206
87780
|
const reserve = options.reserve ?? resolveReserve(options.mint, options.market);
|
|
@@ -87226,7 +87800,7 @@ function createKaminoDepositCommand() {
|
|
|
87226
87800
|
);
|
|
87227
87801
|
console.log(source_default.cyan.bold("\n Kamino Deposit Preview\n"));
|
|
87228
87802
|
console.log(table.toString());
|
|
87229
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
87803
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
87230
87804
|
}
|
|
87231
87805
|
return;
|
|
87232
87806
|
}
|
|
@@ -87240,8 +87814,31 @@ function createKaminoDepositCommand() {
|
|
|
87240
87814
|
format === "json" ? outputErrorJson(result.error) : outputErrorTable(result.error);
|
|
87241
87815
|
process.exit(1);
|
|
87242
87816
|
}
|
|
87243
|
-
|
|
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
|
+
}
|
|
87244
87837
|
} catch (e) {
|
|
87838
|
+
if (e instanceof ByrealError) {
|
|
87839
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
87840
|
+
process.exit(1);
|
|
87841
|
+
}
|
|
87245
87842
|
const message = e.message || "Kamino deposit failed";
|
|
87246
87843
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
87247
87844
|
Error: ${message}`));
|
|
@@ -87250,11 +87847,11 @@ Error: ${message}`));
|
|
|
87250
87847
|
});
|
|
87251
87848
|
}
|
|
87252
87849
|
function createKaminoWithdrawCommand() {
|
|
87253
|
-
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) => {
|
|
87254
87851
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
87255
87852
|
const format = globalOptions.output;
|
|
87256
87853
|
const startTime = Date.now();
|
|
87257
|
-
const mode =
|
|
87854
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
87258
87855
|
const walletAddress = validateWallet(globalOptions.walletAddress, format);
|
|
87259
87856
|
try {
|
|
87260
87857
|
const reserve = options.reserve ?? resolveReserve(options.mint, options.market);
|
|
@@ -87280,7 +87877,7 @@ function createKaminoWithdrawCommand() {
|
|
|
87280
87877
|
);
|
|
87281
87878
|
console.log(source_default.cyan.bold("\n Kamino Withdraw Preview\n"));
|
|
87282
87879
|
console.log(table.toString());
|
|
87283
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
87880
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
87284
87881
|
}
|
|
87285
87882
|
return;
|
|
87286
87883
|
}
|
|
@@ -87294,8 +87891,31 @@ function createKaminoWithdrawCommand() {
|
|
|
87294
87891
|
format === "json" ? outputErrorJson(result.error) : outputErrorTable(result.error);
|
|
87295
87892
|
process.exit(1);
|
|
87296
87893
|
}
|
|
87297
|
-
|
|
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
|
+
}
|
|
87298
87914
|
} catch (e) {
|
|
87915
|
+
if (e instanceof ByrealError) {
|
|
87916
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
87917
|
+
process.exit(1);
|
|
87918
|
+
}
|
|
87299
87919
|
const message = e.message || "Kamino withdraw failed";
|
|
87300
87920
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
87301
87921
|
Error: ${message}`));
|
|
@@ -87606,11 +88226,11 @@ async function findEmptyAccounts(connection, owner, programId, exceptions) {
|
|
|
87606
88226
|
|
|
87607
88227
|
// src/plugins/rent/commands.ts
|
|
87608
88228
|
function createRentReclaimCommand() {
|
|
87609
|
-
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) => {
|
|
87610
88230
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
87611
88231
|
const format = globalOptions.output;
|
|
87612
88232
|
const startTime = Date.now();
|
|
87613
|
-
const mode =
|
|
88233
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
87614
88234
|
const walletAddress = globalOptions.walletAddress;
|
|
87615
88235
|
if (!walletAddress) {
|
|
87616
88236
|
const e = missingWalletAddressError();
|
|
@@ -87669,13 +88289,33 @@ Error: ${msg}`));
|
|
|
87669
88289
|
acctTable.push([a.pubkey, a.mint, progLabel]);
|
|
87670
88290
|
}
|
|
87671
88291
|
console.log(acctTable.toString());
|
|
87672
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
88292
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
87673
88293
|
}
|
|
87674
88294
|
return;
|
|
87675
88295
|
}
|
|
87676
88296
|
const txs = await buildCloseTransactions(walletAddress, scan.emptyAccounts);
|
|
87677
|
-
|
|
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);
|
|
87678
88314
|
} catch (e) {
|
|
88315
|
+
if (e instanceof ByrealError) {
|
|
88316
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
88317
|
+
process.exit(1);
|
|
88318
|
+
}
|
|
87679
88319
|
const message = e.message || "Rent reclaim failed";
|
|
87680
88320
|
format === "json" ? outputErrorJson({ code: "RPC_ERROR", type: "SYSTEM", message, retryable: true }) : console.error(source_default.red(`
|
|
87681
88321
|
Error: ${message}`));
|
|
@@ -87848,11 +88488,11 @@ async function executeSweep(params) {
|
|
|
87848
88488
|
|
|
87849
88489
|
// src/plugins/consolidate/commands.ts
|
|
87850
88490
|
function createSweepExecuteCommand() {
|
|
87851
|
-
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) => {
|
|
87852
88492
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
87853
88493
|
const format = globalOptions.output;
|
|
87854
88494
|
const startTime = Date.now();
|
|
87855
|
-
const mode =
|
|
88495
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
87856
88496
|
const walletAddress = globalOptions.walletAddress;
|
|
87857
88497
|
if (!walletAddress) {
|
|
87858
88498
|
const e = missingWalletAddressError();
|
|
@@ -87936,7 +88576,7 @@ Error: ${msg}`));
|
|
|
87936
88576
|
]);
|
|
87937
88577
|
}
|
|
87938
88578
|
console.log(tokenTable.toString());
|
|
87939
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
88579
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
87940
88580
|
}
|
|
87941
88581
|
return;
|
|
87942
88582
|
}
|
|
@@ -87961,12 +88601,36 @@ Error: ${msg}`));
|
|
|
87961
88601
|
}
|
|
87962
88602
|
return;
|
|
87963
88603
|
}
|
|
87964
|
-
|
|
87965
|
-
|
|
87966
|
-
|
|
87967
|
-
|
|
87968
|
-
|
|
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);
|
|
87969
88629
|
} catch (e) {
|
|
88630
|
+
if (e instanceof ByrealError) {
|
|
88631
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
88632
|
+
process.exit(1);
|
|
88633
|
+
}
|
|
87970
88634
|
const message = e.message || "Token consolidation failed";
|
|
87971
88635
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
87972
88636
|
Error: ${message}`));
|
|
@@ -88223,11 +88887,11 @@ function fallbackHint2(route) {
|
|
|
88223
88887
|
return null;
|
|
88224
88888
|
}
|
|
88225
88889
|
function createTitanSwapCommand() {
|
|
88226
|
-
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) => {
|
|
88227
88891
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
88228
88892
|
const format = globalOptions.output;
|
|
88229
88893
|
const startTime = Date.now();
|
|
88230
|
-
const mode =
|
|
88894
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
88231
88895
|
const walletAddress = globalOptions.walletAddress;
|
|
88232
88896
|
if (!walletAddress) {
|
|
88233
88897
|
const e = missingWalletAddressError();
|
|
@@ -88293,12 +88957,35 @@ Error: ${msg}`));
|
|
|
88293
88957
|
console.log(table.toString());
|
|
88294
88958
|
const hint = fallbackHint2(getLastRoute2());
|
|
88295
88959
|
if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
|
|
88296
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
88960
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
88297
88961
|
}
|
|
88298
88962
|
return;
|
|
88299
88963
|
}
|
|
88300
|
-
|
|
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
|
+
}
|
|
88301
88984
|
} catch (e) {
|
|
88985
|
+
if (e instanceof ByrealError) {
|
|
88986
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
88987
|
+
process.exit(1);
|
|
88988
|
+
}
|
|
88302
88989
|
const message = e.message || "Titan swap failed";
|
|
88303
88990
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
88304
88991
|
Error: ${message}`));
|
|
@@ -88473,11 +89160,11 @@ function fallbackHint3(route) {
|
|
|
88473
89160
|
return null;
|
|
88474
89161
|
}
|
|
88475
89162
|
function createDFlowSwapCommand() {
|
|
88476
|
-
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) => {
|
|
88477
89164
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
88478
89165
|
const format = globalOptions.output;
|
|
88479
89166
|
const startTime = Date.now();
|
|
88480
|
-
const mode =
|
|
89167
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
88481
89168
|
const walletAddress = globalOptions.walletAddress;
|
|
88482
89169
|
if (!walletAddress) {
|
|
88483
89170
|
const e = missingWalletAddressError();
|
|
@@ -88543,12 +89230,35 @@ Error: ${msg}`));
|
|
|
88543
89230
|
console.log(table.toString());
|
|
88544
89231
|
const hint = fallbackHint3(getLastRoute3());
|
|
88545
89232
|
if (hint) console.error(source_default.gray(`[byreal] ${hint}`));
|
|
88546
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
89233
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
88547
89234
|
}
|
|
88548
89235
|
return;
|
|
88549
89236
|
}
|
|
88550
|
-
|
|
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
|
+
}
|
|
88551
89257
|
} catch (e) {
|
|
89258
|
+
if (e instanceof ByrealError) {
|
|
89259
|
+
format === "json" ? outputErrorJson(e.toJSON()) : outputErrorTable(e.toJSON());
|
|
89260
|
+
process.exit(1);
|
|
89261
|
+
}
|
|
88552
89262
|
const message = e.message || "DFlow swap failed";
|
|
88553
89263
|
format === "json" ? outputErrorJson({ code: "API_ERROR", type: "NETWORK", message, retryable: true }) : console.error(source_default.red(`
|
|
88554
89264
|
Error: ${message}`));
|
|
@@ -89316,21 +90026,38 @@ async function resolveUiAmounts(quote) {
|
|
|
89316
90026
|
uiOutAmount: rawToUi(quote.outAmount, outputDecimals)
|
|
89317
90027
|
};
|
|
89318
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
|
+
}
|
|
89319
90047
|
function createSwapExecuteCommand() {
|
|
89320
|
-
return new Command("execute").description("Preview or
|
|
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) => {
|
|
89321
90049
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
89322
90050
|
const format = globalOptions.output;
|
|
89323
90051
|
const startTime = Date.now();
|
|
89324
|
-
|
|
90052
|
+
let mode;
|
|
90053
|
+
try {
|
|
90054
|
+
mode = resolveExecutionMode(options);
|
|
90055
|
+
} catch (e) {
|
|
90056
|
+
emitError(format, e);
|
|
90057
|
+
}
|
|
89325
90058
|
const userPublicKey = globalOptions.walletAddress;
|
|
89326
90059
|
if (!userPublicKey) {
|
|
89327
|
-
|
|
89328
|
-
if (format === "json") {
|
|
89329
|
-
outputErrorJson(err2.toJSON());
|
|
89330
|
-
} else {
|
|
89331
|
-
outputErrorTable(err2.toJSON());
|
|
89332
|
-
}
|
|
89333
|
-
process.exit(1);
|
|
90060
|
+
emitError(format, missingWalletAddressError());
|
|
89334
90061
|
}
|
|
89335
90062
|
try {
|
|
89336
90063
|
new import_web3124.PublicKey(userPublicKey);
|
|
@@ -89361,12 +90088,12 @@ Error: Invalid wallet address: ${userPublicKey}`));
|
|
|
89361
90088
|
userPublicKey
|
|
89362
90089
|
});
|
|
89363
90090
|
if (!quoteResult.ok) {
|
|
89364
|
-
|
|
89365
|
-
|
|
89366
|
-
|
|
89367
|
-
|
|
89368
|
-
|
|
89369
|
-
|
|
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
|
+
}));
|
|
89370
90097
|
}
|
|
89371
90098
|
const quote = quoteResult.value;
|
|
89372
90099
|
const { uiInAmount, uiOutAmount } = await resolveUiAmounts(quote);
|
|
@@ -89389,7 +90116,7 @@ Error: Invalid wallet address: ${userPublicKey}`));
|
|
|
89389
90116
|
outputJson({ mode: "dry-run", ...quote, uiInAmount, uiOutAmount, inAmountUsd, outAmountUsd }, startTime);
|
|
89390
90117
|
} else {
|
|
89391
90118
|
outputSwapQuoteTable(quote, uiInAmount, uiOutAmount);
|
|
89392
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
90119
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
89393
90120
|
}
|
|
89394
90121
|
return;
|
|
89395
90122
|
}
|
|
@@ -89403,16 +90130,30 @@ Error: ${errMsg}`));
|
|
|
89403
90130
|
}
|
|
89404
90131
|
process.exit(1);
|
|
89405
90132
|
}
|
|
89406
|
-
|
|
89407
|
-
|
|
89408
|
-
|
|
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
|
+
}
|
|
89409
90143
|
if (format === "json") {
|
|
89410
|
-
|
|
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
|
+
);
|
|
89411
90152
|
} else {
|
|
89412
|
-
|
|
89413
|
-
Error: ${message}`));
|
|
90153
|
+
outputTransactionResult(broadcast.value.signature);
|
|
89414
90154
|
}
|
|
89415
|
-
|
|
90155
|
+
} catch (e) {
|
|
90156
|
+
emitError(format, e);
|
|
89416
90157
|
}
|
|
89417
90158
|
});
|
|
89418
90159
|
}
|
|
@@ -89628,11 +90369,11 @@ function createPositionsOpenCommand() {
|
|
|
89628
90369
|
).option(
|
|
89629
90370
|
"--amount-usd <usd>",
|
|
89630
90371
|
"Investment amount in USD (auto-calculates token split, mutually exclusive with --amount)"
|
|
89631
|
-
).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) => {
|
|
89632
90373
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
89633
90374
|
const format = globalOptions.output;
|
|
89634
90375
|
const startTime = Date.now();
|
|
89635
|
-
const mode =
|
|
90376
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
89636
90377
|
const walletAddress = globalOptions.walletAddress;
|
|
89637
90378
|
if (!walletAddress) {
|
|
89638
90379
|
const err2 = missingWalletAddressError();
|
|
@@ -89876,7 +90617,7 @@ function createPositionsOpenCommand() {
|
|
|
89876
90617
|
} else {
|
|
89877
90618
|
console.log(source_default.green("\n Balance check: sufficient"));
|
|
89878
90619
|
console.log(
|
|
89879
|
-
source_default.yellow("\n Remove --dry-run to
|
|
90620
|
+
source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
|
|
89880
90621
|
);
|
|
89881
90622
|
}
|
|
89882
90623
|
}
|
|
@@ -89892,7 +90633,29 @@ function createPositionsOpenCommand() {
|
|
|
89892
90633
|
otherAmountMax
|
|
89893
90634
|
});
|
|
89894
90635
|
const base64 = serializeTransaction(result.transaction);
|
|
89895
|
-
|
|
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
|
+
}
|
|
89896
90659
|
} catch (e) {
|
|
89897
90660
|
const message = e.message || "Unknown SDK error";
|
|
89898
90661
|
if (format === "json") {
|
|
@@ -89923,11 +90686,11 @@ function createPositionsIncreaseCommand() {
|
|
|
89923
90686
|
).option(
|
|
89924
90687
|
"--amount-usd <usd>",
|
|
89925
90688
|
"Investment amount in USD (auto-calculates token split, mutually exclusive with --amount)"
|
|
89926
|
-
).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) => {
|
|
89927
90690
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
89928
90691
|
const format = globalOptions.output;
|
|
89929
90692
|
const startTime = Date.now();
|
|
89930
|
-
const mode =
|
|
90693
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
89931
90694
|
const walletAddress = globalOptions.walletAddress;
|
|
89932
90695
|
if (!walletAddress) {
|
|
89933
90696
|
const err2 = missingWalletAddressError();
|
|
@@ -90174,7 +90937,7 @@ Error: ${errMsg}`));
|
|
|
90174
90937
|
} else {
|
|
90175
90938
|
console.log(source_default.green("\n Balance check: sufficient"));
|
|
90176
90939
|
console.log(
|
|
90177
|
-
source_default.yellow("\n Remove --dry-run to
|
|
90940
|
+
source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
|
|
90178
90941
|
);
|
|
90179
90942
|
}
|
|
90180
90943
|
}
|
|
@@ -90188,7 +90951,29 @@ Error: ${errMsg}`));
|
|
|
90188
90951
|
otherAmountMax
|
|
90189
90952
|
});
|
|
90190
90953
|
const base64 = serializeTransaction(result.transaction);
|
|
90191
|
-
|
|
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
|
+
}
|
|
90192
90977
|
} catch (e) {
|
|
90193
90978
|
const message = e.message || "Unknown SDK error";
|
|
90194
90979
|
if (format === "json") {
|
|
@@ -90213,11 +90998,11 @@ function createPositionsDecreaseCommand() {
|
|
|
90213
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(
|
|
90214
90999
|
"--amount-usd <usd>",
|
|
90215
91000
|
"USD amount of liquidity to remove (mutually exclusive with --percentage)"
|
|
90216
|
-
).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) => {
|
|
90217
91002
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
90218
91003
|
const format = globalOptions.output;
|
|
90219
91004
|
const startTime = Date.now();
|
|
90220
|
-
const mode =
|
|
91005
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
90221
91006
|
const hasPercentage = options.percentage !== void 0;
|
|
90222
91007
|
const hasAmountUsd = options.amountUsd !== void 0;
|
|
90223
91008
|
if (hasPercentage && hasAmountUsd) {
|
|
@@ -90403,7 +91188,7 @@ Error: ${errMsg}`));
|
|
|
90403
91188
|
} else {
|
|
90404
91189
|
outputPositionDecreasePreview(previewData);
|
|
90405
91190
|
console.log(
|
|
90406
|
-
source_default.yellow("\n Remove --dry-run to
|
|
91191
|
+
source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
|
|
90407
91192
|
);
|
|
90408
91193
|
}
|
|
90409
91194
|
return;
|
|
@@ -90425,7 +91210,29 @@ Error: ${errMsg}`));
|
|
|
90425
91210
|
});
|
|
90426
91211
|
}
|
|
90427
91212
|
const base64 = serializeTransaction(result.transaction);
|
|
90428
|
-
|
|
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
|
+
}
|
|
90429
91236
|
} catch (e) {
|
|
90430
91237
|
const message = e.message || "Unknown SDK error";
|
|
90431
91238
|
if (format === "json") {
|
|
@@ -90447,11 +91254,11 @@ SDK Error: ${message}`));
|
|
|
90447
91254
|
});
|
|
90448
91255
|
}
|
|
90449
91256
|
function createPositionsCloseCommand() {
|
|
90450
|
-
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) => {
|
|
90451
91258
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
90452
91259
|
const format = globalOptions.output;
|
|
90453
91260
|
const startTime = Date.now();
|
|
90454
|
-
const mode =
|
|
91261
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
90455
91262
|
const walletAddress = globalOptions.walletAddress;
|
|
90456
91263
|
if (!walletAddress) {
|
|
90457
91264
|
const err2 = missingWalletAddressError();
|
|
@@ -90525,7 +91332,7 @@ Error: ${errMsg}`));
|
|
|
90525
91332
|
} else {
|
|
90526
91333
|
outputPositionClosePreview(previewData);
|
|
90527
91334
|
console.log(
|
|
90528
|
-
source_default.yellow("\n Remove --dry-run to
|
|
91335
|
+
source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
|
|
90529
91336
|
);
|
|
90530
91337
|
}
|
|
90531
91338
|
return;
|
|
@@ -90538,7 +91345,29 @@ Error: ${errMsg}`));
|
|
|
90538
91345
|
slippage
|
|
90539
91346
|
});
|
|
90540
91347
|
const base64 = serializeTransaction(result.transaction);
|
|
90541
|
-
|
|
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
|
+
}
|
|
90542
91371
|
} catch (e) {
|
|
90543
91372
|
const message = e.message || "Unknown SDK error";
|
|
90544
91373
|
if (format === "json") {
|
|
@@ -90563,11 +91392,11 @@ function createPositionsClaimCommand() {
|
|
|
90563
91392
|
return new Command("claim").description("Claim accumulated fees from positions").requiredOption(
|
|
90564
91393
|
"--nft-mints <addresses>",
|
|
90565
91394
|
"Comma-separated NFT mint addresses (from positions list)"
|
|
90566
|
-
).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) => {
|
|
90567
91396
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
90568
91397
|
const format = globalOptions.output;
|
|
90569
91398
|
const startTime = Date.now();
|
|
90570
|
-
const mode =
|
|
91399
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
90571
91400
|
const walletAddress = globalOptions.walletAddress;
|
|
90572
91401
|
if (!walletAddress) {
|
|
90573
91402
|
const err2 = missingWalletAddressError();
|
|
@@ -90671,20 +91500,53 @@ Error: ${errMsg}`));
|
|
|
90671
91500
|
outputJson({ mode: "dry-run", entries: enrichedEntries }, startTime);
|
|
90672
91501
|
} else {
|
|
90673
91502
|
outputPositionClaimPreview(enrichedEntries);
|
|
90674
|
-
console.log(source_default.yellow("\n Remove --dry-run to
|
|
91503
|
+
console.log(source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."));
|
|
90675
91504
|
}
|
|
90676
91505
|
return;
|
|
90677
91506
|
}
|
|
90678
91507
|
const unsignedTransactions = entries.map((entry) => entry.txPayload);
|
|
90679
|
-
|
|
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
|
+
}
|
|
90680
91542
|
});
|
|
90681
91543
|
}
|
|
90682
91544
|
function createPositionsClaimRewardsCommand() {
|
|
90683
|
-
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) => {
|
|
90684
91546
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
90685
91547
|
const format = globalOptions.output;
|
|
90686
91548
|
const startTime = Date.now();
|
|
90687
|
-
const mode =
|
|
91549
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
90688
91550
|
const walletAddress = globalOptions.walletAddress;
|
|
90689
91551
|
if (!walletAddress) {
|
|
90690
91552
|
const err2 = missingWalletAddressError();
|
|
@@ -90744,7 +91606,7 @@ function createPositionsClaimRewardsCommand() {
|
|
|
90744
91606
|
console.log(source_default.gray("\n No unclaimed incentive rewards.\n"));
|
|
90745
91607
|
} else {
|
|
90746
91608
|
console.log(
|
|
90747
|
-
source_default.yellow("\n Remove --dry-run to
|
|
91609
|
+
source_default.yellow("\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy.")
|
|
90748
91610
|
);
|
|
90749
91611
|
}
|
|
90750
91612
|
}
|
|
@@ -90762,6 +91624,7 @@ function createPositionsClaimRewardsCommand() {
|
|
|
90762
91624
|
return;
|
|
90763
91625
|
}
|
|
90764
91626
|
const positionAddresses = [...new Set(allRewards.map((r) => r.positionAddress))];
|
|
91627
|
+
if (mode === "execute") requirePrivyContext(walletAddress);
|
|
90765
91628
|
const encodeResult = await api.encodeReward({
|
|
90766
91629
|
walletAddress,
|
|
90767
91630
|
positionAddresses,
|
|
@@ -90787,14 +91650,52 @@ function createPositionsClaimRewardsCommand() {
|
|
|
90787
91650
|
}
|
|
90788
91651
|
return;
|
|
90789
91652
|
}
|
|
90790
|
-
|
|
90791
|
-
|
|
90792
|
-
|
|
90793
|
-
|
|
90794
|
-
|
|
90795
|
-
|
|
90796
|
-
|
|
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
|
+
}
|
|
90797
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
|
+
}
|
|
90798
91699
|
const message = e.message || "Unknown error";
|
|
90799
91700
|
if (format === "json") {
|
|
90800
91701
|
outputErrorJson({ code: "SDK_ERROR", type: "SYSTEM", message, retryable: false });
|
|
@@ -90810,11 +91711,11 @@ Error: ${message}`));
|
|
|
90810
91711
|
});
|
|
90811
91712
|
}
|
|
90812
91713
|
function createPositionsClaimBonusCommand() {
|
|
90813
|
-
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) => {
|
|
90814
91715
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
90815
91716
|
const format = globalOptions.output;
|
|
90816
91717
|
const startTime = Date.now();
|
|
90817
|
-
const mode =
|
|
91718
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
90818
91719
|
const walletAddress = globalOptions.walletAddress;
|
|
90819
91720
|
if (!walletAddress) {
|
|
90820
91721
|
const err2 = missingWalletAddressError();
|
|
@@ -90865,7 +91766,7 @@ function createPositionsClaimBonusCommand() {
|
|
|
90865
91766
|
outputBonusPreview(overview, epochs);
|
|
90866
91767
|
if (canClaim) {
|
|
90867
91768
|
console.log(
|
|
90868
|
-
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.
|
|
90869
91770
|
`)
|
|
90870
91771
|
);
|
|
90871
91772
|
} else {
|
|
@@ -90885,6 +91786,7 @@ function createPositionsClaimBonusCommand() {
|
|
|
90885
91786
|
}
|
|
90886
91787
|
return;
|
|
90887
91788
|
}
|
|
91789
|
+
if (mode === "execute") requirePrivyContext(walletAddress);
|
|
90888
91790
|
const encodeResult = await api.encodeReward({
|
|
90889
91791
|
walletAddress,
|
|
90890
91792
|
positionAddresses: [],
|
|
@@ -90910,14 +91812,52 @@ function createPositionsClaimBonusCommand() {
|
|
|
90910
91812
|
}
|
|
90911
91813
|
return;
|
|
90912
91814
|
}
|
|
90913
|
-
|
|
90914
|
-
|
|
90915
|
-
|
|
90916
|
-
|
|
90917
|
-
|
|
90918
|
-
|
|
90919
|
-
|
|
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
|
+
}
|
|
90920
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
|
+
}
|
|
90921
91861
|
const message = e.message || "Unknown error";
|
|
90922
91862
|
if (format === "json") {
|
|
90923
91863
|
outputErrorJson({ code: "SDK_ERROR", type: "SYSTEM", message, retryable: false });
|
|
@@ -91181,11 +92121,11 @@ function createTopPositionsCommand() {
|
|
|
91181
92121
|
function createCopyPositionCommand() {
|
|
91182
92122
|
return new Command("copy").description(
|
|
91183
92123
|
"Copy an existing position with referral bonus"
|
|
91184
|
-
).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) => {
|
|
91185
92125
|
const globalOptions = cmdObj.optsWithGlobals();
|
|
91186
92126
|
const format = globalOptions.output;
|
|
91187
92127
|
const startTime = Date.now();
|
|
91188
|
-
const mode =
|
|
92128
|
+
const mode = safeResolveExecutionMode(options, format);
|
|
91189
92129
|
const walletAddress = globalOptions.walletAddress;
|
|
91190
92130
|
if (!walletAddress) {
|
|
91191
92131
|
const err2 = missingWalletAddressError();
|
|
@@ -91368,7 +92308,7 @@ Error: ${errMsg}`));
|
|
|
91368
92308
|
console.log(source_default.green("\n Balance check: sufficient"));
|
|
91369
92309
|
console.log(
|
|
91370
92310
|
source_default.yellow(
|
|
91371
|
-
"\n Remove --dry-run to
|
|
92311
|
+
"\n Remove --dry-run to emit an unsigned transaction; add --execute to sign + broadcast via Privy."
|
|
91372
92312
|
)
|
|
91373
92313
|
);
|
|
91374
92314
|
}
|
|
@@ -91386,7 +92326,29 @@ Error: ${errMsg}`));
|
|
|
91386
92326
|
refererPosition: options.position
|
|
91387
92327
|
});
|
|
91388
92328
|
const base64 = serializeTransaction(result.transaction);
|
|
91389
|
-
|
|
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
|
+
}
|
|
91390
92352
|
} catch (e) {
|
|
91391
92353
|
const message = e.message || "Unknown SDK error";
|
|
91392
92354
|
if (format === "json") {
|