@glamsystems/glam-cli 1.0.3-alpha.4 → 1.0.3-alpha.6
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 +119 -57
- package/package.json +2 -2
package/main.js
CHANGED
|
@@ -5240,6 +5240,9 @@ async function fetchTokenPrices(pubkeys) {
|
|
|
5240
5240
|
async function fetchTokensList() {
|
|
5241
5241
|
const response = await fetch(`${JUPITER_API}/tokens/v2/tag?query=verified`);
|
|
5242
5242
|
const data = await response.json();
|
|
5243
|
+
if (!response.ok) {
|
|
5244
|
+
throw new Error(`Failed to fetch tokens list and prices from Jupiter: ${response.status} ${data?.message}`);
|
|
5245
|
+
}
|
|
5243
5246
|
const tokenList = data?.map((t) => ({
|
|
5244
5247
|
address: t.id,
|
|
5245
5248
|
name: t.name,
|
|
@@ -5248,6 +5251,7 @@ async function fetchTokensList() {
|
|
|
5248
5251
|
logoURI: t.icon,
|
|
5249
5252
|
tags: t.tags,
|
|
5250
5253
|
usdPrice: t.usdPrice,
|
|
5254
|
+
slot: t.priceBlockId,
|
|
5251
5255
|
}));
|
|
5252
5256
|
return tokenList;
|
|
5253
5257
|
}
|
|
@@ -8363,11 +8367,12 @@ const spl_token_1 = __webpack_require__(17);
|
|
|
8363
8367
|
const constants_1 = __webpack_require__(25);
|
|
8364
8368
|
const jupiter_1 = __webpack_require__(57);
|
|
8365
8369
|
class Holding {
|
|
8366
|
-
constructor(mintAddress, decimals, amount, price, protocol, protocolMeta = {}) {
|
|
8370
|
+
constructor(mintAddress, decimals, amount, price, priceMeta = {}, protocol, protocolMeta = {}) {
|
|
8367
8371
|
this.mintAddress = mintAddress;
|
|
8368
8372
|
this.decimals = decimals;
|
|
8369
8373
|
this.amount = amount;
|
|
8370
8374
|
this.price = price;
|
|
8375
|
+
this.priceMeta = priceMeta;
|
|
8371
8376
|
this.protocol = protocol;
|
|
8372
8377
|
this.protocolMeta = protocolMeta;
|
|
8373
8378
|
this.uiAmount = (0, utils_1.toUiAmount)(this.amount, this.decimals);
|
|
@@ -8481,7 +8486,7 @@ class PriceClient {
|
|
|
8481
8486
|
.map((v) => Array.from(v.pkValues()))
|
|
8482
8487
|
.flat();
|
|
8483
8488
|
// Dedupe keys and fetch all accounts in a single RPC call
|
|
8484
|
-
const pubkeys = Array.from(new utils_1.PkSet(tokenPubkeys.concat(...driftUsers, ...driftSpotMarkets, ...kaminoObligations, ...kaminoReserves)));
|
|
8489
|
+
const pubkeys = Array.from(new utils_1.PkSet(tokenPubkeys.concat(...driftUsers, ...driftSpotMarkets, ...kaminoObligations, ...kaminoReserves, web3_js_1.SYSVAR_CLOCK_PUBKEY)));
|
|
8485
8490
|
const { context: { slot }, value: accountsInfo, } = await this.base.provider.connection.getMultipleAccountsInfoAndContext(pubkeys, commitment);
|
|
8486
8491
|
// Build a map of pubkey to account data for quick lookup
|
|
8487
8492
|
const accountsDataMap = new utils_1.PkMap();
|
|
@@ -8506,10 +8511,12 @@ class PriceClient {
|
|
|
8506
8511
|
const tokenMint = new web3_js_1.PublicKey(item.address);
|
|
8507
8512
|
tokenPricesMap.set(tokenMint, item);
|
|
8508
8513
|
});
|
|
8509
|
-
const tokenHoldings = this.getTokenHoldings(tokenPubkeys, accountsDataMap, tokenPricesMap);
|
|
8510
|
-
const driftSpotHoldings = this.getDriftSpotHoldings(driftPubkeys.pkKeys(), driftSpotMarketsMap, accountsDataMap, tokenPricesMap);
|
|
8511
|
-
const kaminoLendHoldings = this.getKaminoLendHoldings(kaminoPubkeys.pkKeys(), kaminoReservesMap, accountsDataMap, tokenPricesMap);
|
|
8512
|
-
const timestamp =
|
|
8514
|
+
const tokenHoldings = this.getTokenHoldings(tokenPubkeys, accountsDataMap, tokenPricesMap, "Jupiter");
|
|
8515
|
+
const driftSpotHoldings = this.getDriftSpotHoldings(driftPubkeys.pkKeys(), driftSpotMarketsMap, accountsDataMap, tokenPricesMap, "Jupiter");
|
|
8516
|
+
const kaminoLendHoldings = this.getKaminoLendHoldings(kaminoPubkeys.pkKeys(), kaminoReservesMap, accountsDataMap, tokenPricesMap, "Jupiter");
|
|
8517
|
+
const timestamp = accountsDataMap
|
|
8518
|
+
.get(web3_js_1.SYSVAR_CLOCK_PUBKEY)
|
|
8519
|
+
.readUInt32LE(32);
|
|
8513
8520
|
const ret = new VaultHoldings(this.base.statePda, this.base.vaultPda, priceBaseAssetMint, slot, timestamp, commitment);
|
|
8514
8521
|
tokenHoldings.forEach((holding) => ret.add(holding));
|
|
8515
8522
|
driftSpotHoldings.forEach((holding) => ret.add(holding));
|
|
@@ -8567,7 +8574,7 @@ class PriceClient {
|
|
|
8567
8574
|
}
|
|
8568
8575
|
return obligationReservesMap;
|
|
8569
8576
|
}
|
|
8570
|
-
getTokenHoldings(tokenAccountPubkeys, accountsDataMap, tokenPricesMap) {
|
|
8577
|
+
getTokenHoldings(tokenAccountPubkeys, accountsDataMap, tokenPricesMap, priceSource) {
|
|
8571
8578
|
const holdings = [];
|
|
8572
8579
|
if (tokenAccountPubkeys.length === 0) {
|
|
8573
8580
|
return holdings;
|
|
@@ -8577,7 +8584,10 @@ class PriceClient {
|
|
|
8577
8584
|
const tokenInfo = tokenPricesMap.get(mint);
|
|
8578
8585
|
if (tokenInfo) {
|
|
8579
8586
|
const { decimals, usdPrice } = tokenInfo;
|
|
8580
|
-
const holding = new Holding(mint, decimals, new anchor_1.BN(amount), usdPrice,
|
|
8587
|
+
const holding = new Holding(mint, decimals, new anchor_1.BN(amount), usdPrice, {
|
|
8588
|
+
slot: tokenInfo.slot,
|
|
8589
|
+
source: priceSource,
|
|
8590
|
+
}, "Token", {
|
|
8581
8591
|
tokenAccount: pubkey,
|
|
8582
8592
|
});
|
|
8583
8593
|
holdings.push(holding);
|
|
@@ -8585,7 +8595,7 @@ class PriceClient {
|
|
|
8585
8595
|
}
|
|
8586
8596
|
return holdings;
|
|
8587
8597
|
}
|
|
8588
|
-
getDriftSpotHoldings(userPubkeys, spotMarketsMap, accountsDataMap, tokenPricesMap) {
|
|
8598
|
+
getDriftSpotHoldings(userPubkeys, spotMarketsMap, accountsDataMap, tokenPricesMap, priceSource) {
|
|
8589
8599
|
const holdings = [];
|
|
8590
8600
|
for (const userPda of userPubkeys) {
|
|
8591
8601
|
const { spotPositions } = (0, utils_1.decodeUser)(accountsDataMap.get(userPda));
|
|
@@ -8597,7 +8607,10 @@ class PriceClient {
|
|
|
8597
8607
|
: cumulativeDepositInterest;
|
|
8598
8608
|
const amount = this.drift.calcSpotBalanceBn(scaledBalance, decimals, interest);
|
|
8599
8609
|
const direction = Object.keys(balanceType)[0];
|
|
8600
|
-
const holding = new Holding(mint, decimals, amount, tokenPricesMap.get(mint).usdPrice,
|
|
8610
|
+
const holding = new Holding(mint, decimals, amount, tokenPricesMap.get(mint).usdPrice, {
|
|
8611
|
+
slot: tokenPricesMap.get(mint).slot,
|
|
8612
|
+
source: priceSource,
|
|
8613
|
+
}, "DriftProtocol", {
|
|
8601
8614
|
user: userPda,
|
|
8602
8615
|
marketIndex: marketIndex,
|
|
8603
8616
|
direction: direction,
|
|
@@ -8607,7 +8620,7 @@ class PriceClient {
|
|
|
8607
8620
|
}
|
|
8608
8621
|
return holdings;
|
|
8609
8622
|
}
|
|
8610
|
-
getKaminoLendHoldings(obligationPubkeys, reservesMap, accountsDataMap, tokenPricesMap) {
|
|
8623
|
+
getKaminoLendHoldings(obligationPubkeys, reservesMap, accountsDataMap, tokenPricesMap, priceSource) {
|
|
8611
8624
|
const holdings = [];
|
|
8612
8625
|
for (const obligation of obligationPubkeys) {
|
|
8613
8626
|
const { deposits, borrows } = this.klend.parseObligation(obligation, accountsDataMap.get(obligation));
|
|
@@ -8617,7 +8630,10 @@ class PriceClient {
|
|
|
8617
8630
|
.div(parsedReserve.collateralExchangeRate)
|
|
8618
8631
|
.floor();
|
|
8619
8632
|
const amount = new anchor_1.BN(supplyAmount.toString());
|
|
8620
|
-
const holding = new Holding(parsedReserve.liquidityMint, parsedReserve.liquidityMintDecimals, amount, tokenPricesMap.get(parsedReserve.liquidityMint).usdPrice,
|
|
8633
|
+
const holding = new Holding(parsedReserve.liquidityMint, parsedReserve.liquidityMintDecimals, amount, tokenPricesMap.get(parsedReserve.liquidityMint).usdPrice, {
|
|
8634
|
+
slot: tokenPricesMap.get(parsedReserve.liquidityMint).slot,
|
|
8635
|
+
source: priceSource,
|
|
8636
|
+
}, "KaminoLend", {
|
|
8621
8637
|
obligation,
|
|
8622
8638
|
market: parsedReserve.market,
|
|
8623
8639
|
reserve,
|
|
@@ -8634,7 +8650,10 @@ class PriceClient {
|
|
|
8634
8650
|
.div(obligationCumulativeBorrowRate)
|
|
8635
8651
|
.ceil();
|
|
8636
8652
|
const amount = new anchor_1.BN(borrowAmount.toString());
|
|
8637
|
-
const holding = new Holding(parsedReserve.liquidityMint, parsedReserve.liquidityMintDecimals, amount, tokenPricesMap.get(parsedReserve.liquidityMint).usdPrice,
|
|
8653
|
+
const holding = new Holding(parsedReserve.liquidityMint, parsedReserve.liquidityMintDecimals, amount, tokenPricesMap.get(parsedReserve.liquidityMint).usdPrice, {
|
|
8654
|
+
slot: tokenPricesMap.get(parsedReserve.liquidityMint).slot,
|
|
8655
|
+
source: priceSource,
|
|
8656
|
+
}, "KaminoLend", {
|
|
8638
8657
|
obligation,
|
|
8639
8658
|
market: parsedReserve.market,
|
|
8640
8659
|
reserve,
|
|
@@ -10416,7 +10435,8 @@ class CctpClient {
|
|
|
10416
10435
|
const ix = await this.buildReceiveMessageIx(sourceDomain, message);
|
|
10417
10436
|
receiveMessageIxs.push(ix);
|
|
10418
10437
|
}
|
|
10419
|
-
const
|
|
10438
|
+
const createUsdcAtaIx = (0, spl_token_1.createAssociatedTokenAccountIdempotentInstruction)(this.base.signer, this.base.getVaultAta(constants_1.USDC), this.base.vaultPda, constants_1.USDC);
|
|
10439
|
+
const tx = new web3_js_1.Transaction().add(createUsdcAtaIx, ...receiveMessageIxs);
|
|
10420
10440
|
const vTx = await this.base.intoVersionedTransaction(tx, txOptions);
|
|
10421
10441
|
return await this.base.sendAndConfirm(vTx);
|
|
10422
10442
|
}
|
|
@@ -10468,9 +10488,17 @@ class CctpClient {
|
|
|
10468
10488
|
];
|
|
10469
10489
|
}
|
|
10470
10490
|
async buildReceiveMessageIx(sourceDomain, messageObj) {
|
|
10471
|
-
const { message, attestation, eventNonce, decodedMessage
|
|
10491
|
+
const { message, attestation, eventNonce, decodedMessage, status } = messageObj;
|
|
10492
|
+
if (status !== "complete") {
|
|
10493
|
+
throw new Error(`Attestation status is ${status}, expected "complete"`);
|
|
10494
|
+
}
|
|
10495
|
+
if (!decodedMessage ||
|
|
10496
|
+
!decodedMessage?.decodedMessageBody ||
|
|
10497
|
+
!decodedMessage?.decodedMessageBody?.burnToken) {
|
|
10498
|
+
throw new Error("Invalid message object: missing burnToken in decodedMessage");
|
|
10499
|
+
}
|
|
10472
10500
|
// message, attestation, eventNonce, burnToken are hex strings
|
|
10473
|
-
const pdas = await this.getReceiveMessagePdas(constants_1.MESSAGE_TRANSMITTER_V2, constants_1.TOKEN_MESSENGER_MINTER_V2, constants_1.USDC, burnToken, sourceDomain.toString(), eventNonce);
|
|
10501
|
+
const pdas = await this.getReceiveMessagePdas(constants_1.MESSAGE_TRANSMITTER_V2, constants_1.TOKEN_MESSENGER_MINTER_V2, constants_1.USDC, decodedMessage.decodedMessageBody.burnToken, sourceDomain.toString(), eventNonce);
|
|
10474
10502
|
// raw ix data: [discriminator][message][attestation]
|
|
10475
10503
|
const messageBuffer = Buffer.from(message.replace("0x", ""), "hex");
|
|
10476
10504
|
const attestationBuffer = Buffer.from(attestation.replace("0x", ""), "hex");
|
|
@@ -10674,7 +10702,14 @@ class CctpClient {
|
|
|
10674
10702
|
queryParams.set("transactionHash", txHash);
|
|
10675
10703
|
}
|
|
10676
10704
|
const resonse = await fetch(`https://iris-api.circle.com/v2/messages/${sourceDomain}?${queryParams}`);
|
|
10705
|
+
if (resonse.status !== 200) {
|
|
10706
|
+
const { error } = await resonse.json();
|
|
10707
|
+
throw new Error(`Failed to fetch messages from Circle API: ${resonse.status} ${error}`);
|
|
10708
|
+
}
|
|
10677
10709
|
const { messages } = await resonse.json();
|
|
10710
|
+
if (!(messages instanceof Array)) {
|
|
10711
|
+
throw new Error("Invalid response from Circle API: messages not found");
|
|
10712
|
+
}
|
|
10678
10713
|
return messages;
|
|
10679
10714
|
}
|
|
10680
10715
|
/**
|
|
@@ -13067,37 +13102,6 @@ function installVaultCommands(program, context) {
|
|
|
13067
13102
|
process.exit(1);
|
|
13068
13103
|
}
|
|
13069
13104
|
});
|
|
13070
|
-
program
|
|
13071
|
-
.command("add-asset")
|
|
13072
|
-
.argument("<asset>", "Asset mint public key", utils_1.validatePublicKey)
|
|
13073
|
-
.description("Add a new asset to allowlist")
|
|
13074
|
-
.action(async (asset) => {
|
|
13075
|
-
const stateModel = await context.glamClient.fetchStateModel();
|
|
13076
|
-
const assetsSet = new Set([...stateModel.assets, asset].map((a) => a.toBase58()));
|
|
13077
|
-
const assets = Array.from(assetsSet).map((a) => new web3_js_1.PublicKey(a));
|
|
13078
|
-
const txSig = await context.glamClient.state.update({ assets }, context.txOptions);
|
|
13079
|
-
console.log(`Added asset ${asset}: ${txSig}`);
|
|
13080
|
-
});
|
|
13081
|
-
program
|
|
13082
|
-
.command("delete-asset")
|
|
13083
|
-
.argument("<asset>", "Asset mint public key", utils_1.validatePublicKey)
|
|
13084
|
-
.description("Delete an asset from allowlist")
|
|
13085
|
-
.action(async (asset) => {
|
|
13086
|
-
const stateModel = await context.glamClient.fetchStateModel();
|
|
13087
|
-
if (asset.equals(stateModel.baseAssetMint)) {
|
|
13088
|
-
console.error("Base asset cannot be deleted from allowlist");
|
|
13089
|
-
process.exit(1);
|
|
13090
|
-
}
|
|
13091
|
-
const assetsSet = new Set(stateModel.assets.map((a) => a.toBase58()));
|
|
13092
|
-
let removed = assetsSet.delete(asset.toBase58());
|
|
13093
|
-
if (!removed) {
|
|
13094
|
-
console.error("Asset not found in allowlist, nothing to delete");
|
|
13095
|
-
process.exit(1);
|
|
13096
|
-
}
|
|
13097
|
-
const assets = Array.from(assetsSet).map((a) => new web3_js_1.PublicKey(a));
|
|
13098
|
-
const txSig = await context.glamClient.state.update({ assets }, context.txOptions);
|
|
13099
|
-
console.log(`Deleted asset ${asset}: ${txSig}`);
|
|
13100
|
-
});
|
|
13101
13105
|
program
|
|
13102
13106
|
.command("set-enabled <enabled>")
|
|
13103
13107
|
.description("Set GLAM state enabled or disabled")
|
|
@@ -13319,6 +13323,58 @@ function installVaultCommands(program, context) {
|
|
|
13319
13323
|
}
|
|
13320
13324
|
});
|
|
13321
13325
|
});
|
|
13326
|
+
program
|
|
13327
|
+
.command("asset-allowlist")
|
|
13328
|
+
.description("Get asset allowlist and corresponding token account")
|
|
13329
|
+
.action(async () => {
|
|
13330
|
+
const state = await context.glamClient.fetchStateAccount();
|
|
13331
|
+
const mints = await (0, glam_sdk_1.fetchMintsAndTokenPrograms)(context.glamClient.connection, state.assets);
|
|
13332
|
+
const data = mints.map(({ mint: { address, decimals }, tokenProgram }) => {
|
|
13333
|
+
const tokenAccount = context.glamClient.getVaultAta(address, tokenProgram);
|
|
13334
|
+
return {
|
|
13335
|
+
assetMint: address,
|
|
13336
|
+
decimals,
|
|
13337
|
+
tokenAccount,
|
|
13338
|
+
tokenProgram,
|
|
13339
|
+
};
|
|
13340
|
+
});
|
|
13341
|
+
console.log(JSON.stringify(data, null, 2));
|
|
13342
|
+
});
|
|
13343
|
+
program
|
|
13344
|
+
.command("add-asset")
|
|
13345
|
+
.argument("<asset>", "Asset mint public key", utils_1.validatePublicKey)
|
|
13346
|
+
.description("Add a new asset to allowlist")
|
|
13347
|
+
.action(async (asset) => {
|
|
13348
|
+
const state = await context.glamClient.fetchStateAccount();
|
|
13349
|
+
const assetsSet = new glam_sdk_1.PkSet(state.assets);
|
|
13350
|
+
if (assetsSet.has(asset)) {
|
|
13351
|
+
console.error(`Asset ${asset} already allowlisted`);
|
|
13352
|
+
process.exit(1);
|
|
13353
|
+
}
|
|
13354
|
+
const assets = Array.from(assetsSet.add(asset));
|
|
13355
|
+
const txSig = await context.glamClient.state.update({ assets }, context.txOptions);
|
|
13356
|
+
console.log(`Allowlisted asset ${asset}: ${txSig}`);
|
|
13357
|
+
});
|
|
13358
|
+
program
|
|
13359
|
+
.command("delete-asset")
|
|
13360
|
+
.argument("<asset>", "Asset mint public key", utils_1.validatePublicKey)
|
|
13361
|
+
.description("Delete an asset from allowlist")
|
|
13362
|
+
.action(async (asset) => {
|
|
13363
|
+
const state = await context.glamClient.fetchStateAccount();
|
|
13364
|
+
if (asset.equals(state.baseAssetMint)) {
|
|
13365
|
+
console.error("Base asset should not be deleted from allowlist");
|
|
13366
|
+
process.exit(1);
|
|
13367
|
+
}
|
|
13368
|
+
const assetsSet = new glam_sdk_1.PkSet(state.assets);
|
|
13369
|
+
let removed = assetsSet.delete(asset);
|
|
13370
|
+
if (!removed) {
|
|
13371
|
+
console.error(`${asset} not found in allowlist, nothing to delete`);
|
|
13372
|
+
process.exit(1);
|
|
13373
|
+
}
|
|
13374
|
+
const assets = Array.from(assetsSet);
|
|
13375
|
+
const txSig = await context.glamClient.state.update({ assets }, context.txOptions);
|
|
13376
|
+
console.log(`Deleted asset ${asset} from allowlist: ${txSig}`);
|
|
13377
|
+
});
|
|
13322
13378
|
program
|
|
13323
13379
|
.command("holdings")
|
|
13324
13380
|
.description("Get vault holdings")
|
|
@@ -13666,15 +13722,21 @@ function installCctpCommands(program, context) {
|
|
|
13666
13722
|
.option("-n, --nonce <nonce>", "Nonce hex string (start with 0x)")
|
|
13667
13723
|
.description("Receive USDC from an EVM chain. Either txHash or nonce is required.")
|
|
13668
13724
|
.action(async (sourceDomain, { txHash, nonce }) => {
|
|
13669
|
-
|
|
13670
|
-
|
|
13671
|
-
|
|
13672
|
-
|
|
13673
|
-
|
|
13674
|
-
|
|
13675
|
-
|
|
13676
|
-
|
|
13677
|
-
|
|
13725
|
+
try {
|
|
13726
|
+
await context.glamClient.cctp.receiveUsdc(sourceDomain, {
|
|
13727
|
+
txHash,
|
|
13728
|
+
nonce,
|
|
13729
|
+
}, {
|
|
13730
|
+
...context.txOptions,
|
|
13731
|
+
lookupTables: [
|
|
13732
|
+
new web3_js_1.PublicKey("qj4EYgsGpnRdt9rvQW3wWZR8JVaKPg9rG9EB8DNgfz8"), // CCTP lookup table
|
|
13733
|
+
],
|
|
13734
|
+
});
|
|
13735
|
+
}
|
|
13736
|
+
catch (e) {
|
|
13737
|
+
console.error((0, utils_1.parseTxError)(e));
|
|
13738
|
+
process.exit(1);
|
|
13739
|
+
}
|
|
13678
13740
|
});
|
|
13679
13741
|
program
|
|
13680
13742
|
.command("list")
|
|
@@ -14106,7 +14168,7 @@ program
|
|
|
14106
14168
|
initialize(config, skipSimulation);
|
|
14107
14169
|
await (0, idl_1.idlCheck)(context.glamClient);
|
|
14108
14170
|
})
|
|
14109
|
-
.version("1.0.3-alpha.
|
|
14171
|
+
.version("1.0.3-alpha.6");
|
|
14110
14172
|
program
|
|
14111
14173
|
.command("env")
|
|
14112
14174
|
.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-alpha.
|
|
3
|
+
"version": "1.0.3-alpha.6",
|
|
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.18.0"
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@glamsystems/glam-sdk": "1.0.3-alpha.
|
|
24
|
+
"@glamsystems/glam-sdk": "1.0.3-alpha.6",
|
|
25
25
|
"@switchboard-xyz/common": "^3.0.0",
|
|
26
26
|
"commander": "^11.1.0",
|
|
27
27
|
"decimal.js": "^10.6.0",
|