@glamsystems/glam-cli 1.0.10 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/main.js +380 -100
  2. package/package.json +2 -2
package/main.js CHANGED
@@ -2345,6 +2345,7 @@ async function fetchAddressLookupTableAccounts(connection, pubkeys) {
2345
2345
  Object.defineProperty(exports, "__esModule", ({ value: true }));
2346
2346
  exports.getProtocolNamesFromBitmask = getProtocolNamesFromBitmask;
2347
2347
  exports.getPermissionNamesFromBitmask = getPermissionNamesFromBitmask;
2348
+ exports.comparePublicKeyArrays = comparePublicKeyArrays;
2348
2349
  exports.compareIntegrationAcls = compareIntegrationAcls;
2349
2350
  exports.compareDelegateAcls = compareDelegateAcls;
2350
2351
  const bitmask_1 = __webpack_require__(38);
@@ -2366,6 +2367,17 @@ function getPermissionNamesFromBitmask(integrationProgram, protocolBitflag, perm
2366
2367
  const { permissions } = (0, bitmask_1.parseProtocolPermissionsBitmask)(integrationProgram, protocolBitflag, permissionsBitmask);
2367
2368
  return permissions.map((p) => p.name);
2368
2369
  }
2370
+ /**
2371
+ * Compare current and staged PublicKey arrays and return added/removed keys
2372
+ */
2373
+ function comparePublicKeyArrays(current, staged) {
2374
+ const currentSet = new pkset_1.PkSet(current || []);
2375
+ const stagedSet = new pkset_1.PkSet(staged);
2376
+ return {
2377
+ added: [...stagedSet].filter((pk) => !currentSet.has(pk)),
2378
+ removed: [...currentSet].filter((pk) => !stagedSet.has(pk)),
2379
+ };
2380
+ }
2369
2381
  /**
2370
2382
  * Compare current and staged integrationAcls and return the differences
2371
2383
  */
@@ -15151,6 +15163,9 @@ exports.validateInvestorAction = validateInvestorAction;
15151
15163
  exports.validateBooleanInput = validateBooleanInput;
15152
15164
  exports.validateDriftMarketType = validateDriftMarketType;
15153
15165
  exports.executeTxWithErrorHandling = executeTxWithErrorHandling;
15166
+ exports.levenshtein = levenshtein;
15167
+ exports.resolveProtocolName = resolveProtocolName;
15168
+ exports.resolvePermissionNames = resolvePermissionNames;
15154
15169
  const tslib_1 = __webpack_require__(2);
15155
15170
  const anchor_1 = __webpack_require__(4);
15156
15171
  const glam_sdk_1 = __webpack_require__(1);
@@ -15454,6 +15469,127 @@ async function executeTxWithErrorHandling(txFn, confirmOptions, successMessage)
15454
15469
  process.exit(1);
15455
15470
  }
15456
15471
  }
15472
+ function levenshtein(a, b) {
15473
+ const m = a.length, n = b.length;
15474
+ const dp = Array.from({ length: n + 1 }, (_, i) => i);
15475
+ for (let i = 1; i <= m; i++) {
15476
+ let prev = dp[0];
15477
+ dp[0] = i;
15478
+ for (let j = 1; j <= n; j++) {
15479
+ const tmp = dp[j];
15480
+ dp[j] =
15481
+ a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
15482
+ prev = tmp;
15483
+ }
15484
+ }
15485
+ return dp[n];
15486
+ }
15487
+ /**
15488
+ * Resolve a single protocol name with fuzzy matching:
15489
+ * 1. Exact match
15490
+ * 2. Case-insensitive match
15491
+ * 3. Levenshtein suggestion (distance <= 3)
15492
+ *
15493
+ * Returns the canonical protocol name or exits with an error.
15494
+ */
15495
+ function resolveProtocolName(name) {
15496
+ const lookup = (0, glam_sdk_1.getProgramAndBitflagByProtocolName)();
15497
+ const validNames = Object.keys(lookup);
15498
+ // 1. Exact match
15499
+ if (lookup[name]) {
15500
+ return name;
15501
+ }
15502
+ // 2. Case-insensitive match
15503
+ const ciIndex = new Map();
15504
+ for (const valid of validNames) {
15505
+ ciIndex.set(valid.toLowerCase(), valid);
15506
+ }
15507
+ const ciMatch = ciIndex.get(name.toLowerCase());
15508
+ if (ciMatch) {
15509
+ console.log(`Note: using '${ciMatch}' for '${name}'`);
15510
+ return ciMatch;
15511
+ }
15512
+ // 3. Levenshtein suggestion
15513
+ let bestName = "";
15514
+ let bestDist = Infinity;
15515
+ const nameLower = name.toLowerCase();
15516
+ for (const valid of validNames) {
15517
+ const dist = levenshtein(nameLower, valid.toLowerCase());
15518
+ if (dist < bestDist) {
15519
+ bestDist = dist;
15520
+ bestName = valid;
15521
+ }
15522
+ }
15523
+ const suggestion = bestDist <= 3 ? ` Did you mean '${bestName}' instead of '${name}'?` : "";
15524
+ console.error(`Unknown protocol name: ${name}`);
15525
+ if (suggestion)
15526
+ console.error(suggestion);
15527
+ console.error(`Valid protocol names: ${validNames.join(", ")}`);
15528
+ process.exit(1);
15529
+ }
15530
+ /**
15531
+ * Resolve permission names for a given (already-resolved) protocol with fuzzy matching.
15532
+ * Returns an array of canonical permission names or exits with an error.
15533
+ */
15534
+ function resolvePermissionNames(protocolName, inputNames) {
15535
+ const protocolConfig = (0, glam_sdk_1.getProgramAndBitflagByProtocolName)()[protocolName];
15536
+ if (!protocolConfig) {
15537
+ console.error(`Unknown protocol name: ${protocolName}`);
15538
+ process.exit(1);
15539
+ }
15540
+ const [programIdStr, bitflagStr] = protocolConfig;
15541
+ const protocolPermissions = (0, glam_sdk_1.getProtocolsAndPermissions)()[programIdStr]?.[bitflagStr];
15542
+ if (!protocolPermissions) {
15543
+ console.error(`Protocol mapping not found for protocol name ${protocolName}`);
15544
+ process.exit(1);
15545
+ }
15546
+ const validNames = Object.values(protocolPermissions.permissions);
15547
+ const ciIndex = new Map();
15548
+ for (const valid of validNames) {
15549
+ ciIndex.set(valid.toLowerCase(), valid);
15550
+ }
15551
+ const resolved = [];
15552
+ const unknown = [];
15553
+ const suggestions = [];
15554
+ for (const name of inputNames) {
15555
+ // 1. Exact match
15556
+ if (validNames.includes(name)) {
15557
+ resolved.push(name);
15558
+ continue;
15559
+ }
15560
+ // 2. Case-insensitive match
15561
+ const ciMatch = ciIndex.get(name.toLowerCase());
15562
+ if (ciMatch) {
15563
+ console.log(`Note: using '${ciMatch}' for '${name}'`);
15564
+ resolved.push(ciMatch);
15565
+ continue;
15566
+ }
15567
+ // 3. Levenshtein suggestion
15568
+ let bestName = "";
15569
+ let bestDist = Infinity;
15570
+ const nameLower = name.toLowerCase();
15571
+ for (const valid of validNames) {
15572
+ const dist = levenshtein(nameLower, valid.toLowerCase());
15573
+ if (dist < bestDist) {
15574
+ bestDist = dist;
15575
+ bestName = valid;
15576
+ }
15577
+ }
15578
+ if (bestDist <= 3) {
15579
+ suggestions.push(` Did you mean '${bestName}' instead of '${name}'?`);
15580
+ }
15581
+ unknown.push(name);
15582
+ }
15583
+ if (unknown.length) {
15584
+ console.error(`Unknown permission name(s) for ${protocolName}: ${unknown.join(", ")}`);
15585
+ for (const s of suggestions) {
15586
+ console.error(s);
15587
+ }
15588
+ console.error(`Valid permissions for ${protocolName}: ${validNames.join(", ")}`);
15589
+ process.exit(1);
15590
+ }
15591
+ return resolved;
15592
+ }
15457
15593
 
15458
15594
 
15459
15595
  /***/ }),
@@ -48054,6 +48190,21 @@ const validateIntegrationProgram = (input) => {
48054
48190
  }
48055
48191
  return pubkey;
48056
48192
  };
48193
+ function resolveProtocolNames(names) {
48194
+ const lookup = (0, glam_sdk_1.getProgramAndBitflagByProtocolName)();
48195
+ const groups = {};
48196
+ for (const name of names) {
48197
+ const resolved = (0, utils_1.resolveProtocolName)(name);
48198
+ const [programIdStr, bitflagStr] = lookup[resolved];
48199
+ if (programIdStr === (0, glam_sdk_1.getGlamMintProgramId)().toBase58()) {
48200
+ console.error("Mint integration is not allowed");
48201
+ process.exit(1);
48202
+ }
48203
+ const bitflag = parseInt(bitflagStr, 2);
48204
+ groups[programIdStr] = (groups[programIdStr] || 0) | bitflag;
48205
+ }
48206
+ return groups;
48207
+ }
48057
48208
  function installIntegrationCommands(integration, context) {
48058
48209
  integration
48059
48210
  .command("list")
@@ -48073,27 +48224,7 @@ function installIntegrationCommands(integration, context) {
48073
48224
  .argument("<protocols...>", "Protocol names (e.g., SplToken, JupiterSwap, DriftProtocol)")
48074
48225
  .option("-y, --yes", "Skip confirmation")
48075
48226
  .action(async (protocols, { yes }) => {
48076
- const groups = {}; // Program ID -> Protocols Bitmask
48077
- const unknown = [];
48078
- const PROGRAM_AND_BITFLAG_BY_PROTOCOL_NAME = (0, glam_sdk_1.getProgramAndBitflagByProtocolName)();
48079
- for (const name of protocols) {
48080
- const entry = PROGRAM_AND_BITFLAG_BY_PROTOCOL_NAME[name];
48081
- if (!entry) {
48082
- unknown.push(name);
48083
- continue;
48084
- }
48085
- const [programIdStr, bitflagStr] = entry;
48086
- if (programIdStr === (0, glam_sdk_1.getGlamMintProgramId)().toBase58()) {
48087
- console.error("Mint integration is not allowed");
48088
- process.exit(1);
48089
- }
48090
- const bitflag = parseInt(bitflagStr, 2);
48091
- groups[programIdStr] = (groups[programIdStr] || 0) | bitflag;
48092
- }
48093
- if (unknown.length) {
48094
- console.error(`Unknown protocol name(s): ${unknown.join(", ")}`);
48095
- process.exit(1);
48096
- }
48227
+ const groups = resolveProtocolNames(protocols);
48097
48228
  const details = Object.entries(groups).map(([pid, mask]) => {
48098
48229
  const { protocols } = (0, glam_sdk_1.parseProtocolsBitmask)(new web3_js_1.PublicKey(pid), mask);
48099
48230
  const names = protocols.map((p) => p.name).join(", ");
@@ -48117,27 +48248,7 @@ function installIntegrationCommands(integration, context) {
48117
48248
  .argument("<protocols...>", "Protocol names (e.g., SplToken, JupiterSwap, DriftProtocol)")
48118
48249
  .option("-y, --yes", "Skip confirmation")
48119
48250
  .action(async (protocols, { yes }) => {
48120
- const groups = {};
48121
- const unknown = [];
48122
- const PROGRAM_AND_BITFLAG_BY_PROTOCOL_NAME = (0, glam_sdk_1.getProgramAndBitflagByProtocolName)();
48123
- for (const name of protocols) {
48124
- const entry = PROGRAM_AND_BITFLAG_BY_PROTOCOL_NAME[name];
48125
- if (!entry) {
48126
- unknown.push(name);
48127
- continue;
48128
- }
48129
- const [programIdStr, bitflagStr] = entry;
48130
- if (programIdStr === (0, glam_sdk_1.getGlamMintProgramId)().toBase58()) {
48131
- console.error("Mint integration is not allowed");
48132
- process.exit(1);
48133
- }
48134
- const mask = parseInt(bitflagStr, 2);
48135
- groups[programIdStr] = (groups[programIdStr] || 0) | mask;
48136
- }
48137
- if (unknown.length) {
48138
- console.error(`Unknown protocol name(s): ${unknown.join(", ")}`);
48139
- process.exit(1);
48140
- }
48251
+ const groups = resolveProtocolNames(protocols);
48141
48252
  const details = Object.entries(groups).map(([pid, mask]) => {
48142
48253
  const { protocols } = (0, glam_sdk_1.parseProtocolsBitmask)(new web3_js_1.PublicKey(pid), mask);
48143
48254
  const names = protocols.map((p) => p.name).join(", ");
@@ -48218,17 +48329,13 @@ function installDelegateCommands(delegate, context) {
48218
48329
  .option("-y, --yes", "Skip confirmation prompt")
48219
48330
  .description("Grant delegate permissions for a single protocol")
48220
48331
  .action(async (delegate, permissions, { protocol, yes }) => {
48221
- try {
48222
- const { integrationProgram, protocolBitflag, permissionsBitmask } = (0, glam_sdk_1.parsePermissionNames)({
48223
- protocolName: protocol,
48224
- permissionNames: permissions,
48225
- });
48226
- await handleDelegatePermissions("grant", delegate, integrationProgram, protocolBitflag, protocol, permissionsBitmask, permissions, context, yes);
48227
- }
48228
- catch (e) {
48229
- console.error(e);
48230
- process.exit(1);
48231
- }
48332
+ const resolvedProtocol = (0, utils_1.resolveProtocolName)(protocol);
48333
+ const resolvedPermissions = (0, utils_1.resolvePermissionNames)(resolvedProtocol, permissions);
48334
+ const { integrationProgram, protocolBitflag, permissionsBitmask } = (0, glam_sdk_1.parsePermissionNames)({
48335
+ protocolName: resolvedProtocol,
48336
+ permissionNames: resolvedPermissions,
48337
+ });
48338
+ await handleDelegatePermissions("grant", delegate, integrationProgram, protocolBitflag, resolvedProtocol, permissionsBitmask, resolvedPermissions, context, yes);
48232
48339
  });
48233
48340
  delegate
48234
48341
  .command("revoke")
@@ -48238,17 +48345,13 @@ function installDelegateCommands(delegate, context) {
48238
48345
  .option("-y, --yes", "Skip confirmation prompt")
48239
48346
  .description("Revoke delegate permissions for a single protocol by name")
48240
48347
  .action(async (delegate, permissions, { protocol, yes }) => {
48241
- try {
48242
- const { integrationProgram, protocolBitflag, permissionsBitmask } = (0, glam_sdk_1.parsePermissionNames)({
48243
- protocolName: protocol,
48244
- permissionNames: permissions,
48245
- });
48246
- await handleDelegatePermissions("revoke", delegate, integrationProgram, protocolBitflag, protocol, permissionsBitmask, permissions, context, yes);
48247
- }
48248
- catch (e) {
48249
- console.error(e);
48250
- process.exit(1);
48251
- }
48348
+ const resolvedProtocol = (0, utils_1.resolveProtocolName)(protocol);
48349
+ const resolvedPermissions = (0, utils_1.resolvePermissionNames)(resolvedProtocol, permissions);
48350
+ const { integrationProgram, protocolBitflag, permissionsBitmask } = (0, glam_sdk_1.parsePermissionNames)({
48351
+ protocolName: resolvedProtocol,
48352
+ permissionNames: resolvedPermissions,
48353
+ });
48354
+ await handleDelegatePermissions("revoke", delegate, integrationProgram, protocolBitflag, resolvedProtocol, permissionsBitmask, resolvedPermissions, context, yes);
48252
48355
  });
48253
48356
  delegate
48254
48357
  .command("revoke-all")
@@ -48788,18 +48891,33 @@ function installVaultCommands(program, context) {
48788
48891
  message,
48789
48892
  }, (txSig) => `Vault ownership transferred: ${txSig}`);
48790
48893
  });
48791
- program
48792
- .command("set-enabled")
48793
- .argument("<enabled>", "New vault state", utils_1.validateBooleanInput)
48794
- .description("Enable or disable a GLAM vault")
48795
- .option("-y, --yes", "Skip confirmation prompt", false)
48796
- .action(async (enabled, options) => {
48894
+ const setEnabled = async (enabled, options) => {
48797
48895
  const stateAccount = await context.glamClient.fetchStateAccount();
48798
48896
  const name = (0, glam_sdk_1.charsToString)(stateAccount.name);
48799
48897
  await (0, utils_1.executeTxWithErrorHandling)(() => context.glamClient.access.emergencyAccessUpdate({ stateEnabled: enabled }, context.txOptions), {
48800
48898
  skip: options?.yes,
48801
48899
  message: `Confirm ${enabled ? "enabling" : "disabling"} vault: ${name}`,
48802
48900
  }, (txSig) => `GLAM vault ${name} ${enabled ? "enabled" : "disabled"}: ${txSig}`);
48901
+ };
48902
+ program
48903
+ .command("enable")
48904
+ .description("Enable a GLAM vault")
48905
+ .option("-y, --yes", "Skip confirmation prompt", false)
48906
+ .action(async (options) => setEnabled(true, options));
48907
+ program
48908
+ .command("disable")
48909
+ .description("Disable a GLAM vault")
48910
+ .option("-y, --yes", "Skip confirmation prompt", false)
48911
+ .action(async (options) => setEnabled(false, options));
48912
+ // Deprecated: use 'enable' or 'disable' instead
48913
+ program
48914
+ .command("set-enabled")
48915
+ .argument("<enabled>", "New vault state", utils_1.validateBooleanInput)
48916
+ .description("[deprecated] Use 'enable' or 'disable' instead")
48917
+ .option("-y, --yes", "Skip confirmation prompt", false)
48918
+ .action(async (enabled, options) => {
48919
+ console.warn("Warning: 'set-enabled' is deprecated, use 'enable' or 'disable' instead.");
48920
+ await setEnabled(enabled, options);
48803
48921
  });
48804
48922
  program
48805
48923
  .command("view")
@@ -48922,11 +49040,42 @@ function installVaultCommands(program, context) {
48922
49040
  }, (txSig) => `wSOL unwrapped: ${txSig}`);
48923
49041
  });
48924
49042
  program
48925
- .command("balances")
48926
- .description("Get balances")
48927
- .option("-a, --all", "Show all assets including token accounts with 0 balance")
48928
- .action(async (options) => {
48929
- const { all } = options;
49043
+ .command("close-token-accounts")
49044
+ .argument("[mints...]", "Mint address(es) of token accounts to close")
49045
+ .option("--empty", "Close all empty (zero-balance) token accounts", false)
49046
+ .option("-y, --yes", "Skip confirmation prompt", false)
49047
+ .description("Close vault token accounts")
49048
+ .action(async (mints, options) => {
49049
+ let tokenAccountPubkeys = [];
49050
+ if (options.empty) {
49051
+ const vault = context.glamClient.vaultPda;
49052
+ const { tokenAccounts } = await context.glamClient.getSolAndTokenBalances(vault);
49053
+ const emptyAccounts = tokenAccounts.filter((ta) => ta.uiAmount === 0);
49054
+ if (emptyAccounts.length === 0) {
49055
+ console.log("No empty token accounts to close.");
49056
+ return;
49057
+ }
49058
+ const emptyMints = emptyAccounts.map((ta) => ta.mint);
49059
+ const mintInfos = await (0, glam_sdk_1.fetchMintsAndTokenPrograms)(context.glamClient.connection, emptyMints);
49060
+ tokenAccountPubkeys = mintInfos.map(({ mint: { address }, tokenProgram }) => context.glamClient.getVaultAta(address, tokenProgram));
49061
+ }
49062
+ else if (mints.length > 0) {
49063
+ const mintPubkeys = mints.map((m) => (0, utils_1.validatePublicKey)(m));
49064
+ const mintInfos = await (0, glam_sdk_1.fetchMintsAndTokenPrograms)(context.glamClient.connection, mintPubkeys);
49065
+ tokenAccountPubkeys = mintInfos.map(({ mint: { address }, tokenProgram }) => context.glamClient.getVaultAta(address, tokenProgram));
49066
+ }
49067
+ else {
49068
+ console.error("Provide mint address(es) or use --empty to close all empty token accounts.");
49069
+ process.exit(1);
49070
+ }
49071
+ const count = tokenAccountPubkeys.length;
49072
+ await (0, utils_1.executeTxWithErrorHandling)(() => context.glamClient.vault.closeTokenAccounts(tokenAccountPubkeys, context.txOptions), {
49073
+ skip: options?.yes,
49074
+ message: `Confirm closing ${count} token account(s)`,
49075
+ }, (txSig) => `Closed ${count} token account(s): ${txSig}`);
49076
+ });
49077
+ const tokenBalances = async (options) => {
49078
+ const { all, json } = options;
48930
49079
  const vault = context.glamClient.vaultPda;
48931
49080
  const { uiAmount: solUiAmount, tokenAccounts } = await context.glamClient.getSolAndTokenBalances(vault);
48932
49081
  const mints = tokenAccounts.map((ta) => ta.mint.toBase58());
@@ -48935,33 +49084,59 @@ function installVaultCommands(program, context) {
48935
49084
  }
48936
49085
  const jupApi = context.glamClient.jupiterSwap.jupApi;
48937
49086
  const tokenList = await jupApi.fetchTokensList();
48938
- // Define column widths
49087
+ const solPrice = tokenList.getByMint(glam_sdk_1.WSOL)?.usdPrice || 0;
49088
+ const rows = [
49089
+ {
49090
+ token: "SOL",
49091
+ mint: "N/A",
49092
+ amount: solUiAmount,
49093
+ value: solPrice * solUiAmount,
49094
+ },
49095
+ ...tokenAccounts
49096
+ .filter((ta) => all || ta.uiAmount > 0)
49097
+ .map((ta) => {
49098
+ const mintStr = ta.mint.toBase58();
49099
+ const token = tokenList.getByMint(mintStr);
49100
+ const tokenSymbol = token?.symbol === "SOL" ? "wSOL" : token?.symbol || "Unknown";
49101
+ const value = (token?.usdPrice || 0) * ta.uiAmount;
49102
+ return {
49103
+ token: tokenSymbol,
49104
+ mint: mintStr,
49105
+ amount: ta.uiAmount,
49106
+ value,
49107
+ };
49108
+ }),
49109
+ ];
49110
+ if (json) {
49111
+ console.log(JSON.stringify(rows, null, 2));
49112
+ return;
49113
+ }
48939
49114
  const colWidths = [12, 45, 15, 20];
48940
49115
  const printRow = (items) => {
48941
49116
  console.log(items[0].padEnd(colWidths[0]), items[1].padEnd(colWidths[1]), items[2].padEnd(colWidths[2]), items[3].padEnd(colWidths[3]));
48942
49117
  };
48943
- printRow(["Token", "Mint", "Amount", "Value (USD)"]); // header row
48944
- printRow([
48945
- "SOL",
48946
- "N/A",
48947
- solUiAmount.toFixed(9).toString(),
48948
- ((tokenList.getByMint(glam_sdk_1.WSOL)?.usdPrice || 0) * solUiAmount).toFixed(6),
48949
- ]);
48950
- tokenAccounts.forEach((ta) => {
48951
- const { uiAmount, mint } = ta;
48952
- const mintStr = mint.toBase58();
48953
- if (all || uiAmount > 0) {
48954
- const token = tokenList.getByMint(mintStr);
48955
- const tokenSymbol = token?.symbol === "SOL" ? "wSOL" : token?.symbol || "Unknown";
48956
- const value = (token?.usdPrice || 0) * uiAmount;
48957
- printRow([
48958
- tokenSymbol,
48959
- mintStr,
48960
- uiAmount.toString(),
48961
- value ? value.toFixed(6) : "NaN",
48962
- ]);
48963
- }
48964
- });
49118
+ printRow(["Token", "Mint", "Amount", "Value (USD)"]);
49119
+ rows.forEach((r) => printRow([
49120
+ r.token,
49121
+ r.mint,
49122
+ r.token === "SOL" ? r.amount.toFixed(9) : r.amount.toString(),
49123
+ r.value ? r.value.toFixed(6) : "NaN",
49124
+ ]));
49125
+ };
49126
+ program
49127
+ .command("token-balances")
49128
+ .description("Get token balances")
49129
+ .option("-a, --all", "Show all assets including token accounts with 0 balance")
49130
+ .option("-j, --json", "Output in JSON format", false)
49131
+ .action(tokenBalances);
49132
+ // Deprecated: use 'token-balances' instead
49133
+ program
49134
+ .command("balances")
49135
+ .description("[deprecated] Use 'token-balances' instead")
49136
+ .option("-a, --all", "Show all assets including token accounts with 0 balance")
49137
+ .action(async (options) => {
49138
+ console.warn("Warning: 'balances' is deprecated, use 'token-balances' instead.");
49139
+ await tokenBalances(options);
48965
49140
  });
48966
49141
  program
48967
49142
  .command("list-assets")
@@ -49104,12 +49279,46 @@ module.exports = require("zlib");
49104
49279
 
49105
49280
  /***/ }),
49106
49281
  /* 642 */
49107
- /***/ ((__unused_webpack_module, exports, __webpack_require__) => {
49282
+ /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
49108
49283
 
49109
49284
  "use strict";
49110
49285
 
49286
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
49287
+ if (k2 === undefined) k2 = k;
49288
+ var desc = Object.getOwnPropertyDescriptor(m, k);
49289
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
49290
+ desc = { enumerable: true, get: function() { return m[k]; } };
49291
+ }
49292
+ Object.defineProperty(o, k2, desc);
49293
+ }) : (function(o, m, k, k2) {
49294
+ if (k2 === undefined) k2 = k;
49295
+ o[k2] = m[k];
49296
+ }));
49297
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
49298
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
49299
+ }) : function(o, v) {
49300
+ o["default"] = v;
49301
+ });
49302
+ var __importStar = (this && this.__importStar) || (function () {
49303
+ var ownKeys = function(o) {
49304
+ ownKeys = Object.getOwnPropertyNames || function (o) {
49305
+ var ar = [];
49306
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
49307
+ return ar;
49308
+ };
49309
+ return ownKeys(o);
49310
+ };
49311
+ return function (mod) {
49312
+ if (mod && mod.__esModule) return mod;
49313
+ var result = {};
49314
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
49315
+ __setModuleDefault(result, mod);
49316
+ return result;
49317
+ };
49318
+ })();
49111
49319
  Object.defineProperty(exports, "__esModule", ({ value: true }));
49112
49320
  exports.installManageCommands = installManageCommands;
49321
+ const anchor_1 = __webpack_require__(4);
49113
49322
  const utils_1 = __webpack_require__(102);
49114
49323
  const web3_js_1 = __webpack_require__(5);
49115
49324
  const glam_sdk_1 = __webpack_require__(1);
@@ -49204,6 +49413,62 @@ function installManageCommands(manage, context) {
49204
49413
  message: `Confirm unpausing ${action}`,
49205
49414
  }, (txSig) => `Unpaused ${action}: ${txSig}`);
49206
49415
  });
49416
+ manage
49417
+ .command("list-requests")
49418
+ .description("List pending user requests in the queue")
49419
+ .action(async () => {
49420
+ const queue = await context.glamClient.fetchRequestQueue();
49421
+ const requests = queue?.data || [];
49422
+ if (requests.length === 0) {
49423
+ console.log("No pending requests in the queue.");
49424
+ return;
49425
+ }
49426
+ const { baseAssetDecimals } = await context.glamClient.fetchStateModel();
49427
+ const { mint } = await (await Promise.resolve().then(() => __importStar(__webpack_require__(1)))).fetchMintAndTokenProgram(context.glamClient.connection, context.glamClient.mintPda);
49428
+ const shareDecimals = mint.decimals;
49429
+ console.log(`Found ${requests.length} request(s):\n`);
49430
+ for (const r of requests) {
49431
+ const type = Object.keys(r.requestType)[0];
49432
+ const isSub = glam_sdk_1.RequestType.equals(r.requestType, glam_sdk_1.RequestType.SUBSCRIPTION);
49433
+ const incoming = (0, glam_sdk_1.toUiAmount)(new anchor_1.BN(r.incoming.toString()), isSub ? baseAssetDecimals : shareDecimals);
49434
+ const outgoing = (0, glam_sdk_1.toUiAmount)(new anchor_1.BN(r.outgoing.toString()), isSub ? shareDecimals : baseAssetDecimals);
49435
+ const createdAt = new anchor_1.BN(r.createdAt.toString()).toNumber();
49436
+ const fulfilledAt = new anchor_1.BN(r.fulfilledAt.toString()).toNumber();
49437
+ const createdDate = createdAt
49438
+ ? new Date(createdAt * 1000).toISOString()
49439
+ : "N/A";
49440
+ const status = fulfilledAt ? "fulfilled (claimable)" : "pending";
49441
+ console.log(` User: ${r.user.toBase58()}`);
49442
+ console.log(` Type: ${type}`);
49443
+ console.log(` Incoming: ${incoming}`);
49444
+ console.log(` Outgoing: ${outgoing}`);
49445
+ console.log(` Status: ${status}`);
49446
+ console.log(` Created: ${createdDate}`);
49447
+ console.log();
49448
+ }
49449
+ });
49450
+ manage
49451
+ .command("cancel-for-user")
49452
+ .argument("<pubkey>", "Public key of the user", utils_1.validatePublicKey)
49453
+ .option("-y, --yes", "Skip confirmation prompt", false)
49454
+ .description("Cancel a queued request on behalf of a user")
49455
+ .action(async (pubkey, options) => {
49456
+ await (0, utils_1.executeTxWithErrorHandling)(() => context.glamClient.invest.cancelForUser(pubkey, context.txOptions), {
49457
+ skip: options?.yes,
49458
+ message: `Confirm canceling queued request for user ${pubkey.toBase58()}?`,
49459
+ }, (txSig) => `Cancelled request for ${pubkey.toBase58()}: ${txSig}`);
49460
+ });
49461
+ manage
49462
+ .command("claim-for-user")
49463
+ .argument("<pubkey>", "Public key of the user", utils_1.validatePublicKey)
49464
+ .option("-y, --yes", "Skip confirmation prompt", false)
49465
+ .description("Claim a fulfilled request on behalf of a user")
49466
+ .action(async (pubkey, options) => {
49467
+ await (0, utils_1.executeTxWithErrorHandling)(() => context.glamClient.invest.claimForUser(pubkey, context.txOptions), {
49468
+ skip: options?.yes,
49469
+ message: `Confirm claiming for user ${pubkey.toBase58()}?`,
49470
+ }, (txSig) => `Claimed for ${pubkey.toBase58()}: ${txSig}`);
49471
+ });
49207
49472
  }
49208
49473
 
49209
49474
 
@@ -49584,6 +49849,21 @@ function installTimelockCommands(program, context) {
49584
49849
  });
49585
49850
  }
49586
49851
  }
49852
+ else if (name === "assets" || name === "borrowable") {
49853
+ const { added, removed } = (0, glam_sdk_1.comparePublicKeyArrays)(stateModel[name] || [], value);
49854
+ if (added.length === 0 && removed.length === 0) {
49855
+ console.log(` ${name}: No changes`);
49856
+ }
49857
+ else {
49858
+ console.log(` ${name}:`);
49859
+ added.forEach((pk) => {
49860
+ console.log(` [+] ${pk.toBase58()}`);
49861
+ });
49862
+ removed.forEach((pk) => {
49863
+ console.log(` [-] ${pk.toBase58()}`);
49864
+ });
49865
+ }
49866
+ }
49587
49867
  else if (name === "timelockDuration") {
49588
49868
  console.log(` ${name}: ${stateModel.timelockDuration}s → ${value}s`);
49589
49869
  }
@@ -49765,7 +50045,7 @@ program
49765
50045
  initialize(config, skipSimulation);
49766
50046
  await (0, idl_1.idlCheck)(context.glamClient);
49767
50047
  })
49768
- .version("1.0.10");
50048
+ .version("1.0.11");
49769
50049
  program
49770
50050
  .command("env")
49771
50051
  .description("Display current environment setup")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glamsystems/glam-cli",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "CLI for interacting with the GLAM Protocol",
5
5
  "main": "./main.js",
6
6
  "bin": {
@@ -21,7 +21,7 @@
21
21
  "node": ">=20.20.0"
22
22
  },
23
23
  "dependencies": {
24
- "@glamsystems/glam-sdk": "1.0.10",
24
+ "@glamsystems/glam-sdk": "1.0.11",
25
25
  "@switchboard-xyz/common": "^3.0.0",
26
26
  "commander": "^11.1.0",
27
27
  "decimal.js": "^10.6.0",