@net-protocol/cli 0.1.43 → 0.1.44
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/dist/chat/index.mjs +24 -3
- package/dist/chat/index.mjs.map +1 -1
- package/dist/cli/index.mjs +463 -124
- package/dist/cli/index.mjs.map +1 -1
- package/dist/feed/index.mjs +407 -93
- package/dist/feed/index.mjs.map +1 -1
- package/dist/profile/index.mjs +17 -1
- package/dist/profile/index.mjs.map +1 -1
- package/dist/upvote/index.mjs +24 -1
- package/dist/upvote/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.mjs
CHANGED
|
@@ -6,10 +6,10 @@ import { createRequire } from 'module';
|
|
|
6
6
|
import chalk4 from 'chalk';
|
|
7
7
|
import * as fs6 from 'fs';
|
|
8
8
|
import { readFileSync, existsSync, mkdirSync, writeFileSync } from 'fs';
|
|
9
|
-
import { OPTIMAL_CHUNK_SIZE, StorageClient, detectFileTypeFromBase64, base64ToDataUri, shouldSuggestXmlStorage, getStorageKeyBytes,
|
|
9
|
+
import { OPTIMAL_CHUNK_SIZE, StorageClient, detectFileTypeFromBase64, base64ToDataUri, shouldSuggestXmlStorage, getStorageKeyBytes, chunkDataForStorage, CHUNKED_STORAGE_CONTRACT, STORAGE_CONTRACT as STORAGE_CONTRACT$1, encodeStorageKeyForUrl } from '@net-protocol/storage';
|
|
10
10
|
import { createPublicClient, http, createWalletClient, stringToHex, hexToString, parseEther, encodeFunctionData, publicActions, concat, defineChain, decodeEventLog, formatEther, isAddress } from 'viem';
|
|
11
|
+
import { getSupportedChains, getNetContract, getChainName, getChainRpcUrls, getPublicClient, getBaseDataSuffix, NetClient, toBytes32, getChainBlockExplorer, NULL_ADDRESS, getChainSlug } from '@net-protocol/core';
|
|
11
12
|
import { privateKeyToAccount } from 'viem/accounts';
|
|
12
|
-
import { getNetContract, getChainName, getChainRpcUrls, getPublicClient, getBaseDataSuffix, NetClient, toBytes32, NULL_ADDRESS } from '@net-protocol/core';
|
|
13
13
|
import { fundBackendWallet, checkBackendWalletBalance, createRelayX402Client, createRelaySession, batchTransactions, submitTransactionsViaRelay, waitForConfirmations, retryFailedTransactions as retryFailedTransactions$1 } from '@net-protocol/relay';
|
|
14
14
|
import { isCommentTopic, parseCommentData, FeedRegistryClient, FeedClient, AgentRegistryClient, COMMENT_TOPIC_SUFFIX, FEED_TOPIC_PREFIX } from '@net-protocol/feeds';
|
|
15
15
|
import '@net-protocol/chats';
|
|
@@ -130,6 +130,75 @@ function parseCommonOptionsWithDefault(options, supportsEncodeOnly = false) {
|
|
|
130
130
|
rpcUrl: getRpcUrlWithBotchanFallback(options.rpcUrl)
|
|
131
131
|
};
|
|
132
132
|
}
|
|
133
|
+
var WEBSITE_BASE = "https://netprotocol.app";
|
|
134
|
+
var STORAGE_BASE = "https://storedon.net";
|
|
135
|
+
function chainSlug(chainId) {
|
|
136
|
+
return getChainSlug({ chainId }) ?? null;
|
|
137
|
+
}
|
|
138
|
+
function stripFeedPrefix(topic) {
|
|
139
|
+
const lower = topic.toLowerCase();
|
|
140
|
+
return lower.startsWith("feed-") ? lower.slice(5) : lower;
|
|
141
|
+
}
|
|
142
|
+
function feedUrl(chainId, feedName) {
|
|
143
|
+
const slug = chainSlug(chainId);
|
|
144
|
+
if (!slug) return null;
|
|
145
|
+
return `${WEBSITE_BASE}/app/feed/${slug}/${stripFeedPrefix(feedName)}`;
|
|
146
|
+
}
|
|
147
|
+
function walletUrl(chainId, address) {
|
|
148
|
+
const slug = chainSlug(chainId);
|
|
149
|
+
if (!slug) return null;
|
|
150
|
+
return `${WEBSITE_BASE}/app/feed/${slug}/${address.toLowerCase()}`;
|
|
151
|
+
}
|
|
152
|
+
function profileUrl(chainId, address) {
|
|
153
|
+
const slug = chainSlug(chainId);
|
|
154
|
+
if (!slug) return null;
|
|
155
|
+
return `${WEBSITE_BASE}/app/profile/${slug}/${address.toLowerCase()}`;
|
|
156
|
+
}
|
|
157
|
+
function tokenUrl(chainId, tokenAddress) {
|
|
158
|
+
const slug = chainSlug(chainId);
|
|
159
|
+
if (!slug) return null;
|
|
160
|
+
return `${WEBSITE_BASE}/app/token/${slug}/${tokenAddress.toLowerCase()}`;
|
|
161
|
+
}
|
|
162
|
+
function storageUrl(chainId, operatorAddress, key) {
|
|
163
|
+
return `${STORAGE_BASE}/net/${chainId}/storage/load/${operatorAddress.toLowerCase()}/${encodeStorageKeyForUrl(
|
|
164
|
+
key
|
|
165
|
+
)}`;
|
|
166
|
+
}
|
|
167
|
+
function explorerTxUrl(chainId, txHash) {
|
|
168
|
+
const base9 = getChainBlockExplorer({ chainId })?.url;
|
|
169
|
+
if (!base9) return null;
|
|
170
|
+
return `${base9}/tx/${txHash}`;
|
|
171
|
+
}
|
|
172
|
+
function explorerAddressUrl(chainId, address) {
|
|
173
|
+
const base9 = getChainBlockExplorer({ chainId })?.url;
|
|
174
|
+
if (!base9) return null;
|
|
175
|
+
return `${base9}/address/${address}`;
|
|
176
|
+
}
|
|
177
|
+
function postIdToCommentParam(postId) {
|
|
178
|
+
const colon = postId.indexOf(":");
|
|
179
|
+
if (colon === -1) return postId;
|
|
180
|
+
return `${postId.slice(0, colon)}-${postId.slice(colon + 1)}`;
|
|
181
|
+
}
|
|
182
|
+
function postPermalink(chainId, opts) {
|
|
183
|
+
const slug = chainSlug(chainId);
|
|
184
|
+
if (!slug) return null;
|
|
185
|
+
const params = new URLSearchParams();
|
|
186
|
+
if (opts.globalIndex != null) {
|
|
187
|
+
params.set("index", String(opts.globalIndex));
|
|
188
|
+
} else if (opts.topic != null && opts.topicIndex != null) {
|
|
189
|
+
params.set("topic", stripFeedPrefix(opts.topic));
|
|
190
|
+
params.set("index", String(opts.topicIndex));
|
|
191
|
+
} else if (opts.user != null && opts.userIndex != null) {
|
|
192
|
+
params.set("user", opts.user.toLowerCase());
|
|
193
|
+
params.set("index", String(opts.userIndex));
|
|
194
|
+
} else {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
197
|
+
if (opts.commentId) {
|
|
198
|
+
params.set("commentId", postIdToCommentParam(opts.commentId));
|
|
199
|
+
}
|
|
200
|
+
return `${WEBSITE_BASE}/app/feed/${slug}/post?${params.toString()}`;
|
|
201
|
+
}
|
|
133
202
|
async function checkNormalStorageExists(params) {
|
|
134
203
|
const { storageClient, storageKey, operatorAddress, expectedContent } = params;
|
|
135
204
|
const existing = await storageClient.get({
|
|
@@ -213,7 +282,7 @@ function extractTypedArgsFromTransaction(tx, type) {
|
|
|
213
282
|
}
|
|
214
283
|
function generateStorageUrl(operatorAddress, chainId, storageKey) {
|
|
215
284
|
if (!operatorAddress) return void 0;
|
|
216
|
-
return
|
|
285
|
+
return storageUrl(chainId, operatorAddress, storageKey);
|
|
217
286
|
}
|
|
218
287
|
async function checkTransactionExists(params) {
|
|
219
288
|
const { storageClient, tx, operatorAddress } = params;
|
|
@@ -1182,6 +1251,11 @@ async function executeStorageRead(options) {
|
|
|
1182
1251
|
key: options.key,
|
|
1183
1252
|
operator: options.operator,
|
|
1184
1253
|
chainId: readOnlyOptions.chainId,
|
|
1254
|
+
storageUrl: storageUrl(
|
|
1255
|
+
readOnlyOptions.chainId,
|
|
1256
|
+
options.operator,
|
|
1257
|
+
options.key
|
|
1258
|
+
),
|
|
1185
1259
|
text: result.text,
|
|
1186
1260
|
data: options.raw ? result.data : result.data,
|
|
1187
1261
|
isXml: result.isXml,
|
|
@@ -1374,7 +1448,7 @@ function registerStorageCommand(program2) {
|
|
|
1374
1448
|
try {
|
|
1375
1449
|
console.log(chalk4.blue(`\u{1F4C1} Reading file: ${options.file}`));
|
|
1376
1450
|
const result = await uploadFile(uploadOptions);
|
|
1377
|
-
const
|
|
1451
|
+
const storageUrl2 = generateStorageUrl(
|
|
1378
1452
|
result.operatorAddress,
|
|
1379
1453
|
commonOptions.chainId,
|
|
1380
1454
|
options.key
|
|
@@ -1384,8 +1458,8 @@ function registerStorageCommand(program2) {
|
|
|
1384
1458
|
chalk4.green(
|
|
1385
1459
|
`\u2713 All data already stored - skipping upload
|
|
1386
1460
|
Storage Key: ${options.key}
|
|
1387
|
-
Skipped: ${result.transactionsSkipped} transaction(s)${
|
|
1388
|
-
Storage URL: ${chalk4.cyan(
|
|
1461
|
+
Skipped: ${result.transactionsSkipped} transaction(s)${storageUrl2 ? `
|
|
1462
|
+
Storage URL: ${chalk4.cyan(storageUrl2)}` : ""}`
|
|
1389
1463
|
)
|
|
1390
1464
|
);
|
|
1391
1465
|
process.exit(0);
|
|
@@ -1398,8 +1472,8 @@ function registerStorageCommand(program2) {
|
|
|
1398
1472
|
Storage Type: ${result.storageType === "xml" ? "XML" : "Normal"}
|
|
1399
1473
|
Transactions Sent: ${result.transactionsSent}
|
|
1400
1474
|
Transactions Skipped: ${result.transactionsSkipped}
|
|
1401
|
-
Final Transaction Hash: ${result.finalHash || "N/A"}${
|
|
1402
|
-
Storage URL: ${chalk4.cyan(
|
|
1475
|
+
Final Transaction Hash: ${result.finalHash || "N/A"}${storageUrl2 ? `
|
|
1476
|
+
Storage URL: ${chalk4.cyan(storageUrl2)}` : ""}`
|
|
1403
1477
|
)
|
|
1404
1478
|
);
|
|
1405
1479
|
process.exit(0);
|
|
@@ -1456,7 +1530,7 @@ function registerStorageCommand(program2) {
|
|
|
1456
1530
|
try {
|
|
1457
1531
|
console.log(chalk4.blue(`\u{1F4C1} Reading file: ${options.file}`));
|
|
1458
1532
|
const result = await previewFile(previewOptions);
|
|
1459
|
-
const
|
|
1533
|
+
const storageUrl2 = generateStorageUrl(
|
|
1460
1534
|
result.operatorAddress,
|
|
1461
1535
|
commonOptions.chainId,
|
|
1462
1536
|
options.key
|
|
@@ -1492,8 +1566,8 @@ function registerStorageCommand(program2) {
|
|
|
1492
1566
|
console.log(
|
|
1493
1567
|
` Operator Address: ${chalk4.gray(result.operatorAddress)}`
|
|
1494
1568
|
);
|
|
1495
|
-
if (
|
|
1496
|
-
console.log(` Storage URL: ${chalk4.cyan(
|
|
1569
|
+
if (storageUrl2) {
|
|
1570
|
+
console.log(` Storage URL: ${chalk4.cyan(storageUrl2)}`);
|
|
1497
1571
|
}
|
|
1498
1572
|
if (result.needToStoreChunks === 0 && !result.metadataNeedsStorage) {
|
|
1499
1573
|
console.log(
|
|
@@ -1569,7 +1643,7 @@ function registerStorageCommand(program2) {
|
|
|
1569
1643
|
const result = await uploadFileWithRelay(uploadRelayOptions);
|
|
1570
1644
|
const { privateKeyToAccount: privateKeyToAccount28 } = await import('viem/accounts');
|
|
1571
1645
|
const userAccount = privateKeyToAccount28(commonOptions.privateKey);
|
|
1572
|
-
const
|
|
1646
|
+
const storageUrl2 = generateStorageUrl(
|
|
1573
1647
|
userAccount.address,
|
|
1574
1648
|
commonOptions.chainId,
|
|
1575
1649
|
options.key
|
|
@@ -1585,8 +1659,8 @@ function registerStorageCommand(program2) {
|
|
|
1585
1659
|
Metadata Submitted: ${result.metadataSubmitted ? "Yes" : "No (already exists)"}
|
|
1586
1660
|
Backend Wallet: ${result.backendWalletAddress}
|
|
1587
1661
|
Chunk Transaction Hashes: ${result.chunkTransactionHashes.length > 0 ? result.chunkTransactionHashes.join(", ") : "None"}${result.metadataTransactionHash ? `
|
|
1588
|
-
Metadata Transaction Hash: ${result.metadataTransactionHash}` : ""}${
|
|
1589
|
-
Storage URL: ${chalk4.cyan(
|
|
1662
|
+
Metadata Transaction Hash: ${result.metadataTransactionHash}` : ""}${storageUrl2 ? `
|
|
1663
|
+
Storage URL: ${chalk4.cyan(storageUrl2)}` : ""}`
|
|
1590
1664
|
)
|
|
1591
1665
|
);
|
|
1592
1666
|
process.exit(0);
|
|
@@ -1935,33 +2009,25 @@ function registerMessageCommand(program2) {
|
|
|
1935
2009
|
messageCommand.addCommand(readCommand);
|
|
1936
2010
|
messageCommand.addCommand(countCommand);
|
|
1937
2011
|
}
|
|
1938
|
-
var SUPPORTED_CHAINS = [
|
|
1939
|
-
{ id: 8453, name: "Base", type: "mainnet" },
|
|
1940
|
-
{ id: 1, name: "Ethereum", type: "mainnet" },
|
|
1941
|
-
{ id: 666666666, name: "Degen", type: "mainnet" },
|
|
1942
|
-
{ id: 5112, name: "Ham", type: "mainnet" },
|
|
1943
|
-
{ id: 57073, name: "Ink", type: "mainnet" },
|
|
1944
|
-
{ id: 130, name: "Unichain", type: "mainnet" },
|
|
1945
|
-
{ id: 999, name: "HyperEVM", type: "mainnet" },
|
|
1946
|
-
{ id: 9745, name: "Plasma", type: "mainnet" },
|
|
1947
|
-
{ id: 143, name: "Monad", type: "mainnet" },
|
|
1948
|
-
{ id: 84532, name: "Base Sepolia", type: "testnet" },
|
|
1949
|
-
{ id: 11155111, name: "Sepolia", type: "testnet" }
|
|
1950
|
-
];
|
|
1951
2012
|
function registerChainsCommand(program2) {
|
|
1952
2013
|
program2.command("chains").description("List supported chains").option("--json", "Output in JSON format").action((options) => {
|
|
2014
|
+
const chains = getSupportedChains();
|
|
1953
2015
|
if (options.json) {
|
|
1954
|
-
console.log(JSON.stringify(
|
|
2016
|
+
console.log(JSON.stringify(chains, null, 2));
|
|
1955
2017
|
return;
|
|
1956
2018
|
}
|
|
1957
2019
|
console.log(chalk4.white.bold("Supported Chains:\n"));
|
|
1958
2020
|
console.log(chalk4.cyan("Mainnets:"));
|
|
1959
|
-
|
|
1960
|
-
console.log(
|
|
2021
|
+
chains.filter((c) => c.type === "mainnet").forEach((chain) => {
|
|
2022
|
+
console.log(
|
|
2023
|
+
` ${chalk4.white(chain.name)} ${chalk4.gray(`(${chain.chainId})`)}`
|
|
2024
|
+
);
|
|
1961
2025
|
});
|
|
1962
2026
|
console.log(chalk4.cyan("\nTestnets:"));
|
|
1963
|
-
|
|
1964
|
-
console.log(
|
|
2027
|
+
chains.filter((c) => c.type === "testnet").forEach((chain) => {
|
|
2028
|
+
console.log(
|
|
2029
|
+
` ${chalk4.white(chain.name)} ${chalk4.gray(`(${chain.chainId})`)}`
|
|
2030
|
+
);
|
|
1965
2031
|
});
|
|
1966
2032
|
});
|
|
1967
2033
|
}
|
|
@@ -2225,10 +2291,19 @@ async function executeTokenInfo(options) {
|
|
|
2225
2291
|
const output = {
|
|
2226
2292
|
address: tokenAddress,
|
|
2227
2293
|
chainId: readOnlyOptions.chainId,
|
|
2294
|
+
tokenUrl: tokenUrl(readOnlyOptions.chainId, tokenAddress),
|
|
2295
|
+
explorerAddressUrl: explorerAddressUrl(
|
|
2296
|
+
readOnlyOptions.chainId,
|
|
2297
|
+
tokenAddress
|
|
2298
|
+
),
|
|
2228
2299
|
token: {
|
|
2229
2300
|
name: token.name,
|
|
2230
2301
|
symbol: token.symbol,
|
|
2231
2302
|
deployer: token.deployer,
|
|
2303
|
+
deployerProfileUrl: profileUrl(
|
|
2304
|
+
readOnlyOptions.chainId,
|
|
2305
|
+
token.deployer
|
|
2306
|
+
),
|
|
2232
2307
|
image: token.image,
|
|
2233
2308
|
animation: token.animation || null,
|
|
2234
2309
|
fid: token.fid.toString(),
|
|
@@ -2427,6 +2502,8 @@ async function executeProfileGet(options) {
|
|
|
2427
2502
|
const output = {
|
|
2428
2503
|
address: options.address,
|
|
2429
2504
|
chainId: readOnlyOptions.chainId,
|
|
2505
|
+
profileUrl: profileUrl(readOnlyOptions.chainId, options.address),
|
|
2506
|
+
walletUrl: walletUrl(readOnlyOptions.chainId, options.address),
|
|
2430
2507
|
profilePicture: profilePicture || null,
|
|
2431
2508
|
displayName: displayName || null,
|
|
2432
2509
|
xUsername: xUsername || null,
|
|
@@ -5679,38 +5756,70 @@ function formatComment(comment, depth) {
|
|
|
5679
5756
|
];
|
|
5680
5757
|
return lines.join("\n");
|
|
5681
5758
|
}
|
|
5682
|
-
function
|
|
5759
|
+
function stripFeedPrefix2(topic) {
|
|
5760
|
+
const match = topic.match(/^(.+?):comments:/);
|
|
5761
|
+
const base9 = match ? match[1] : topic;
|
|
5762
|
+
return base9.replace(/^feed-/i, "");
|
|
5763
|
+
}
|
|
5764
|
+
function postToJson(post, options) {
|
|
5765
|
+
const { chainId, topicIndex, userIndex, globalIndex, commentCount } = options;
|
|
5766
|
+
const feedName = stripFeedPrefix2(post.topic);
|
|
5767
|
+
const postId = `${post.sender}:${post.timestamp}`;
|
|
5768
|
+
const permalink = postPermalink(chainId, {
|
|
5769
|
+
globalIndex,
|
|
5770
|
+
topic: post.topic,
|
|
5771
|
+
topicIndex,
|
|
5772
|
+
user: userIndex !== void 0 ? post.sender : void 0,
|
|
5773
|
+
userIndex
|
|
5774
|
+
});
|
|
5683
5775
|
const result = {
|
|
5684
|
-
|
|
5776
|
+
postId,
|
|
5777
|
+
permalink,
|
|
5685
5778
|
sender: post.sender,
|
|
5779
|
+
senderProfileUrl: profileUrl(chainId, post.sender),
|
|
5780
|
+
senderWalletUrl: walletUrl(chainId, post.sender),
|
|
5686
5781
|
text: post.text,
|
|
5687
5782
|
timestamp: Number(post.timestamp),
|
|
5783
|
+
feed: feedName,
|
|
5784
|
+
feedUrl: feedUrl(chainId, feedName),
|
|
5688
5785
|
topic: post.topic
|
|
5689
5786
|
};
|
|
5690
|
-
if (
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
if (
|
|
5694
|
-
|
|
5695
|
-
}
|
|
5787
|
+
if (topicIndex !== void 0) result.topicIndex = topicIndex;
|
|
5788
|
+
if (userIndex !== void 0) result.userIndex = userIndex;
|
|
5789
|
+
if (globalIndex !== void 0) result.globalIndex = globalIndex;
|
|
5790
|
+
if (commentCount !== void 0) result.commentCount = commentCount;
|
|
5791
|
+
if (post.data && post.data !== "0x") result.data = post.data;
|
|
5696
5792
|
return result;
|
|
5697
5793
|
}
|
|
5698
|
-
function feedToJson(feed, index) {
|
|
5699
|
-
|
|
5794
|
+
function feedToJson(feed, index, chainId) {
|
|
5795
|
+
const result = {
|
|
5700
5796
|
index,
|
|
5701
5797
|
feedName: feed.feedName,
|
|
5702
5798
|
registrant: feed.registrant,
|
|
5703
5799
|
timestamp: feed.timestamp
|
|
5704
5800
|
};
|
|
5801
|
+
if (chainId !== void 0) {
|
|
5802
|
+
result.feedUrl = feedUrl(chainId, feed.feedName);
|
|
5803
|
+
}
|
|
5804
|
+
return result;
|
|
5705
5805
|
}
|
|
5706
|
-
function commentToJson(comment,
|
|
5707
|
-
|
|
5806
|
+
function commentToJson(comment, options) {
|
|
5807
|
+
const { chainId, depth, parentPostUrl } = options;
|
|
5808
|
+
const commentParam = `${comment.sender}-${comment.timestamp}`;
|
|
5809
|
+
const permalink = parentPostUrl ? `${parentPostUrl}${parentPostUrl.includes("?") ? "&" : "?"}commentId=${commentParam}` : null;
|
|
5810
|
+
const result = {
|
|
5811
|
+
commentId: `${comment.sender}:${comment.timestamp}`,
|
|
5812
|
+
permalink,
|
|
5708
5813
|
sender: comment.sender,
|
|
5814
|
+
senderProfileUrl: profileUrl(chainId, comment.sender),
|
|
5709
5815
|
text: comment.text,
|
|
5710
5816
|
timestamp: Number(comment.timestamp),
|
|
5711
|
-
depth
|
|
5712
|
-
data: comment.data !== "0x" ? comment.data : void 0
|
|
5817
|
+
depth
|
|
5713
5818
|
};
|
|
5819
|
+
if (comment.data !== "0x") {
|
|
5820
|
+
result.data = comment.data;
|
|
5821
|
+
}
|
|
5822
|
+
return result;
|
|
5714
5823
|
}
|
|
5715
5824
|
function formatAgent(agent, index) {
|
|
5716
5825
|
const timestamp = formatTimestamp(agent.timestamp);
|
|
@@ -5720,12 +5829,17 @@ function formatAgent(agent, index) {
|
|
|
5720
5829
|
];
|
|
5721
5830
|
return lines.join("\n");
|
|
5722
5831
|
}
|
|
5723
|
-
function agentToJson(agent, index) {
|
|
5724
|
-
|
|
5832
|
+
function agentToJson(agent, index, chainId) {
|
|
5833
|
+
const result = {
|
|
5725
5834
|
index,
|
|
5726
5835
|
address: agent.address,
|
|
5727
5836
|
timestamp: agent.timestamp
|
|
5728
5837
|
};
|
|
5838
|
+
if (chainId !== void 0) {
|
|
5839
|
+
result.profileUrl = profileUrl(chainId, agent.address);
|
|
5840
|
+
result.walletUrl = walletUrl(chainId, agent.address);
|
|
5841
|
+
}
|
|
5842
|
+
return result;
|
|
5729
5843
|
}
|
|
5730
5844
|
function printJson(data) {
|
|
5731
5845
|
console.log(JSON.stringify(data, null, 2));
|
|
@@ -5743,7 +5857,11 @@ async function executeFeedList(options) {
|
|
|
5743
5857
|
maxFeeds: options.limit ?? 50
|
|
5744
5858
|
});
|
|
5745
5859
|
if (options.json) {
|
|
5746
|
-
printJson(
|
|
5860
|
+
printJson(
|
|
5861
|
+
feeds.map(
|
|
5862
|
+
(feed, i) => feedToJson(feed, i, readOnlyOptions.chainId)
|
|
5863
|
+
)
|
|
5864
|
+
);
|
|
5747
5865
|
} else {
|
|
5748
5866
|
if (feeds.length === 0) {
|
|
5749
5867
|
console.log(chalk4.yellow("No registered feeds found"));
|
|
@@ -5969,26 +6087,31 @@ async function executeFeedRead(feed, options) {
|
|
|
5969
6087
|
return;
|
|
5970
6088
|
}
|
|
5971
6089
|
const fetchLimit = options.sender ? Math.max(limit * 5, 100) : limit;
|
|
5972
|
-
|
|
6090
|
+
const fetched = await client.getFeedPostsWithIndex({
|
|
5973
6091
|
topic: normalizedFeed,
|
|
5974
6092
|
maxPosts: fetchLimit
|
|
5975
6093
|
});
|
|
6094
|
+
let postsWithIndex = fetched.messages.map((post, i) => ({
|
|
6095
|
+
post,
|
|
6096
|
+
topicIndex: fetched.startIndex + i
|
|
6097
|
+
}));
|
|
5976
6098
|
if (options.sender) {
|
|
5977
6099
|
const senderLower = options.sender.toLowerCase();
|
|
5978
|
-
|
|
5979
|
-
(post) => post.sender.toLowerCase() === senderLower
|
|
6100
|
+
postsWithIndex = postsWithIndex.filter(
|
|
6101
|
+
({ post }) => post.sender.toLowerCase() === senderLower
|
|
5980
6102
|
);
|
|
5981
|
-
|
|
6103
|
+
postsWithIndex = postsWithIndex.slice(0, limit);
|
|
5982
6104
|
}
|
|
5983
6105
|
if (options.unseen) {
|
|
5984
6106
|
const lastSeen = getLastSeenTimestamp(normalizedFeed);
|
|
5985
6107
|
const myAddress = getMyAddress();
|
|
5986
|
-
|
|
6108
|
+
postsWithIndex = postsWithIndex.filter(({ post }) => {
|
|
5987
6109
|
const isNew = lastSeen === null || Number(post.timestamp) > lastSeen;
|
|
5988
6110
|
const isFromOther = !myAddress || post.sender.toLowerCase() !== myAddress;
|
|
5989
6111
|
return isNew && isFromOther;
|
|
5990
6112
|
});
|
|
5991
6113
|
}
|
|
6114
|
+
const posts = postsWithIndex.map(({ post }) => post);
|
|
5992
6115
|
if (options.markSeen) {
|
|
5993
6116
|
const allPosts = await client.getFeedPosts({
|
|
5994
6117
|
topic: normalizedFeed,
|
|
@@ -6004,7 +6127,13 @@ async function executeFeedRead(feed, options) {
|
|
|
6004
6127
|
);
|
|
6005
6128
|
if (options.json) {
|
|
6006
6129
|
printJson(
|
|
6007
|
-
|
|
6130
|
+
postsWithIndex.map(
|
|
6131
|
+
({ post, topicIndex }, i) => postToJson(post, {
|
|
6132
|
+
chainId: readOnlyOptions.chainId,
|
|
6133
|
+
topicIndex,
|
|
6134
|
+
commentCount: commentCounts[i]
|
|
6135
|
+
})
|
|
6136
|
+
)
|
|
6008
6137
|
);
|
|
6009
6138
|
} else {
|
|
6010
6139
|
if (posts.length === 0) {
|
|
@@ -6066,6 +6195,34 @@ async function executeTransaction(walletClient, txConfig) {
|
|
|
6066
6195
|
});
|
|
6067
6196
|
return hash;
|
|
6068
6197
|
}
|
|
6198
|
+
async function getMessageIndicesFromTx(params) {
|
|
6199
|
+
const publicClient = getPublicClient({
|
|
6200
|
+
chainId: params.chainId,
|
|
6201
|
+
rpcUrl: params.rpcUrl
|
|
6202
|
+
});
|
|
6203
|
+
const netContract = getNetContract(params.chainId);
|
|
6204
|
+
const contractAddress = netContract.address.toLowerCase();
|
|
6205
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
6206
|
+
hash: params.txHash
|
|
6207
|
+
});
|
|
6208
|
+
const indices = [];
|
|
6209
|
+
for (const log of receipt.logs) {
|
|
6210
|
+
if (log.address.toLowerCase() !== contractAddress) continue;
|
|
6211
|
+
try {
|
|
6212
|
+
const decoded = decodeEventLog({
|
|
6213
|
+
abi: netContract.abi,
|
|
6214
|
+
data: log.data,
|
|
6215
|
+
topics: log.topics
|
|
6216
|
+
});
|
|
6217
|
+
if (decoded.eventName === "MessageSent") {
|
|
6218
|
+
const args = decoded.args;
|
|
6219
|
+
indices.push(Number(args.messageIndex));
|
|
6220
|
+
}
|
|
6221
|
+
} catch {
|
|
6222
|
+
}
|
|
6223
|
+
}
|
|
6224
|
+
return indices;
|
|
6225
|
+
}
|
|
6069
6226
|
|
|
6070
6227
|
// src/commands/feed/post.ts
|
|
6071
6228
|
var MAX_MESSAGE_LENGTH = 4e3;
|
|
@@ -6117,11 +6274,23 @@ ${options.body}` : message;
|
|
|
6117
6274
|
commonOptions.chainId,
|
|
6118
6275
|
commonOptions.rpcUrl
|
|
6119
6276
|
);
|
|
6120
|
-
|
|
6277
|
+
if (!options.json) {
|
|
6278
|
+
console.log(chalk4.blue(`Posting to feed "${normalizedFeed}"...`));
|
|
6279
|
+
}
|
|
6121
6280
|
try {
|
|
6122
6281
|
const hash = await executeTransaction(walletClient, txConfig);
|
|
6123
6282
|
const senderAddress = walletClient.account.address;
|
|
6124
6283
|
let postId;
|
|
6284
|
+
let globalIndex;
|
|
6285
|
+
try {
|
|
6286
|
+
const indices = await getMessageIndicesFromTx({
|
|
6287
|
+
chainId: commonOptions.chainId,
|
|
6288
|
+
rpcUrl: commonOptions.rpcUrl,
|
|
6289
|
+
txHash: hash
|
|
6290
|
+
});
|
|
6291
|
+
globalIndex = indices[0];
|
|
6292
|
+
} catch {
|
|
6293
|
+
}
|
|
6125
6294
|
try {
|
|
6126
6295
|
const posts = await client.getFeedPosts({
|
|
6127
6296
|
topic: normalizedFeed,
|
|
@@ -6143,19 +6312,36 @@ ${options.body}` : message;
|
|
|
6143
6312
|
sender: senderAddress,
|
|
6144
6313
|
text: fullMessage,
|
|
6145
6314
|
postId
|
|
6146
|
-
// Now we have the actual post ID for checking comments later
|
|
6147
6315
|
});
|
|
6316
|
+
const permalink = postPermalink(commonOptions.chainId, {
|
|
6317
|
+
globalIndex
|
|
6318
|
+
});
|
|
6319
|
+
if (options.json) {
|
|
6320
|
+
printJson({
|
|
6321
|
+
success: true,
|
|
6322
|
+
txHash: hash,
|
|
6323
|
+
explorerTxUrl: explorerTxUrl(commonOptions.chainId, hash),
|
|
6324
|
+
postId,
|
|
6325
|
+
globalIndex,
|
|
6326
|
+
permalink,
|
|
6327
|
+
feed: normalizedFeed,
|
|
6328
|
+
feedUrl: feedUrl(commonOptions.chainId, normalizedFeed),
|
|
6329
|
+
sender: senderAddress,
|
|
6330
|
+
senderProfileUrl: profileUrl(commonOptions.chainId, senderAddress),
|
|
6331
|
+
text: fullMessage
|
|
6332
|
+
});
|
|
6333
|
+
return;
|
|
6334
|
+
}
|
|
6148
6335
|
const displayText = options.body ? `${message} (+ body)` : message;
|
|
6149
|
-
const
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
Text: ${displayText}`
|
|
6157
|
-
|
|
6158
|
-
);
|
|
6336
|
+
const lines = [
|
|
6337
|
+
`Message posted successfully!`,
|
|
6338
|
+
` Transaction: ${hash}`,
|
|
6339
|
+
` Feed: ${normalizedFeed}`
|
|
6340
|
+
];
|
|
6341
|
+
if (postId) lines.push(` Post ID: ${postId}`);
|
|
6342
|
+
if (permalink) lines.push(` Permalink: ${permalink}`);
|
|
6343
|
+
lines.push(` Text: ${displayText}`);
|
|
6344
|
+
console.log(chalk4.green(lines.join("\n")));
|
|
6159
6345
|
} catch (error) {
|
|
6160
6346
|
exitWithError(
|
|
6161
6347
|
`Failed to post message: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -6170,7 +6356,10 @@ function registerFeedPostCommand(parent) {
|
|
|
6170
6356
|
).option("--rpc-url <url>", "Custom RPC URL").option("--private-key <key>", "Private key (0x-prefixed)").option(
|
|
6171
6357
|
"--encode-only",
|
|
6172
6358
|
"Output transaction data as JSON instead of executing"
|
|
6173
|
-
).option("--data <data>", "Optional data to attach to the post").option("--body <text>", "Post body (message becomes the title)").
|
|
6359
|
+
).option("--data <data>", "Optional data to attach to the post").option("--body <text>", "Post body (message becomes the title)").option(
|
|
6360
|
+
"--json",
|
|
6361
|
+
"Output structured JSON (includes permalink and other URLs) after submission"
|
|
6362
|
+
).action(async (feed, message, options) => {
|
|
6174
6363
|
await executeFeedPost(feed, message, options);
|
|
6175
6364
|
});
|
|
6176
6365
|
}
|
|
@@ -6199,11 +6388,6 @@ function parsePostId(postId) {
|
|
|
6199
6388
|
timestamp
|
|
6200
6389
|
};
|
|
6201
6390
|
}
|
|
6202
|
-
function findPostByParsedId(posts, parsedId) {
|
|
6203
|
-
return posts.find(
|
|
6204
|
-
(p) => p.sender.toLowerCase() === parsedId.sender.toLowerCase() && p.timestamp === parsedId.timestamp
|
|
6205
|
-
);
|
|
6206
|
-
}
|
|
6207
6391
|
|
|
6208
6392
|
// src/commands/feed/comment-write.ts
|
|
6209
6393
|
var MAX_MESSAGE_LENGTH2 = 4e3;
|
|
@@ -6236,17 +6420,20 @@ async function executeFeedCommentWrite(feed, postId, message, options) {
|
|
|
6236
6420
|
`Feed "${normalizedFeed}" has no posts. Cannot find post ${postId}.`
|
|
6237
6421
|
);
|
|
6238
6422
|
}
|
|
6239
|
-
const
|
|
6423
|
+
const fetched = await client.getFeedPostsWithIndex({
|
|
6240
6424
|
topic: normalizedFeed,
|
|
6241
6425
|
maxPosts: 100
|
|
6242
|
-
// Fetch enough to find the post
|
|
6243
6426
|
});
|
|
6244
|
-
const
|
|
6427
|
+
const matchOffset = fetched.messages.findIndex(
|
|
6428
|
+
(p) => p.sender.toLowerCase() === parsedId.sender.toLowerCase() && p.timestamp === parsedId.timestamp
|
|
6429
|
+
);
|
|
6430
|
+
const targetPost = matchOffset >= 0 ? fetched.messages[matchOffset] : void 0;
|
|
6245
6431
|
if (!targetPost) {
|
|
6246
6432
|
exitWithError(
|
|
6247
6433
|
`Post not found with ID ${postId} in feed "${normalizedFeed}". Make sure the sender and timestamp are correct.`
|
|
6248
6434
|
);
|
|
6249
6435
|
}
|
|
6436
|
+
const parentTopicIndex = fetched.startIndex + matchOffset;
|
|
6250
6437
|
const txConfig = client.prepareComment({
|
|
6251
6438
|
post: targetPost,
|
|
6252
6439
|
text: message
|
|
@@ -6270,26 +6457,81 @@ async function executeFeedCommentWrite(feed, postId, message, options) {
|
|
|
6270
6457
|
commonOptions.chainId,
|
|
6271
6458
|
commonOptions.rpcUrl
|
|
6272
6459
|
);
|
|
6273
|
-
|
|
6460
|
+
if (!options.json) {
|
|
6461
|
+
console.log(chalk4.blue(`Commenting on post ${postId}...`));
|
|
6462
|
+
}
|
|
6274
6463
|
try {
|
|
6275
6464
|
const hash = await executeTransaction(walletClient, txConfig);
|
|
6465
|
+
const senderAddress = walletClient.account.address;
|
|
6466
|
+
let globalIndex;
|
|
6467
|
+
try {
|
|
6468
|
+
const indices = await getMessageIndicesFromTx({
|
|
6469
|
+
chainId: commonOptions.chainId,
|
|
6470
|
+
rpcUrl: commonOptions.rpcUrl,
|
|
6471
|
+
txHash: hash
|
|
6472
|
+
});
|
|
6473
|
+
globalIndex = indices[0];
|
|
6474
|
+
} catch {
|
|
6475
|
+
}
|
|
6476
|
+
let commentTimestamp;
|
|
6477
|
+
if (globalIndex !== void 0) {
|
|
6478
|
+
try {
|
|
6479
|
+
const netClient = createNetClient(commonOptions);
|
|
6480
|
+
const fetchedComment = await netClient.getMessageAtIndex({
|
|
6481
|
+
messageIndex: globalIndex
|
|
6482
|
+
});
|
|
6483
|
+
if (fetchedComment) {
|
|
6484
|
+
commentTimestamp = Number(fetchedComment.timestamp);
|
|
6485
|
+
}
|
|
6486
|
+
} catch {
|
|
6487
|
+
}
|
|
6488
|
+
}
|
|
6276
6489
|
addHistoryEntry({
|
|
6277
6490
|
type: "comment",
|
|
6278
6491
|
txHash: hash,
|
|
6279
6492
|
chainId: commonOptions.chainId,
|
|
6280
6493
|
feed: normalizedFeed,
|
|
6281
|
-
sender:
|
|
6494
|
+
sender: senderAddress,
|
|
6282
6495
|
text: message,
|
|
6283
6496
|
postId
|
|
6284
6497
|
});
|
|
6285
|
-
|
|
6286
|
-
|
|
6287
|
-
|
|
6288
|
-
|
|
6289
|
-
|
|
6290
|
-
|
|
6291
|
-
|
|
6292
|
-
|
|
6498
|
+
const parentPostUrl = postPermalink(commonOptions.chainId, {
|
|
6499
|
+
topic: normalizedFeed,
|
|
6500
|
+
topicIndex: parentTopicIndex
|
|
6501
|
+
});
|
|
6502
|
+
const commentPermalink = commentTimestamp !== void 0 ? postPermalink(commonOptions.chainId, {
|
|
6503
|
+
topic: normalizedFeed,
|
|
6504
|
+
topicIndex: parentTopicIndex,
|
|
6505
|
+
commentId: `${senderAddress}-${commentTimestamp}`
|
|
6506
|
+
}) : postPermalink(commonOptions.chainId, { globalIndex });
|
|
6507
|
+
if (options.json) {
|
|
6508
|
+
printJson({
|
|
6509
|
+
success: true,
|
|
6510
|
+
txHash: hash,
|
|
6511
|
+
explorerTxUrl: explorerTxUrl(commonOptions.chainId, hash),
|
|
6512
|
+
globalIndex,
|
|
6513
|
+
permalink: commentPermalink,
|
|
6514
|
+
parentPostId: postId,
|
|
6515
|
+
parentPostUrl,
|
|
6516
|
+
feed: normalizedFeed,
|
|
6517
|
+
feedUrl: feedUrl(commonOptions.chainId, normalizedFeed),
|
|
6518
|
+
sender: senderAddress,
|
|
6519
|
+
senderProfileUrl: profileUrl(commonOptions.chainId, senderAddress),
|
|
6520
|
+
text: message,
|
|
6521
|
+
...commentTimestamp !== void 0 && {
|
|
6522
|
+
commentId: `${senderAddress}:${commentTimestamp}`
|
|
6523
|
+
}
|
|
6524
|
+
});
|
|
6525
|
+
return;
|
|
6526
|
+
}
|
|
6527
|
+
const lines = [
|
|
6528
|
+
`Comment posted successfully!`,
|
|
6529
|
+
` Transaction: ${hash}`,
|
|
6530
|
+
` Post: ${postId}`
|
|
6531
|
+
];
|
|
6532
|
+
if (commentPermalink) lines.push(` Permalink: ${commentPermalink}`);
|
|
6533
|
+
lines.push(` Comment: ${message}`);
|
|
6534
|
+
console.log(chalk4.green(lines.join("\n")));
|
|
6293
6535
|
} catch (error) {
|
|
6294
6536
|
exitWithError(
|
|
6295
6537
|
`Failed to post comment: ${error instanceof Error ? error.message : String(error)}`
|
|
@@ -6306,6 +6548,9 @@ function registerFeedCommentWriteCommand(parent) {
|
|
|
6306
6548
|
).option("--rpc-url <url>", "Custom RPC URL").option("--private-key <key>", "Private key (0x-prefixed)").option(
|
|
6307
6549
|
"--encode-only",
|
|
6308
6550
|
"Output transaction data as JSON instead of executing"
|
|
6551
|
+
).option(
|
|
6552
|
+
"--json",
|
|
6553
|
+
"Output structured JSON (includes permalink and other URLs) after submission"
|
|
6309
6554
|
).action(async (feed, postId, message, options) => {
|
|
6310
6555
|
await executeFeedCommentWrite(feed, postId, message, options);
|
|
6311
6556
|
});
|
|
@@ -6332,17 +6577,25 @@ async function executeFeedCommentRead(feed, postId, options) {
|
|
|
6332
6577
|
`Feed "${normalizedFeed}" has no posts. Cannot find post ${postId}.`
|
|
6333
6578
|
);
|
|
6334
6579
|
}
|
|
6335
|
-
const
|
|
6580
|
+
const fetched = await client.getFeedPostsWithIndex({
|
|
6336
6581
|
topic: normalizedFeed,
|
|
6337
6582
|
maxPosts: 100
|
|
6338
6583
|
// Fetch enough to find the post
|
|
6339
6584
|
});
|
|
6340
|
-
const
|
|
6585
|
+
const matchIndex = fetched.messages.findIndex(
|
|
6586
|
+
(p) => p.sender.toLowerCase() === parsedId.sender.toLowerCase() && p.timestamp === parsedId.timestamp
|
|
6587
|
+
);
|
|
6588
|
+
const targetPost = matchIndex >= 0 ? fetched.messages[matchIndex] : void 0;
|
|
6341
6589
|
if (!targetPost) {
|
|
6342
6590
|
exitWithError(
|
|
6343
6591
|
`Post not found with ID ${postId} in feed "${normalizedFeed}". Make sure the sender and timestamp are correct.`
|
|
6344
6592
|
);
|
|
6345
6593
|
}
|
|
6594
|
+
const parentTopicIndex = fetched.startIndex + matchIndex;
|
|
6595
|
+
const parentPostUrl = postPermalink(readOnlyOptions.chainId, {
|
|
6596
|
+
topic: normalizedFeed,
|
|
6597
|
+
topicIndex: parentTopicIndex
|
|
6598
|
+
});
|
|
6346
6599
|
const commentCount = await client.getCommentCount(targetPost);
|
|
6347
6600
|
if (commentCount === 0) {
|
|
6348
6601
|
if (options.json) {
|
|
@@ -6363,7 +6616,11 @@ async function executeFeedCommentRead(feed, postId, options) {
|
|
|
6363
6616
|
if (options.json) {
|
|
6364
6617
|
printJson(
|
|
6365
6618
|
commentsWithDepth.map(
|
|
6366
|
-
({ comment, depth }) => commentToJson(comment,
|
|
6619
|
+
({ comment, depth }) => commentToJson(comment, {
|
|
6620
|
+
chainId: readOnlyOptions.chainId,
|
|
6621
|
+
depth,
|
|
6622
|
+
parentPostUrl
|
|
6623
|
+
})
|
|
6367
6624
|
)
|
|
6368
6625
|
);
|
|
6369
6626
|
} else {
|
|
@@ -6504,8 +6761,10 @@ async function executeFeedReplies(options) {
|
|
|
6504
6761
|
rpcUrl: options.rpcUrl
|
|
6505
6762
|
});
|
|
6506
6763
|
const client = createFeedClient(readOnlyOptions);
|
|
6507
|
-
|
|
6764
|
+
if (!options.json) {
|
|
6765
|
+
console.log(chalk4.blue(`Checking replies on ${postsWithIds.length} posts...
|
|
6508
6766
|
`));
|
|
6767
|
+
}
|
|
6509
6768
|
const results = [];
|
|
6510
6769
|
for (const entry of postsWithIds) {
|
|
6511
6770
|
try {
|
|
@@ -6520,12 +6779,31 @@ async function executeFeedReplies(options) {
|
|
|
6520
6779
|
data: "0x"
|
|
6521
6780
|
};
|
|
6522
6781
|
const commentCount = await client.getCommentCount(postObj);
|
|
6782
|
+
let permalink = null;
|
|
6783
|
+
try {
|
|
6784
|
+
const indices = await getMessageIndicesFromTx({
|
|
6785
|
+
chainId: readOnlyOptions.chainId,
|
|
6786
|
+
rpcUrl: readOnlyOptions.rpcUrl,
|
|
6787
|
+
txHash: entry.txHash
|
|
6788
|
+
});
|
|
6789
|
+
if (indices[0] !== void 0) {
|
|
6790
|
+
permalink = postPermalink(readOnlyOptions.chainId, {
|
|
6791
|
+
globalIndex: indices[0]
|
|
6792
|
+
});
|
|
6793
|
+
}
|
|
6794
|
+
} catch {
|
|
6795
|
+
}
|
|
6523
6796
|
results.push({
|
|
6524
6797
|
feed: entry.feed,
|
|
6525
6798
|
postId: entry.postId,
|
|
6526
6799
|
text: entry.text ?? "",
|
|
6527
6800
|
postedAt: entry.timestamp,
|
|
6528
|
-
commentCount: Number(commentCount)
|
|
6801
|
+
commentCount: Number(commentCount),
|
|
6802
|
+
permalink,
|
|
6803
|
+
feedUrl: feedUrl(readOnlyOptions.chainId, entry.feed),
|
|
6804
|
+
senderProfileUrl: entry.sender ? profileUrl(readOnlyOptions.chainId, entry.sender) : null,
|
|
6805
|
+
explorerTxUrl: explorerTxUrl(readOnlyOptions.chainId, entry.txHash),
|
|
6806
|
+
txHash: entry.txHash
|
|
6529
6807
|
});
|
|
6530
6808
|
} catch {
|
|
6531
6809
|
}
|
|
@@ -6610,7 +6888,14 @@ async function executeFeedPosts(address, options) {
|
|
|
6610
6888
|
endIndex: count
|
|
6611
6889
|
});
|
|
6612
6890
|
if (options.json) {
|
|
6613
|
-
printJson(
|
|
6891
|
+
printJson(
|
|
6892
|
+
messages.map(
|
|
6893
|
+
(msg, i) => postToJson(msg, {
|
|
6894
|
+
chainId: readOnlyOptions.chainId,
|
|
6895
|
+
userIndex: startIndex + i
|
|
6896
|
+
})
|
|
6897
|
+
)
|
|
6898
|
+
);
|
|
6614
6899
|
} else {
|
|
6615
6900
|
console.log(
|
|
6616
6901
|
chalk4.white(`Found ${messages.length} post(s) by ${address}:
|
|
@@ -6788,11 +7073,14 @@ function historyEntryToJson(entry, index) {
|
|
|
6788
7073
|
type: entry.type,
|
|
6789
7074
|
timestamp: entry.timestamp,
|
|
6790
7075
|
txHash: entry.txHash,
|
|
7076
|
+
explorerTxUrl: explorerTxUrl(entry.chainId, entry.txHash),
|
|
6791
7077
|
chainId: entry.chainId,
|
|
6792
|
-
feed: entry.feed
|
|
7078
|
+
feed: entry.feed,
|
|
7079
|
+
feedUrl: feedUrl(entry.chainId, entry.feed)
|
|
6793
7080
|
};
|
|
6794
7081
|
if (entry.sender) {
|
|
6795
7082
|
result.sender = entry.sender;
|
|
7083
|
+
result.senderProfileUrl = profileUrl(entry.chainId, entry.sender);
|
|
6796
7084
|
}
|
|
6797
7085
|
if (entry.text) {
|
|
6798
7086
|
result.text = entry.text;
|
|
@@ -6966,7 +7254,9 @@ async function executeListAgents(options) {
|
|
|
6966
7254
|
if (options.json) {
|
|
6967
7255
|
printJson({
|
|
6968
7256
|
totalCount,
|
|
6969
|
-
agents: agents.map(
|
|
7257
|
+
agents: agents.map(
|
|
7258
|
+
(agent, i) => agentToJson(agent, i, readOnlyOptions.chainId)
|
|
7259
|
+
)
|
|
6970
7260
|
});
|
|
6971
7261
|
} else {
|
|
6972
7262
|
if (agents.length === 0) {
|
|
@@ -7025,9 +7315,13 @@ async function executeFeedVerifyClaim(txHash, options) {
|
|
|
7025
7315
|
const netClient = createNetClient(readOnlyOptions);
|
|
7026
7316
|
const existingHistory = getHistory();
|
|
7027
7317
|
if (existingHistory.some((entry) => entry.txHash === txHash)) {
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7318
|
+
if (options.json) {
|
|
7319
|
+
printJson({ alreadyRecorded: true, txHash });
|
|
7320
|
+
} else {
|
|
7321
|
+
console.log(
|
|
7322
|
+
chalk4.yellow("Transaction already recorded in history. Skipping.")
|
|
7323
|
+
);
|
|
7324
|
+
}
|
|
7031
7325
|
return;
|
|
7032
7326
|
}
|
|
7033
7327
|
const receipt = await publicClient.getTransactionReceipt({ hash: txHash }).catch(
|
|
@@ -7062,11 +7356,13 @@ async function executeFeedVerifyClaim(txHash, options) {
|
|
|
7062
7356
|
"Transaction does not contain any Net protocol messages."
|
|
7063
7357
|
);
|
|
7064
7358
|
}
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7359
|
+
if (!options.json) {
|
|
7360
|
+
console.log(
|
|
7361
|
+
chalk4.blue(
|
|
7362
|
+
`Found ${messageSentEvents.length} message(s) in transaction. Fetching details...`
|
|
7363
|
+
)
|
|
7364
|
+
);
|
|
7365
|
+
}
|
|
7070
7366
|
const messages = await Promise.all(
|
|
7071
7367
|
messageSentEvents.map(
|
|
7072
7368
|
(event) => netClient.getMessageAtIndex({
|
|
@@ -7074,41 +7370,40 @@ async function executeFeedVerifyClaim(txHash, options) {
|
|
|
7074
7370
|
})
|
|
7075
7371
|
)
|
|
7076
7372
|
);
|
|
7373
|
+
const entries = [];
|
|
7077
7374
|
let recorded = 0;
|
|
7078
7375
|
for (let i = 0; i < messages.length; i++) {
|
|
7079
7376
|
const message = messages[i];
|
|
7080
7377
|
if (!message) {
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
|
|
7085
|
-
|
|
7378
|
+
if (!options.json) {
|
|
7379
|
+
console.log(
|
|
7380
|
+
chalk4.yellow(
|
|
7381
|
+
` Could not fetch message at index ${messageSentEvents[i].messageIndex}. Skipping.`
|
|
7382
|
+
)
|
|
7383
|
+
);
|
|
7384
|
+
}
|
|
7086
7385
|
continue;
|
|
7087
7386
|
}
|
|
7387
|
+
const globalIndex = Number(messageSentEvents[i].messageIndex);
|
|
7088
7388
|
const feedName = extractFeedName(message.topic);
|
|
7089
7389
|
const isComment = isCommentTopic(message.topic);
|
|
7090
7390
|
let type;
|
|
7091
7391
|
let postId;
|
|
7092
|
-
let
|
|
7392
|
+
let parentPostId;
|
|
7393
|
+
let permalink = null;
|
|
7093
7394
|
if (isComment) {
|
|
7094
7395
|
type = "comment";
|
|
7095
7396
|
const commentData = parseCommentData(message.data);
|
|
7096
|
-
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7101
|
-
|
|
7102
|
-
Tx: ${txHash}`;
|
|
7397
|
+
parentPostId = commentData ? `${commentData.parentSender}:${commentData.parentTimestamp}` : void 0;
|
|
7398
|
+
const commentParam = `${message.sender}-${Number(message.timestamp)}`;
|
|
7399
|
+
permalink = postPermalink(readOnlyOptions.chainId, {
|
|
7400
|
+
globalIndex,
|
|
7401
|
+
commentId: commentParam
|
|
7402
|
+
});
|
|
7103
7403
|
} else {
|
|
7104
7404
|
type = "post";
|
|
7105
7405
|
postId = createPostId(message);
|
|
7106
|
-
|
|
7107
|
-
Feed: ${feedName}
|
|
7108
|
-
Sender: ${message.sender}
|
|
7109
|
-
Text: ${message.text}
|
|
7110
|
-
Post ID: ${postId}
|
|
7111
|
-
Tx: ${txHash}`;
|
|
7406
|
+
permalink = postPermalink(readOnlyOptions.chainId, { globalIndex });
|
|
7112
7407
|
}
|
|
7113
7408
|
addHistoryEntry({
|
|
7114
7409
|
type,
|
|
@@ -7117,11 +7412,49 @@ async function executeFeedVerifyClaim(txHash, options) {
|
|
|
7117
7412
|
feed: feedName,
|
|
7118
7413
|
sender: message.sender,
|
|
7119
7414
|
text: message.text,
|
|
7120
|
-
postId
|
|
7415
|
+
postId: type === "comment" ? parentPostId : postId
|
|
7121
7416
|
});
|
|
7122
|
-
|
|
7417
|
+
const entry = {
|
|
7418
|
+
type,
|
|
7419
|
+
txHash,
|
|
7420
|
+
explorerTxUrl: explorerTxUrl(readOnlyOptions.chainId, txHash),
|
|
7421
|
+
globalIndex,
|
|
7422
|
+
permalink,
|
|
7423
|
+
feed: feedName,
|
|
7424
|
+
feedUrl: feedUrl(readOnlyOptions.chainId, feedName),
|
|
7425
|
+
sender: message.sender,
|
|
7426
|
+
senderProfileUrl: profileUrl(
|
|
7427
|
+
readOnlyOptions.chainId,
|
|
7428
|
+
message.sender
|
|
7429
|
+
),
|
|
7430
|
+
text: message.text,
|
|
7431
|
+
timestamp: Number(message.timestamp)
|
|
7432
|
+
};
|
|
7433
|
+
if (type === "post") entry.postId = postId;
|
|
7434
|
+
if (type === "comment") entry.parentPostId = parentPostId;
|
|
7435
|
+
entries.push(entry);
|
|
7436
|
+
if (!options.json) {
|
|
7437
|
+
const label = type === "comment" ? `Verified comment:
|
|
7438
|
+
Feed: ${feedName}
|
|
7439
|
+
Sender: ${message.sender}
|
|
7440
|
+
Text: ${message.text}
|
|
7441
|
+
Parent post: ${parentPostId ?? "unknown"}
|
|
7442
|
+
Permalink: ${permalink ?? "(unavailable)"}
|
|
7443
|
+
Tx: ${txHash}` : `Verified post:
|
|
7444
|
+
Feed: ${feedName}
|
|
7445
|
+
Sender: ${message.sender}
|
|
7446
|
+
Text: ${message.text}
|
|
7447
|
+
Post ID: ${postId}
|
|
7448
|
+
Permalink: ${permalink ?? "(unavailable)"}
|
|
7449
|
+
Tx: ${txHash}`;
|
|
7450
|
+
console.log(chalk4.green(` ${label}`));
|
|
7451
|
+
}
|
|
7123
7452
|
recorded++;
|
|
7124
7453
|
}
|
|
7454
|
+
if (options.json) {
|
|
7455
|
+
printJson({ recorded, entries });
|
|
7456
|
+
return;
|
|
7457
|
+
}
|
|
7125
7458
|
if (recorded > 0) {
|
|
7126
7459
|
console.log(
|
|
7127
7460
|
chalk4.green(`
|
|
@@ -7136,7 +7469,10 @@ function registerFeedVerifyClaimCommand(parent) {
|
|
|
7136
7469
|
"--chain-id <id>",
|
|
7137
7470
|
"Chain ID (default: 8453 for Base)",
|
|
7138
7471
|
(value) => parseInt(value, 10)
|
|
7139
|
-
).option("--rpc-url <url>", "Custom RPC URL").
|
|
7472
|
+
).option("--rpc-url <url>", "Custom RPC URL").option(
|
|
7473
|
+
"--json",
|
|
7474
|
+
"Output structured JSON (includes permalink and other URLs)"
|
|
7475
|
+
).action(async (txHash, options) => {
|
|
7140
7476
|
await executeFeedVerifyClaim(txHash, options);
|
|
7141
7477
|
});
|
|
7142
7478
|
}
|
|
@@ -7332,6 +7668,7 @@ async function executeGetUpvotes(options) {
|
|
|
7332
7668
|
JSON.stringify(
|
|
7333
7669
|
{
|
|
7334
7670
|
tokenAddress,
|
|
7671
|
+
tokenUrl: tokenUrl(readOnlyOptions.chainId, tokenAddress),
|
|
7335
7672
|
scoreKey,
|
|
7336
7673
|
total,
|
|
7337
7674
|
strategies: strategyCounts.map((s) => ({
|
|
@@ -7500,6 +7837,8 @@ async function executeGetUserUpvotes(options) {
|
|
|
7500
7837
|
{
|
|
7501
7838
|
address: userAddress,
|
|
7502
7839
|
chainId: readOnlyOptions.chainId,
|
|
7840
|
+
profileUrl: profileUrl(readOnlyOptions.chainId, userAddress),
|
|
7841
|
+
walletUrl: walletUrl(readOnlyOptions.chainId, userAddress),
|
|
7503
7842
|
upvotesGiven: Number(given),
|
|
7504
7843
|
upvotesReceived: Number(received),
|
|
7505
7844
|
upvotePriceWei: upvotePrice.toString(),
|