@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.
- package/main.js +380 -100
- 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 =
|
|
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
|
-
|
|
48222
|
-
|
|
48223
|
-
|
|
48224
|
-
|
|
48225
|
-
|
|
48226
|
-
|
|
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
|
-
|
|
48242
|
-
|
|
48243
|
-
|
|
48244
|
-
|
|
48245
|
-
|
|
48246
|
-
|
|
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
|
-
|
|
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("
|
|
48926
|
-
.
|
|
48927
|
-
.option("
|
|
48928
|
-
.
|
|
48929
|
-
|
|
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
|
-
|
|
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)"]);
|
|
48944
|
-
printRow([
|
|
48945
|
-
|
|
48946
|
-
|
|
48947
|
-
|
|
48948
|
-
|
|
48949
|
-
]);
|
|
48950
|
-
|
|
48951
|
-
|
|
48952
|
-
|
|
48953
|
-
|
|
48954
|
-
|
|
48955
|
-
|
|
48956
|
-
|
|
48957
|
-
|
|
48958
|
-
|
|
48959
|
-
|
|
48960
|
-
|
|
48961
|
-
|
|
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.
|
|
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.
|
|
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.
|
|
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",
|