@txtcel/mcp 0.1.2 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/index.js +288 -363
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -47867,7 +47867,6 @@ function loadWallet() {
|
|
|
47867
47867
|
var import_zorsh = __toESM(require_src2(), 1);
|
|
47868
47868
|
import { Buffer as Buffer3 } from "buffer";
|
|
47869
47869
|
var TAG_CONTENT = 1;
|
|
47870
|
-
var TAG_ALLOC = 2;
|
|
47871
47870
|
var TAG_THREAD = 3;
|
|
47872
47871
|
var TAG_SETTINGS = 5;
|
|
47873
47872
|
var TAG_ACCESS = 6;
|
|
@@ -47875,12 +47874,11 @@ var TAG_LIKES = 7;
|
|
|
47875
47874
|
var TAG_ACCESS_ENTRY = 9;
|
|
47876
47875
|
var TAG_FOLLOW_REGISTRY = 10;
|
|
47877
47876
|
var TAG_FOLLOWER_SHARD = 11;
|
|
47878
|
-
var KIND_TEXT = 0;
|
|
47879
47877
|
var ACCESS_ALLOWED = 0;
|
|
47880
47878
|
var ACCESS_DENIED = 1;
|
|
47881
47879
|
var ACCESS_FEE_EXEMPT = 2;
|
|
47882
|
-
var
|
|
47883
|
-
var CONTENT_SLOTS =
|
|
47880
|
+
var KIND_TEXT = 0;
|
|
47881
|
+
var CONTENT_SLOTS = 32;
|
|
47884
47882
|
var EXTEND_THRESHOLD = 16;
|
|
47885
47883
|
var MAX_BODY_LEN = 8192;
|
|
47886
47884
|
var MAX_TITLE_LEN = 64;
|
|
@@ -47954,9 +47952,7 @@ var ContentNodeSchema = import_zorsh.b.struct({
|
|
|
47954
47952
|
var AllocNodeSchema = import_zorsh.b.struct({
|
|
47955
47953
|
tag: import_zorsh.b.u8(),
|
|
47956
47954
|
thread: Pubkey,
|
|
47957
|
-
allocSeq: import_zorsh.b.u32()
|
|
47958
|
-
upperAllocSeq: import_zorsh.b.u32(),
|
|
47959
|
-
nextAllocSeq: import_zorsh.b.u32()
|
|
47955
|
+
allocSeq: import_zorsh.b.u32()
|
|
47960
47956
|
});
|
|
47961
47957
|
var ThreadNodeSchema = import_zorsh.b.struct({
|
|
47962
47958
|
tag: import_zorsh.b.u8(),
|
|
@@ -47993,7 +47989,7 @@ var AccessEntrySchema = import_zorsh.b.struct({
|
|
|
47993
47989
|
var AllocLikesSchema = import_zorsh.b.struct({
|
|
47994
47990
|
tag: import_zorsh.b.u8(),
|
|
47995
47991
|
allocSeq: import_zorsh.b.u32(),
|
|
47996
|
-
counts: import_zorsh.b.array(import_zorsh.b.u32(),
|
|
47992
|
+
counts: import_zorsh.b.array(import_zorsh.b.u32(), CONTENT_SLOTS)
|
|
47997
47993
|
});
|
|
47998
47994
|
var FollowRegistrySchema = import_zorsh.b.struct({
|
|
47999
47995
|
tag: import_zorsh.b.u8(),
|
|
@@ -48029,7 +48025,6 @@ var FillSlotInstr = import_zorsh.b.struct({
|
|
|
48029
48025
|
kind: import_zorsh.b.u16(),
|
|
48030
48026
|
body: import_zorsh.b.bytes(),
|
|
48031
48027
|
candidates: import_zorsh.b.vec(CandidateSlotSchema),
|
|
48032
|
-
extend: import_zorsh.b.u8(),
|
|
48033
48028
|
treasuryShardIdx: import_zorsh.b.u16(),
|
|
48034
48029
|
authorFeeShardIdx: import_zorsh.b.u8(),
|
|
48035
48030
|
replyAllocSeq: import_zorsh.b.u32(),
|
|
@@ -48083,17 +48078,6 @@ function decodeContent(pubkey, data) {
|
|
|
48083
48078
|
text: raw.kind === KIND_TEXT ? textDecoder.decode(raw.body) : ""
|
|
48084
48079
|
};
|
|
48085
48080
|
}
|
|
48086
|
-
function decodeAlloc(pubkey, data) {
|
|
48087
|
-
const raw = AllocNodeSchema.deserialize(data);
|
|
48088
|
-
if (raw.tag !== TAG_ALLOC) throw new Error("Invalid AllocNode tag");
|
|
48089
|
-
return {
|
|
48090
|
-
pubkey,
|
|
48091
|
-
seed: raw.thread,
|
|
48092
|
-
allocSeq: raw.allocSeq,
|
|
48093
|
-
upperAllocSeq: raw.upperAllocSeq === INDEX_NONE ? null : raw.upperAllocSeq,
|
|
48094
|
-
nextAllocSeq: raw.nextAllocSeq === INDEX_NONE ? null : raw.nextAllocSeq
|
|
48095
|
-
};
|
|
48096
|
-
}
|
|
48097
48081
|
var textDecoder2 = new TextDecoder();
|
|
48098
48082
|
function decodeThread(pubkey, data) {
|
|
48099
48083
|
const raw = ThreadNodeSchema.deserialize(data);
|
|
@@ -48250,47 +48234,46 @@ function randomTreasuryShard() {
|
|
|
48250
48234
|
function randomAuthorFeeShard() {
|
|
48251
48235
|
return Math.floor(Math.random() * N_AUTHOR_FEE_SHARDS);
|
|
48252
48236
|
}
|
|
48237
|
+
function assertOwnedTag(info, programId, tag, name) {
|
|
48238
|
+
if (!info.owner.equals(programId)) throw new Error(`${name} not owned by program`);
|
|
48239
|
+
if (info.data.length === 0 || info.data[0] !== tag) throw new Error(`Invalid ${name} data`);
|
|
48240
|
+
}
|
|
48241
|
+
async function fetchRequiredAccount(connection, programId, key, tag, name) {
|
|
48242
|
+
const info = await connection.getAccountInfo(key, "confirmed");
|
|
48243
|
+
if (!info) throw new Error(`${name} not found`);
|
|
48244
|
+
assertOwnedTag(info, programId, tag, name);
|
|
48245
|
+
return info;
|
|
48246
|
+
}
|
|
48247
|
+
async function fetchOptionalAccount(connection, programId, key, tag, name) {
|
|
48248
|
+
const info = await connection.getAccountInfo(key, "confirmed");
|
|
48249
|
+
if (!info) return null;
|
|
48250
|
+
assertOwnedTag(info, programId, tag, name);
|
|
48251
|
+
return info;
|
|
48252
|
+
}
|
|
48253
|
+
function isOwnedTag(info, programId, tag) {
|
|
48254
|
+
return info !== null && info.owner.equals(programId) && info.data.length > 0 && info.data[0] === tag;
|
|
48255
|
+
}
|
|
48253
48256
|
async function loadThreadNode(connection, programId, pubkey) {
|
|
48254
|
-
const info = await connection
|
|
48255
|
-
if (!info) throw new Error("ThreadNode not found");
|
|
48256
|
-
if (!info.owner.equals(programId)) throw new Error("ThreadNode not owned by program");
|
|
48257
|
-
if (info.data.length === 0 || info.data[0] !== TAG_THREAD) throw new Error("Invalid ThreadNode data");
|
|
48257
|
+
const info = await fetchRequiredAccount(connection, programId, pubkey, TAG_THREAD, "ThreadNode");
|
|
48258
48258
|
return decodeThread(pubkey.toBase58(), info.data);
|
|
48259
48259
|
}
|
|
48260
|
-
async function loadAllocNode(connection, programId, pubkey) {
|
|
48261
|
-
const info = await connection.getAccountInfo(pubkey, "confirmed");
|
|
48262
|
-
if (!info) throw new Error("AllocNode not found");
|
|
48263
|
-
if (!info.owner.equals(programId)) throw new Error("AllocNode not owned by program");
|
|
48264
|
-
if (info.data.length === 0 || info.data[0] !== TAG_ALLOC) throw new Error("Invalid AllocNode data");
|
|
48265
|
-
return decodeAlloc(pubkey.toBase58(), info.data);
|
|
48266
|
-
}
|
|
48267
48260
|
async function loadContentNode(connection, programId, pubkey) {
|
|
48268
|
-
const info = await connection
|
|
48269
|
-
if (!info) throw new Error("ContentNode not found");
|
|
48270
|
-
if (!info.owner.equals(programId)) throw new Error("ContentNode not owned by program");
|
|
48271
|
-
if (info.data.length === 0 || info.data[0] !== TAG_CONTENT) throw new Error("Invalid ContentNode data");
|
|
48261
|
+
const info = await fetchRequiredAccount(connection, programId, pubkey, TAG_CONTENT, "ContentNode");
|
|
48272
48262
|
return decodeContent(pubkey.toBase58(), info.data);
|
|
48273
48263
|
}
|
|
48274
48264
|
async function loadProgramSettings(connection, programId) {
|
|
48275
48265
|
const settingsKey = deriveSettingsPda(programId);
|
|
48276
|
-
const info = await connection
|
|
48266
|
+
const info = await fetchOptionalAccount(connection, programId, settingsKey, TAG_SETTINGS, "ProgramSettings");
|
|
48277
48267
|
if (!info) return null;
|
|
48278
|
-
if (!info.owner.equals(programId)) throw new Error("ProgramSettings not owned by program");
|
|
48279
|
-
if (info.data.length === 0 || info.data[0] !== TAG_SETTINGS) throw new Error("Invalid ProgramSettings data");
|
|
48280
48268
|
return decodeSettings(settingsKey.toBase58(), info.data);
|
|
48281
48269
|
}
|
|
48282
48270
|
async function loadThreadAccess(connection, programId, accessKey) {
|
|
48283
|
-
const info = await connection
|
|
48284
|
-
if (!info) throw new Error("ThreadAccess not found");
|
|
48285
|
-
if (!info.owner.equals(programId)) throw new Error("ThreadAccess not owned by program");
|
|
48286
|
-
if (info.data.length === 0 || info.data[0] !== TAG_ACCESS) throw new Error("Invalid ThreadAccess data");
|
|
48271
|
+
const info = await fetchRequiredAccount(connection, programId, accessKey, TAG_ACCESS, "ThreadAccess");
|
|
48287
48272
|
return decodeThreadAccess(accessKey.toBase58(), info.data);
|
|
48288
48273
|
}
|
|
48289
48274
|
async function loadAllocLikes(connection, programId, pubkey) {
|
|
48290
|
-
const info = await connection
|
|
48275
|
+
const info = await fetchOptionalAccount(connection, programId, pubkey, TAG_LIKES, "AllocLikes");
|
|
48291
48276
|
if (!info) return null;
|
|
48292
|
-
if (!info.owner.equals(programId)) throw new Error("AllocLikes not owned by program");
|
|
48293
|
-
if (info.data.length === 0 || info.data[0] !== TAG_LIKES) throw new Error("Invalid AllocLikes data");
|
|
48294
48277
|
return decodeAllocLikes(pubkey.toBase58(), info.data);
|
|
48295
48278
|
}
|
|
48296
48279
|
async function loadAccessEntries(connection, programId, seed) {
|
|
@@ -48315,10 +48298,8 @@ async function loadAccessEntries(connection, programId, seed) {
|
|
|
48315
48298
|
}
|
|
48316
48299
|
async function loadFollowRegistry(connection, programId, owner) {
|
|
48317
48300
|
const registryKey = deriveFollowRegistryPda(programId, owner);
|
|
48318
|
-
const info = await connection
|
|
48301
|
+
const info = await fetchOptionalAccount(connection, programId, registryKey, TAG_FOLLOW_REGISTRY, "FollowRegistry");
|
|
48319
48302
|
if (!info) return null;
|
|
48320
|
-
if (!info.owner.equals(programId)) throw new Error("FollowRegistry not owned by program");
|
|
48321
|
-
if (info.data.length === 0 || info.data[0] !== TAG_FOLLOW_REGISTRY) throw new Error("Invalid FollowRegistry data");
|
|
48322
48303
|
return decodeFollowRegistry(registryKey.toBase58(), info.data);
|
|
48323
48304
|
}
|
|
48324
48305
|
async function loadFollowerCount(connection, programId, seed) {
|
|
@@ -48330,8 +48311,7 @@ async function loadFollowerCount(connection, programId, seed) {
|
|
|
48330
48311
|
let total = 0n;
|
|
48331
48312
|
for (let i = 0; i < infos.length; i++) {
|
|
48332
48313
|
const info = infos[i];
|
|
48333
|
-
if (!info
|
|
48334
|
-
if (info.data.length === 0 || info.data[0] !== TAG_FOLLOWER_SHARD) continue;
|
|
48314
|
+
if (!isOwnedTag(info, programId, TAG_FOLLOWER_SHARD)) continue;
|
|
48335
48315
|
total += decodeFollowerShard(shardKeys[i].toBase58(), info.data).count;
|
|
48336
48316
|
}
|
|
48337
48317
|
return total;
|
|
@@ -48344,41 +48324,21 @@ async function loadThreadNodesBatched(connection, programId, channels) {
|
|
|
48344
48324
|
const infos = await connection.getMultipleAccountsInfo(chunk, "confirmed");
|
|
48345
48325
|
for (let j = 0; j < infos.length; j++) {
|
|
48346
48326
|
const info = infos[j];
|
|
48347
|
-
if (!info
|
|
48348
|
-
if (info.data.length === 0 || info.data[0] !== TAG_THREAD) continue;
|
|
48327
|
+
if (!isOwnedTag(info, programId, TAG_THREAD)) continue;
|
|
48349
48328
|
const key = chunk[j].toBase58();
|
|
48350
48329
|
result.set(key, decodeThread(key, info.data));
|
|
48351
48330
|
}
|
|
48352
48331
|
}
|
|
48353
48332
|
return result;
|
|
48354
48333
|
}
|
|
48355
|
-
function
|
|
48356
|
-
|
|
48357
|
-
|
|
48358
|
-
|
|
48359
|
-
}
|
|
48360
|
-
|
|
48361
|
-
|
|
48362
|
-
|
|
48363
|
-
const treasuryShardIdx = randomTreasuryShard();
|
|
48364
|
-
const treasuryShard = deriveTreasuryShardPda(programId, treasuryShardIdx);
|
|
48365
|
-
return new TransactionInstruction({
|
|
48366
|
-
programId,
|
|
48367
|
-
keys: [
|
|
48368
|
-
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
48369
|
-
{ pubkey: threadAccount, isSigner: true, isWritable: true },
|
|
48370
|
-
{ pubkey: allocAccount, isSigner: false, isWritable: true },
|
|
48371
|
-
{ pubkey: settingsAccount, isSigner: false, isWritable: false },
|
|
48372
|
-
{ pubkey: treasuryShard, isSigner: false, isWritable: true },
|
|
48373
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48374
|
-
],
|
|
48375
|
-
data: Buffer3.from(CreateRootAllocInstr.serialize({
|
|
48376
|
-
tag: Instruction.CreateRootAlloc,
|
|
48377
|
-
messageFee,
|
|
48378
|
-
treasuryShardIdx,
|
|
48379
|
-
title: titleBytes
|
|
48380
|
-
}))
|
|
48381
|
-
});
|
|
48334
|
+
function signerMeta(pubkey) {
|
|
48335
|
+
return { pubkey, isSigner: true, isWritable: true };
|
|
48336
|
+
}
|
|
48337
|
+
function writableMeta(pubkey) {
|
|
48338
|
+
return { pubkey, isSigner: false, isWritable: true };
|
|
48339
|
+
}
|
|
48340
|
+
function readonlyMeta(pubkey) {
|
|
48341
|
+
return { pubkey, isSigner: false, isWritable: false };
|
|
48382
48342
|
}
|
|
48383
48343
|
function buildFillSlotInstruction(opts) {
|
|
48384
48344
|
const {
|
|
@@ -48391,7 +48351,6 @@ function buildFillSlotInstruction(opts) {
|
|
|
48391
48351
|
bodyBytes,
|
|
48392
48352
|
kind = KIND_TEXT,
|
|
48393
48353
|
maxFee,
|
|
48394
|
-
extendInfo,
|
|
48395
48354
|
replyAllocSeq: replyAllocSeqRaw,
|
|
48396
48355
|
replySlot: replySlotRaw
|
|
48397
48356
|
} = opts;
|
|
@@ -48402,22 +48361,18 @@ function buildFillSlotInstruction(opts) {
|
|
|
48402
48361
|
const accessAccount = deriveAccessPda(programId, seed);
|
|
48403
48362
|
const entryAccount = deriveAccessEntryPda(programId, seed, payer);
|
|
48404
48363
|
const keys = [
|
|
48405
|
-
|
|
48406
|
-
|
|
48407
|
-
|
|
48408
|
-
|
|
48409
|
-
|
|
48410
|
-
|
|
48364
|
+
signerMeta(payer),
|
|
48365
|
+
readonlyMeta(threadAccount),
|
|
48366
|
+
readonlyMeta(settingsAccount),
|
|
48367
|
+
writableMeta(treasuryShard),
|
|
48368
|
+
writableMeta(authorFeeShard),
|
|
48369
|
+
readonlyMeta(SystemProgram.programId)
|
|
48411
48370
|
];
|
|
48412
|
-
for (const
|
|
48413
|
-
keys.push(
|
|
48414
|
-
}
|
|
48415
|
-
keys.push({ pubkey: accessAccount, isSigner: false, isWritable: false });
|
|
48416
|
-
keys.push({ pubkey: entryAccount, isSigner: false, isWritable: false });
|
|
48417
|
-
if (extendInfo) {
|
|
48418
|
-
keys.push({ pubkey: extendInfo.currentAllocPda, isSigner: false, isWritable: true });
|
|
48419
|
-
keys.push({ pubkey: extendInfo.newAllocPda, isSigner: false, isWritable: true });
|
|
48371
|
+
for (const candidate of candidates) {
|
|
48372
|
+
keys.push(writableMeta(candidate.pda));
|
|
48420
48373
|
}
|
|
48374
|
+
keys.push(readonlyMeta(accessAccount));
|
|
48375
|
+
keys.push(readonlyMeta(entryAccount));
|
|
48421
48376
|
return new TransactionInstruction({
|
|
48422
48377
|
programId,
|
|
48423
48378
|
keys,
|
|
@@ -48425,8 +48380,7 @@ function buildFillSlotInstruction(opts) {
|
|
|
48425
48380
|
tag: Instruction.FillSlot,
|
|
48426
48381
|
kind,
|
|
48427
48382
|
body: bodyBytes,
|
|
48428
|
-
candidates: candidates.map((
|
|
48429
|
-
extend: extendInfo ? 1 : 0,
|
|
48383
|
+
candidates: candidates.map((candidate) => ({ allocSeq: candidate.allocSeq, slot: candidate.slot })),
|
|
48430
48384
|
treasuryShardIdx,
|
|
48431
48385
|
authorFeeShardIdx,
|
|
48432
48386
|
replyAllocSeq: replyAllocSeqRaw ?? INDEX_NONE,
|
|
@@ -48435,17 +48389,36 @@ function buildFillSlotInstruction(opts) {
|
|
|
48435
48389
|
}))
|
|
48436
48390
|
});
|
|
48437
48391
|
}
|
|
48392
|
+
function buildPrepareAllocInstruction(programId, payer, seed, allocSeq) {
|
|
48393
|
+
const currentAllocPda = deriveAllocPda(programId, seed, allocSeq);
|
|
48394
|
+
const newAllocPda = deriveAllocPda(programId, seed, allocSeq + 1);
|
|
48395
|
+
const threadAccount = deriveThreadPda(programId, seed);
|
|
48396
|
+
return new TransactionInstruction({
|
|
48397
|
+
programId,
|
|
48398
|
+
keys: [
|
|
48399
|
+
signerMeta(payer),
|
|
48400
|
+
writableMeta(currentAllocPda),
|
|
48401
|
+
writableMeta(newAllocPda),
|
|
48402
|
+
writableMeta(threadAccount),
|
|
48403
|
+
readonlyMeta(SystemProgram.programId)
|
|
48404
|
+
],
|
|
48405
|
+
data: Buffer3.from(PrepareAllocInstr.serialize({
|
|
48406
|
+
tag: Instruction.PrepareAlloc,
|
|
48407
|
+
allocSeq
|
|
48408
|
+
}))
|
|
48409
|
+
});
|
|
48410
|
+
}
|
|
48438
48411
|
function buildAppendContentInstruction(programId, payer, contentAccount, threadAccount, settingsAccount, treasuryShard, authorFeeShard, chunk, treasuryShardIdx, authorFeeShardIdx) {
|
|
48439
48412
|
return new TransactionInstruction({
|
|
48440
48413
|
programId,
|
|
48441
48414
|
keys: [
|
|
48442
|
-
|
|
48443
|
-
|
|
48444
|
-
|
|
48445
|
-
|
|
48446
|
-
|
|
48447
|
-
|
|
48448
|
-
|
|
48415
|
+
signerMeta(payer),
|
|
48416
|
+
writableMeta(contentAccount),
|
|
48417
|
+
readonlyMeta(threadAccount),
|
|
48418
|
+
readonlyMeta(settingsAccount),
|
|
48419
|
+
writableMeta(treasuryShard),
|
|
48420
|
+
writableMeta(authorFeeShard),
|
|
48421
|
+
readonlyMeta(SystemProgram.programId)
|
|
48449
48422
|
],
|
|
48450
48423
|
data: Buffer3.from(AppendContentInstr.serialize({
|
|
48451
48424
|
tag: Instruction.AppendContent,
|
|
@@ -48455,6 +48428,18 @@ function buildAppendContentInstruction(programId, payer, contentAccount, threadA
|
|
|
48455
48428
|
}))
|
|
48456
48429
|
});
|
|
48457
48430
|
}
|
|
48431
|
+
var TX_SIZE_LIMIT = 1232;
|
|
48432
|
+
var TX_OVERHEAD = 1 + 64 + 3 + 32;
|
|
48433
|
+
var FILL_SLOT_FIXED_OVERHEAD = 1 + 2 + 4 + 4 + 2 + 1 + 4 + 1 + 8;
|
|
48434
|
+
var CANDIDATE_SIZE = 4 + 1;
|
|
48435
|
+
var ACCOUNT_KEY_SIZE = 32;
|
|
48436
|
+
var FILL_SLOT_BASE_ACCOUNTS = 6;
|
|
48437
|
+
var FILL_SLOT_ACCESS_ACCOUNTS = 2;
|
|
48438
|
+
var PREPARE_ALLOC_MARGINAL_SIZE = 2 * ACCOUNT_KEY_SIZE + 1 + 1 + 5 + 1 + (1 + 4);
|
|
48439
|
+
var CONTENT_NODE_FIXED_SIZE = 89;
|
|
48440
|
+
var MAX_FEE_SLIPPAGE_NUM = 2n;
|
|
48441
|
+
var APPEND_INSTR_ACCOUNTS = 7;
|
|
48442
|
+
var APPEND_TX_OVERHEAD = TX_OVERHEAD + 1 + (APPEND_INSTR_ACCOUNTS + 1) * ACCOUNT_KEY_SIZE + 1 + 1 + 1 + APPEND_INSTR_ACCOUNTS + 2 + 1 + 4 + 2 + 1;
|
|
48458
48443
|
function ensureTextBytes(text) {
|
|
48459
48444
|
const bytes = new TextEncoder().encode(text);
|
|
48460
48445
|
if (bytes.length === 0) {
|
|
@@ -48473,74 +48458,41 @@ function shuffle(arr) {
|
|
|
48473
48458
|
}
|
|
48474
48459
|
return result;
|
|
48475
48460
|
}
|
|
48476
|
-
|
|
48477
|
-
|
|
48478
|
-
var FILL_SLOT_FIXED_OVERHEAD = 1 + 2 + 4 + 4 + 1 + 2 + 1 + 4 + 1 + 8;
|
|
48479
|
-
var CANDIDATE_SIZE = 4 + 1;
|
|
48480
|
-
var ACCOUNT_KEY_SIZE = 32;
|
|
48481
|
-
var FILL_SLOT_BASE_ACCOUNTS = 6;
|
|
48482
|
-
var FILL_SLOT_ACCESS_ACCOUNTS = 2;
|
|
48483
|
-
var CONTENT_NODE_FIXED_SIZE = 89;
|
|
48484
|
-
var MAX_FEE_SLIPPAGE_NUM = 2n;
|
|
48485
|
-
var APPEND_INSTR_ACCOUNTS = 7;
|
|
48486
|
-
var APPEND_TX_OVERHEAD = TX_OVERHEAD + 1 + (APPEND_INSTR_ACCOUNTS + 1) * ACCOUNT_KEY_SIZE + 1 + 1 + 1 + APPEND_INSTR_ACCOUNTS + 2 + 1 + 4 + 2 + 1;
|
|
48487
|
-
function estimateFillSlotTxSize(nCandidates, hasExtend, textLen) {
|
|
48488
|
-
const nAccounts = FILL_SLOT_BASE_ACCOUNTS + nCandidates + FILL_SLOT_ACCESS_ACCOUNTS + (hasExtend ? 2 : 0);
|
|
48461
|
+
function estimateFillSlotTxSize(nCandidates, textLen) {
|
|
48462
|
+
const nAccounts = FILL_SLOT_BASE_ACCOUNTS + nCandidates + FILL_SLOT_ACCESS_ACCOUNTS;
|
|
48489
48463
|
const accountsSize = 1 + (nAccounts + 1) * ACCOUNT_KEY_SIZE;
|
|
48490
48464
|
const instrDataSize = FILL_SLOT_FIXED_OVERHEAD + textLen + nCandidates * CANDIDATE_SIZE;
|
|
48491
48465
|
const instrOverhead = 1 + 1 + 1 + nAccounts + 2;
|
|
48492
48466
|
return TX_OVERHEAD + accountsSize + instrOverhead + instrDataSize;
|
|
48493
48467
|
}
|
|
48494
|
-
function maxFillSlotTextLen(nCandidates,
|
|
48495
|
-
const withoutText = estimateFillSlotTxSize(nCandidates,
|
|
48496
|
-
return TX_SIZE_LIMIT - withoutText;
|
|
48468
|
+
function maxFillSlotTextLen(nCandidates, reserve = 0) {
|
|
48469
|
+
const withoutText = estimateFillSlotTxSize(nCandidates, 0);
|
|
48470
|
+
return TX_SIZE_LIMIT - withoutText - reserve;
|
|
48497
48471
|
}
|
|
48498
48472
|
function maxAppendChunkLen() {
|
|
48499
48473
|
return TX_SIZE_LIMIT - APPEND_TX_OVERHEAD;
|
|
48500
48474
|
}
|
|
48475
|
+
function pageCandidates(programId, seed, allocSeq) {
|
|
48476
|
+
return Array.from({ length: CONTENT_SLOTS }, (_, slot) => ({
|
|
48477
|
+
pda: deriveContentPda(programId, seed, allocSeq, slot),
|
|
48478
|
+
allocSeq,
|
|
48479
|
+
slot
|
|
48480
|
+
}));
|
|
48481
|
+
}
|
|
48501
48482
|
async function buildSendMessageTransactions(connection, programId, payerKey, seed, text, replyTo) {
|
|
48502
48483
|
const textBytes = ensureTextBytes(text);
|
|
48503
48484
|
const threadPda = deriveThreadPda(programId, seed);
|
|
48504
48485
|
const thread = await loadThreadNode(connection, programId, threadPda);
|
|
48505
48486
|
const lastAllocSeq = thread.lastAllocSeq;
|
|
48506
|
-
const
|
|
48507
|
-
const
|
|
48508
|
-
const
|
|
48509
|
-
pda: deriveContentPda(programId, seed, lastAllocSeq, slot),
|
|
48510
|
-
allocSeq: lastAllocSeq,
|
|
48511
|
-
slot
|
|
48512
|
-
}));
|
|
48513
|
-
const lastInfos = await connection.getMultipleAccountsInfo(
|
|
48514
|
-
lastAllocCandidates.map((c) => c.pda)
|
|
48515
|
-
);
|
|
48516
|
-
const freeInLast = lastAllocCandidates.filter((_, i) => lastInfos[i] === null);
|
|
48517
|
-
let freeInNext = [];
|
|
48518
|
-
if (freeInLast.length < DESIRED_CANDIDATES && lastAlloc.nextAllocSeq !== null) {
|
|
48519
|
-
const nextSeq = lastAlloc.nextAllocSeq;
|
|
48520
|
-
const nextAllocCandidates = Array.from({ length: CONTENT_SLOTS }, (_, slot) => ({
|
|
48521
|
-
pda: deriveContentPda(programId, seed, nextSeq, slot),
|
|
48522
|
-
allocSeq: nextSeq,
|
|
48523
|
-
slot
|
|
48524
|
-
}));
|
|
48525
|
-
const nextInfos = await connection.getMultipleAccountsInfo(
|
|
48526
|
-
nextAllocCandidates.map((c) => c.pda)
|
|
48527
|
-
);
|
|
48528
|
-
freeInNext = nextAllocCandidates.filter((_, i) => nextInfos[i] === null);
|
|
48529
|
-
}
|
|
48530
|
-
const allFree = [...freeInLast, ...freeInNext];
|
|
48531
|
-
if (allFree.length === 0) throw new Error("No free slots in thread");
|
|
48532
|
-
const selected = shuffle(allFree).slice(0, DESIRED_CANDIDATES);
|
|
48487
|
+
const windowCandidates = lastAllocSeq >= 1 ? [...pageCandidates(programId, seed, lastAllocSeq - 1), ...pageCandidates(programId, seed, lastAllocSeq)] : pageCandidates(programId, seed, lastAllocSeq);
|
|
48488
|
+
const windowInfos = await connection.getMultipleAccountsInfo(windowCandidates.map((c) => c.pda));
|
|
48489
|
+
const freeInWindow = windowCandidates.filter((_, i) => windowInfos[i] === null);
|
|
48533
48490
|
const treasuryShardIdx = randomTreasuryShard();
|
|
48534
48491
|
const authorFeeShardIdx = randomAuthorFeeShard();
|
|
48535
|
-
const
|
|
48536
|
-
|
|
48537
|
-
|
|
48538
|
-
|
|
48539
|
-
currentAllocPda: lastAllocPda,
|
|
48540
|
-
newAllocPda: deriveAllocPda(programId, seed, lastAllocSeq + 1)
|
|
48541
|
-
};
|
|
48542
|
-
}
|
|
48543
|
-
const maxFirst = maxFillSlotTextLen(selected.length, !!extendInfo);
|
|
48492
|
+
const extendInline = freeInWindow.length === 0;
|
|
48493
|
+
const selected = extendInline ? pageCandidates(programId, seed, lastAllocSeq + 1).slice(0, DESIRED_CANDIDATES) : shuffle(freeInWindow).slice(0, DESIRED_CANDIDATES);
|
|
48494
|
+
const reserve = extendInline ? PREPARE_ALLOC_MARGINAL_SIZE : 0;
|
|
48495
|
+
const maxFirst = maxFillSlotTextLen(selected.length, reserve);
|
|
48544
48496
|
const firstChunkLen = Math.min(textBytes.length, maxFirst);
|
|
48545
48497
|
const firstChunk = textBytes.subarray(0, firstChunkLen);
|
|
48546
48498
|
const settings = await loadProgramSettings(connection, programId);
|
|
@@ -48560,16 +48512,19 @@ async function buildSendMessageTransactions(connection, programId, payerKey, see
|
|
|
48560
48512
|
authorFeeShardIdx,
|
|
48561
48513
|
bodyBytes: firstChunk,
|
|
48562
48514
|
maxFee,
|
|
48563
|
-
extendInfo,
|
|
48564
48515
|
replyAllocSeq: replyTo?.allocSeq ?? null,
|
|
48565
48516
|
replySlot: replyTo?.slot ?? null
|
|
48566
48517
|
});
|
|
48567
|
-
const
|
|
48518
|
+
const firstTx = new Transaction();
|
|
48519
|
+
if (extendInline) {
|
|
48520
|
+
firstTx.add(buildPrepareAllocInstruction(programId, payerKey, seed, lastAllocSeq));
|
|
48521
|
+
}
|
|
48522
|
+
firstTx.add(fillSlotIx);
|
|
48523
|
+
const transactions = [firstTx];
|
|
48568
48524
|
if (firstChunkLen < textBytes.length) {
|
|
48569
48525
|
const remaining = textBytes.subarray(firstChunkLen);
|
|
48570
48526
|
const appendMax = maxAppendChunkLen();
|
|
48571
48527
|
const contentPda = selected[0].pda;
|
|
48572
|
-
const threadPda2 = deriveThreadPda(programId, seed);
|
|
48573
48528
|
const settingsPda = deriveSettingsPda(programId);
|
|
48574
48529
|
const treasuryShardPda = deriveTreasuryShardPda(programId, treasuryShardIdx);
|
|
48575
48530
|
const authorFeeShardPda = deriveAuthorFeePda(programId, seed, authorFeeShardIdx);
|
|
@@ -48579,7 +48534,7 @@ async function buildSendMessageTransactions(connection, programId, payerKey, see
|
|
|
48579
48534
|
programId,
|
|
48580
48535
|
payerKey,
|
|
48581
48536
|
contentPda,
|
|
48582
|
-
|
|
48537
|
+
threadPda,
|
|
48583
48538
|
settingsPda,
|
|
48584
48539
|
treasuryShardPda,
|
|
48585
48540
|
authorFeeShardPda,
|
|
@@ -48592,6 +48547,45 @@ async function buildSendMessageTransactions(connection, programId, payerKey, see
|
|
|
48592
48547
|
}
|
|
48593
48548
|
return transactions;
|
|
48594
48549
|
}
|
|
48550
|
+
async function buildExtendAllocTransaction(connection, programId, payerKey, seed) {
|
|
48551
|
+
const threadPda = deriveThreadPda(programId, seed);
|
|
48552
|
+
const thread = await loadThreadNode(connection, programId, threadPda);
|
|
48553
|
+
const lastAllocSeq = thread.lastAllocSeq;
|
|
48554
|
+
const tailCandidates = pageCandidates(programId, seed, lastAllocSeq);
|
|
48555
|
+
const tailInfos = await connection.getMultipleAccountsInfo(tailCandidates.map((c) => c.pda));
|
|
48556
|
+
const freeOnPageN = tailInfos.filter((info) => info === null).length;
|
|
48557
|
+
const filled = CONTENT_SLOTS - freeOnPageN;
|
|
48558
|
+
if (filled < EXTEND_THRESHOLD) return null;
|
|
48559
|
+
return new Transaction().add(buildPrepareAllocInstruction(programId, payerKey, seed, lastAllocSeq));
|
|
48560
|
+
}
|
|
48561
|
+
function buildCreateRootAllocInstruction(programId, payer, seed, messageFee = 0n, title = "") {
|
|
48562
|
+
const titleBytes = new TextEncoder().encode(title);
|
|
48563
|
+
if (titleBytes.length > MAX_TITLE_LEN) {
|
|
48564
|
+
throw new Error(`Title is too long (max ${MAX_TITLE_LEN} bytes)`);
|
|
48565
|
+
}
|
|
48566
|
+
const threadAccount = deriveThreadPda(programId, seed);
|
|
48567
|
+
const allocAccount = deriveAllocPda(programId, seed, 0);
|
|
48568
|
+
const settingsAccount = deriveSettingsPda(programId);
|
|
48569
|
+
const treasuryShardIdx = randomTreasuryShard();
|
|
48570
|
+
const treasuryShard = deriveTreasuryShardPda(programId, treasuryShardIdx);
|
|
48571
|
+
return new TransactionInstruction({
|
|
48572
|
+
programId,
|
|
48573
|
+
keys: [
|
|
48574
|
+
signerMeta(payer),
|
|
48575
|
+
signerMeta(threadAccount),
|
|
48576
|
+
writableMeta(allocAccount),
|
|
48577
|
+
readonlyMeta(settingsAccount),
|
|
48578
|
+
writableMeta(treasuryShard),
|
|
48579
|
+
readonlyMeta(SystemProgram.programId)
|
|
48580
|
+
],
|
|
48581
|
+
data: Buffer3.from(CreateRootAllocInstr.serialize({
|
|
48582
|
+
tag: Instruction.CreateRootAlloc,
|
|
48583
|
+
messageFee,
|
|
48584
|
+
treasuryShardIdx,
|
|
48585
|
+
title: titleBytes
|
|
48586
|
+
}))
|
|
48587
|
+
});
|
|
48588
|
+
}
|
|
48595
48589
|
async function createRootAlloc(connection, programId, payer, messageFee = 0n, title = "", onSent) {
|
|
48596
48590
|
const programKey = new PublicKey(programId);
|
|
48597
48591
|
const threadKeypair = Keypair.generate();
|
|
@@ -48610,58 +48604,49 @@ async function createRootAlloc(connection, programId, payer, messageFee = 0n, ti
|
|
|
48610
48604
|
allocPda: deriveAllocPda(programKey, seed, 0).toBase58()
|
|
48611
48605
|
};
|
|
48612
48606
|
}
|
|
48613
|
-
function
|
|
48614
|
-
const currentAllocPda = deriveAllocPda(programId, seed, allocSeq);
|
|
48615
|
-
const newAllocPda = deriveAllocPda(programId, seed, allocSeq + 1);
|
|
48616
|
-
const threadAccount = deriveThreadPda(programId, seed);
|
|
48617
|
-
return new TransactionInstruction({
|
|
48618
|
-
programId,
|
|
48619
|
-
keys: [
|
|
48620
|
-
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
48621
|
-
{ pubkey: currentAllocPda, isSigner: false, isWritable: true },
|
|
48622
|
-
{ pubkey: newAllocPda, isSigner: false, isWritable: true },
|
|
48623
|
-
{ pubkey: threadAccount, isSigner: false, isWritable: true },
|
|
48624
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48625
|
-
],
|
|
48626
|
-
data: Buffer3.from(PrepareAllocInstr.serialize({
|
|
48627
|
-
tag: Instruction.PrepareAlloc,
|
|
48628
|
-
allocSeq
|
|
48629
|
-
}))
|
|
48630
|
-
});
|
|
48631
|
-
}
|
|
48632
|
-
function buildSweepAuthorFeesInstruction(programId, seed, threadAccount, authorWallet, shardIndices) {
|
|
48607
|
+
function buildCloseAccountInstruction(programId, payer, targetAccount, likesAccount) {
|
|
48633
48608
|
const keys = [
|
|
48634
|
-
|
|
48635
|
-
|
|
48609
|
+
signerMeta(payer),
|
|
48610
|
+
writableMeta(targetAccount)
|
|
48636
48611
|
];
|
|
48637
|
-
|
|
48638
|
-
keys.push(
|
|
48639
|
-
pubkey: deriveAuthorFeePda(programId, seed, idx),
|
|
48640
|
-
isSigner: false,
|
|
48641
|
-
isWritable: true
|
|
48642
|
-
});
|
|
48612
|
+
if (likesAccount) {
|
|
48613
|
+
keys.push(writableMeta(likesAccount));
|
|
48643
48614
|
}
|
|
48644
48615
|
return new TransactionInstruction({
|
|
48645
48616
|
programId,
|
|
48646
48617
|
keys,
|
|
48647
|
-
data: Buffer3.from(
|
|
48648
|
-
tag: Instruction.SweepAuthorFees,
|
|
48649
|
-
shardIndices: Uint8Array.from(shardIndices)
|
|
48650
|
-
}))
|
|
48618
|
+
data: Buffer3.from(TagOnlyInstr.serialize({ tag: Instruction.CloseAccount }))
|
|
48651
48619
|
});
|
|
48652
48620
|
}
|
|
48653
|
-
function
|
|
48654
|
-
const
|
|
48655
|
-
|
|
48656
|
-
|
|
48657
|
-
|
|
48658
|
-
|
|
48659
|
-
|
|
48660
|
-
|
|
48621
|
+
function buildLikeContentInstruction(programId, payer, seed, allocSeq, slot, maxFee) {
|
|
48622
|
+
const likesAccount = deriveLikesPda(programId, seed, allocSeq);
|
|
48623
|
+
const contentAccount = deriveContentPda(programId, seed, allocSeq, slot);
|
|
48624
|
+
const threadAccount = deriveThreadPda(programId, seed);
|
|
48625
|
+
const settingsAccount = deriveSettingsPda(programId);
|
|
48626
|
+
const treasuryShardIdx = randomTreasuryShard();
|
|
48627
|
+
const authorFeeShardIdx = randomAuthorFeeShard();
|
|
48628
|
+
const treasuryShard = deriveTreasuryShardPda(programId, treasuryShardIdx);
|
|
48629
|
+
const authorFeeShard = deriveAuthorFeePda(programId, seed, authorFeeShardIdx);
|
|
48661
48630
|
return new TransactionInstruction({
|
|
48662
48631
|
programId,
|
|
48663
|
-
keys
|
|
48664
|
-
|
|
48632
|
+
keys: [
|
|
48633
|
+
signerMeta(payer),
|
|
48634
|
+
writableMeta(likesAccount),
|
|
48635
|
+
readonlyMeta(contentAccount),
|
|
48636
|
+
readonlyMeta(threadAccount),
|
|
48637
|
+
readonlyMeta(settingsAccount),
|
|
48638
|
+
writableMeta(treasuryShard),
|
|
48639
|
+
writableMeta(authorFeeShard),
|
|
48640
|
+
readonlyMeta(SystemProgram.programId)
|
|
48641
|
+
],
|
|
48642
|
+
data: Buffer3.from(LikeContentInstr.serialize({
|
|
48643
|
+
tag: Instruction.LikeContent,
|
|
48644
|
+
allocSeq,
|
|
48645
|
+
slot,
|
|
48646
|
+
treasuryShardIdx,
|
|
48647
|
+
authorFeeShardIdx,
|
|
48648
|
+
maxFee
|
|
48649
|
+
}))
|
|
48665
48650
|
});
|
|
48666
48651
|
}
|
|
48667
48652
|
function buildInitThreadAccessInstruction(programId, authority, seed, enabled) {
|
|
@@ -48672,11 +48657,11 @@ function buildInitThreadAccessInstruction(programId, authority, seed, enabled) {
|
|
|
48672
48657
|
return new TransactionInstruction({
|
|
48673
48658
|
programId,
|
|
48674
48659
|
keys: [
|
|
48675
|
-
|
|
48676
|
-
|
|
48677
|
-
|
|
48678
|
-
|
|
48679
|
-
|
|
48660
|
+
signerMeta(authority),
|
|
48661
|
+
readonlyMeta(threadAccount),
|
|
48662
|
+
writableMeta(accessAccount),
|
|
48663
|
+
writableMeta(treasuryShard),
|
|
48664
|
+
readonlyMeta(SystemProgram.programId)
|
|
48680
48665
|
],
|
|
48681
48666
|
data: Buffer3.from(InitThreadAccessInstr.serialize({
|
|
48682
48667
|
tag: Instruction.InitThreadAccess,
|
|
@@ -48689,8 +48674,8 @@ function buildSetThreadAccessInstruction(programId, authority, accessAccount, en
|
|
|
48689
48674
|
return new TransactionInstruction({
|
|
48690
48675
|
programId,
|
|
48691
48676
|
keys: [
|
|
48692
|
-
|
|
48693
|
-
|
|
48677
|
+
signerMeta(authority),
|
|
48678
|
+
writableMeta(accessAccount)
|
|
48694
48679
|
],
|
|
48695
48680
|
data: Buffer3.from(SetThreadAccessInstr.serialize({
|
|
48696
48681
|
tag: Instruction.SetThreadAccess,
|
|
@@ -48698,70 +48683,6 @@ function buildSetThreadAccessInstruction(programId, authority, accessAccount, en
|
|
|
48698
48683
|
}))
|
|
48699
48684
|
});
|
|
48700
48685
|
}
|
|
48701
|
-
function buildAddToWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48702
|
-
const accessAccount = deriveAccessPda(programId, seed);
|
|
48703
|
-
const entryAccount = deriveAccessEntryPda(programId, seed, wallet);
|
|
48704
|
-
return new TransactionInstruction({
|
|
48705
|
-
programId,
|
|
48706
|
-
keys: [
|
|
48707
|
-
{ pubkey: authority, isSigner: true, isWritable: true },
|
|
48708
|
-
{ pubkey: accessAccount, isSigner: false, isWritable: true },
|
|
48709
|
-
{ pubkey: entryAccount, isSigner: false, isWritable: true },
|
|
48710
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48711
|
-
],
|
|
48712
|
-
data: Buffer3.from(WalletArgInstr.serialize({
|
|
48713
|
-
tag: Instruction.AddToWhitelist,
|
|
48714
|
-
wallet: wallet.toBytes()
|
|
48715
|
-
}))
|
|
48716
|
-
});
|
|
48717
|
-
}
|
|
48718
|
-
function buildRemoveFromWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48719
|
-
const accessAccount = deriveAccessPda(programId, seed);
|
|
48720
|
-
const entryAccount = deriveAccessEntryPda(programId, seed, wallet);
|
|
48721
|
-
return new TransactionInstruction({
|
|
48722
|
-
programId,
|
|
48723
|
-
keys: [
|
|
48724
|
-
{ pubkey: authority, isSigner: true, isWritable: true },
|
|
48725
|
-
{ pubkey: accessAccount, isSigner: false, isWritable: true },
|
|
48726
|
-
{ pubkey: entryAccount, isSigner: false, isWritable: true },
|
|
48727
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48728
|
-
],
|
|
48729
|
-
data: Buffer3.from(WalletArgInstr.serialize({
|
|
48730
|
-
tag: Instruction.RemoveFromWhitelist,
|
|
48731
|
-
wallet: wallet.toBytes()
|
|
48732
|
-
}))
|
|
48733
|
-
});
|
|
48734
|
-
}
|
|
48735
|
-
function buildSetMessageFeeInstruction(programId, authority, threadAccount, fee) {
|
|
48736
|
-
return new TransactionInstruction({
|
|
48737
|
-
programId,
|
|
48738
|
-
keys: [
|
|
48739
|
-
{ pubkey: authority, isSigner: true, isWritable: true },
|
|
48740
|
-
{ pubkey: threadAccount, isSigner: false, isWritable: true }
|
|
48741
|
-
],
|
|
48742
|
-
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetMessageFee, fee }))
|
|
48743
|
-
});
|
|
48744
|
-
}
|
|
48745
|
-
function buildSetLikeFeeInstruction(programId, authority, threadAccount, fee) {
|
|
48746
|
-
return new TransactionInstruction({
|
|
48747
|
-
programId,
|
|
48748
|
-
keys: [
|
|
48749
|
-
{ pubkey: authority, isSigner: true, isWritable: true },
|
|
48750
|
-
{ pubkey: threadAccount, isSigner: false, isWritable: true }
|
|
48751
|
-
],
|
|
48752
|
-
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetLikeFee, fee }))
|
|
48753
|
-
});
|
|
48754
|
-
}
|
|
48755
|
-
function buildSetEntryFeeInstruction(programId, authority, accessAccount, fee) {
|
|
48756
|
-
return new TransactionInstruction({
|
|
48757
|
-
programId,
|
|
48758
|
-
keys: [
|
|
48759
|
-
{ pubkey: authority, isSigner: true, isWritable: true },
|
|
48760
|
-
{ pubkey: accessAccount, isSigner: false, isWritable: true }
|
|
48761
|
-
],
|
|
48762
|
-
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetEntryFee, fee }))
|
|
48763
|
-
});
|
|
48764
|
-
}
|
|
48765
48686
|
function buildRequestAccessInstruction(programId, payer, seed) {
|
|
48766
48687
|
const accessAccount = deriveAccessPda(programId, seed);
|
|
48767
48688
|
const entryAccount = deriveAccessEntryPda(programId, seed, payer);
|
|
@@ -48774,14 +48695,14 @@ function buildRequestAccessInstruction(programId, payer, seed) {
|
|
|
48774
48695
|
return new TransactionInstruction({
|
|
48775
48696
|
programId,
|
|
48776
48697
|
keys: [
|
|
48777
|
-
|
|
48778
|
-
|
|
48779
|
-
|
|
48780
|
-
|
|
48781
|
-
|
|
48782
|
-
|
|
48783
|
-
|
|
48784
|
-
|
|
48698
|
+
signerMeta(payer),
|
|
48699
|
+
writableMeta(accessAccount),
|
|
48700
|
+
writableMeta(entryAccount),
|
|
48701
|
+
readonlyMeta(threadAccount),
|
|
48702
|
+
readonlyMeta(settingsAccount),
|
|
48703
|
+
writableMeta(treasuryShard),
|
|
48704
|
+
writableMeta(authorFeeShard),
|
|
48705
|
+
readonlyMeta(SystemProgram.programId)
|
|
48785
48706
|
],
|
|
48786
48707
|
data: Buffer3.from(RequestAccessInstr.serialize({
|
|
48787
48708
|
tag: Instruction.RequestAccess,
|
|
@@ -48790,111 +48711,94 @@ function buildRequestAccessInstruction(programId, payer, seed) {
|
|
|
48790
48711
|
}))
|
|
48791
48712
|
});
|
|
48792
48713
|
}
|
|
48793
|
-
function
|
|
48794
|
-
const likesAccount = deriveLikesPda(programId, seed, allocSeq);
|
|
48795
|
-
const contentAccount = deriveContentPda(programId, seed, allocSeq, slot);
|
|
48796
|
-
const threadAccount = deriveThreadPda(programId, seed);
|
|
48797
|
-
const settingsAccount = deriveSettingsPda(programId);
|
|
48798
|
-
const treasuryShardIdx = randomTreasuryShard();
|
|
48799
|
-
const authorFeeShardIdx = randomAuthorFeeShard();
|
|
48800
|
-
const treasuryShard = deriveTreasuryShardPda(programId, treasuryShardIdx);
|
|
48801
|
-
const authorFeeShard = deriveAuthorFeePda(programId, seed, authorFeeShardIdx);
|
|
48802
|
-
return new TransactionInstruction({
|
|
48803
|
-
programId,
|
|
48804
|
-
keys: [
|
|
48805
|
-
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
48806
|
-
{ pubkey: likesAccount, isSigner: false, isWritable: true },
|
|
48807
|
-
{ pubkey: contentAccount, isSigner: false, isWritable: false },
|
|
48808
|
-
{ pubkey: threadAccount, isSigner: false, isWritable: false },
|
|
48809
|
-
{ pubkey: settingsAccount, isSigner: false, isWritable: false },
|
|
48810
|
-
{ pubkey: treasuryShard, isSigner: false, isWritable: true },
|
|
48811
|
-
{ pubkey: authorFeeShard, isSigner: false, isWritable: true },
|
|
48812
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48813
|
-
],
|
|
48814
|
-
data: Buffer3.from(LikeContentInstr.serialize({
|
|
48815
|
-
tag: Instruction.LikeContent,
|
|
48816
|
-
allocSeq,
|
|
48817
|
-
slot,
|
|
48818
|
-
treasuryShardIdx,
|
|
48819
|
-
authorFeeShardIdx,
|
|
48820
|
-
maxFee
|
|
48821
|
-
}))
|
|
48822
|
-
});
|
|
48823
|
-
}
|
|
48824
|
-
function buildAddToBlacklistInstruction(programId, authority, seed, wallet) {
|
|
48714
|
+
function buildAclEntryInstruction(tag, programId, authority, seed, wallet) {
|
|
48825
48715
|
const accessAccount = deriveAccessPda(programId, seed);
|
|
48826
48716
|
const entryAccount = deriveAccessEntryPda(programId, seed, wallet);
|
|
48827
48717
|
return new TransactionInstruction({
|
|
48828
48718
|
programId,
|
|
48829
48719
|
keys: [
|
|
48830
|
-
|
|
48831
|
-
|
|
48832
|
-
|
|
48833
|
-
|
|
48720
|
+
signerMeta(authority),
|
|
48721
|
+
writableMeta(accessAccount),
|
|
48722
|
+
writableMeta(entryAccount),
|
|
48723
|
+
readonlyMeta(SystemProgram.programId)
|
|
48834
48724
|
],
|
|
48835
48725
|
data: Buffer3.from(WalletArgInstr.serialize({
|
|
48836
|
-
tag
|
|
48726
|
+
tag,
|
|
48837
48727
|
wallet: wallet.toBytes()
|
|
48838
48728
|
}))
|
|
48839
48729
|
});
|
|
48840
48730
|
}
|
|
48731
|
+
function buildAddToWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48732
|
+
return buildAclEntryInstruction(Instruction.AddToWhitelist, programId, authority, seed, wallet);
|
|
48733
|
+
}
|
|
48734
|
+
function buildRemoveFromWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48735
|
+
return buildAclEntryInstruction(Instruction.RemoveFromWhitelist, programId, authority, seed, wallet);
|
|
48736
|
+
}
|
|
48737
|
+
function buildAddToBlacklistInstruction(programId, authority, seed, wallet) {
|
|
48738
|
+
return buildAclEntryInstruction(Instruction.AddToBlacklist, programId, authority, seed, wallet);
|
|
48739
|
+
}
|
|
48841
48740
|
function buildRemoveFromBlacklistInstruction(programId, authority, seed, wallet) {
|
|
48842
|
-
|
|
48843
|
-
|
|
48741
|
+
return buildAclEntryInstruction(Instruction.RemoveFromBlacklist, programId, authority, seed, wallet);
|
|
48742
|
+
}
|
|
48743
|
+
function buildAddToFeeWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48744
|
+
return buildAclEntryInstruction(Instruction.AddToFeeWhitelist, programId, authority, seed, wallet);
|
|
48745
|
+
}
|
|
48746
|
+
function buildRemoveFromFeeWhitelistInstruction(programId, authority, seed, wallet) {
|
|
48747
|
+
return buildAclEntryInstruction(Instruction.RemoveFromFeeWhitelist, programId, authority, seed, wallet);
|
|
48748
|
+
}
|
|
48749
|
+
var FEE_TAG = {
|
|
48750
|
+
base: Instruction.SetBaseFee,
|
|
48751
|
+
authorCut: Instruction.SetAuthorFeeCut,
|
|
48752
|
+
entryCut: Instruction.SetEntryCut,
|
|
48753
|
+
likeCut: Instruction.SetLikeCut
|
|
48754
|
+
};
|
|
48755
|
+
function buildSetMessageFeeInstruction(programId, authority, threadAccount, fee) {
|
|
48844
48756
|
return new TransactionInstruction({
|
|
48845
48757
|
programId,
|
|
48846
48758
|
keys: [
|
|
48847
|
-
|
|
48848
|
-
|
|
48849
|
-
{ pubkey: entryAccount, isSigner: false, isWritable: true },
|
|
48850
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48759
|
+
signerMeta(authority),
|
|
48760
|
+
writableMeta(threadAccount)
|
|
48851
48761
|
],
|
|
48852
|
-
data: Buffer3.from(
|
|
48853
|
-
tag: Instruction.RemoveFromBlacklist,
|
|
48854
|
-
wallet: wallet.toBytes()
|
|
48855
|
-
}))
|
|
48762
|
+
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetMessageFee, fee }))
|
|
48856
48763
|
});
|
|
48857
48764
|
}
|
|
48858
|
-
function
|
|
48859
|
-
const accessAccount = deriveAccessPda(programId, seed);
|
|
48860
|
-
const entryAccount = deriveAccessEntryPda(programId, seed, wallet);
|
|
48765
|
+
function buildSetLikeFeeInstruction(programId, authority, threadAccount, fee) {
|
|
48861
48766
|
return new TransactionInstruction({
|
|
48862
48767
|
programId,
|
|
48863
48768
|
keys: [
|
|
48864
|
-
|
|
48865
|
-
|
|
48866
|
-
{ pubkey: entryAccount, isSigner: false, isWritable: true },
|
|
48867
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48769
|
+
signerMeta(authority),
|
|
48770
|
+
writableMeta(threadAccount)
|
|
48868
48771
|
],
|
|
48869
|
-
data: Buffer3.from(
|
|
48870
|
-
tag: Instruction.AddToFeeWhitelist,
|
|
48871
|
-
wallet: wallet.toBytes()
|
|
48872
|
-
}))
|
|
48772
|
+
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetLikeFee, fee }))
|
|
48873
48773
|
});
|
|
48874
48774
|
}
|
|
48875
|
-
function
|
|
48876
|
-
const accessAccount = deriveAccessPda(programId, seed);
|
|
48877
|
-
const entryAccount = deriveAccessEntryPda(programId, seed, wallet);
|
|
48775
|
+
function buildSetEntryFeeInstruction(programId, authority, accessAccount, fee) {
|
|
48878
48776
|
return new TransactionInstruction({
|
|
48879
48777
|
programId,
|
|
48880
48778
|
keys: [
|
|
48881
|
-
|
|
48882
|
-
|
|
48883
|
-
{ pubkey: entryAccount, isSigner: false, isWritable: true },
|
|
48884
|
-
{ pubkey: SystemProgram.programId, isSigner: false, isWritable: false }
|
|
48779
|
+
signerMeta(authority),
|
|
48780
|
+
writableMeta(accessAccount)
|
|
48885
48781
|
],
|
|
48886
|
-
data: Buffer3.from(
|
|
48887
|
-
|
|
48888
|
-
|
|
48782
|
+
data: Buffer3.from(FeeU64Instr.serialize({ tag: Instruction.SetEntryFee, fee }))
|
|
48783
|
+
});
|
|
48784
|
+
}
|
|
48785
|
+
function buildSweepAuthorFeesInstruction(programId, seed, threadAccount, authorWallet, shardIndices) {
|
|
48786
|
+
const keys = [
|
|
48787
|
+
readonlyMeta(threadAccount),
|
|
48788
|
+
signerMeta(authorWallet)
|
|
48789
|
+
];
|
|
48790
|
+
for (const idx of shardIndices) {
|
|
48791
|
+
keys.push(writableMeta(deriveAuthorFeePda(programId, seed, idx)));
|
|
48792
|
+
}
|
|
48793
|
+
return new TransactionInstruction({
|
|
48794
|
+
programId,
|
|
48795
|
+
keys,
|
|
48796
|
+
data: Buffer3.from(SweepAuthorFeesInstr.serialize({
|
|
48797
|
+
tag: Instruction.SweepAuthorFees,
|
|
48798
|
+
shardIndices: Uint8Array.from(shardIndices)
|
|
48889
48799
|
}))
|
|
48890
48800
|
});
|
|
48891
48801
|
}
|
|
48892
|
-
var FEE_TAG = {
|
|
48893
|
-
base: Instruction.SetBaseFee,
|
|
48894
|
-
authorCut: Instruction.SetAuthorFeeCut,
|
|
48895
|
-
entryCut: Instruction.SetEntryCut,
|
|
48896
|
-
likeCut: Instruction.SetLikeCut
|
|
48897
|
-
};
|
|
48898
48802
|
function buildFollowInstruction(tag, opts) {
|
|
48899
48803
|
const { programId, user, seed } = opts;
|
|
48900
48804
|
const threadAccount = deriveThreadPda(programId, seed);
|
|
@@ -48903,11 +48807,11 @@ function buildFollowInstruction(tag, opts) {
|
|
|
48903
48807
|
return new TransactionInstruction({
|
|
48904
48808
|
programId,
|
|
48905
48809
|
keys: [
|
|
48906
|
-
|
|
48907
|
-
|
|
48908
|
-
|
|
48909
|
-
|
|
48910
|
-
|
|
48810
|
+
signerMeta(user),
|
|
48811
|
+
writableMeta(followRegistry),
|
|
48812
|
+
writableMeta(followerShard),
|
|
48813
|
+
readonlyMeta(threadAccount),
|
|
48814
|
+
readonlyMeta(SystemProgram.programId)
|
|
48911
48815
|
],
|
|
48912
48816
|
data: Buffer3.from(TagOnlyInstr.serialize({ tag }))
|
|
48913
48817
|
});
|
|
@@ -48981,6 +48885,18 @@ async function sendTransactions(payer, txs) {
|
|
|
48981
48885
|
}
|
|
48982
48886
|
return sigs;
|
|
48983
48887
|
}
|
|
48888
|
+
async function trySendBestEffort(payer, tx) {
|
|
48889
|
+
try {
|
|
48890
|
+
const { connection } = loadConfig();
|
|
48891
|
+
tx.feePayer = payer.publicKey;
|
|
48892
|
+
const { blockhash } = await connection.getLatestBlockhash("confirmed");
|
|
48893
|
+
tx.recentBlockhash = blockhash;
|
|
48894
|
+
tx.sign(payer);
|
|
48895
|
+
return await connection.sendRawTransaction(tx.serialize());
|
|
48896
|
+
} catch {
|
|
48897
|
+
return null;
|
|
48898
|
+
}
|
|
48899
|
+
}
|
|
48984
48900
|
function explorerTx(signature) {
|
|
48985
48901
|
const { rpcUrl } = loadConfig();
|
|
48986
48902
|
const cluster = rpcUrl.includes("devnet") ? "?cluster=devnet" : rpcUrl.includes("testnet") ? "?cluster=testnet" : rpcUrl.includes("localhost") || rpcUrl.includes("127.0.0.1") ? "?cluster=custom" : "";
|
|
@@ -49113,7 +49029,7 @@ function registerMessagingTools(server) {
|
|
|
49113
49029
|
"send_message",
|
|
49114
49030
|
{
|
|
49115
49031
|
title: "Send message",
|
|
49116
|
-
description: "Post a text message to a channel as the agent wallet. Handles fees, slot selection and chunking of long messages automatically.",
|
|
49032
|
+
description: "Post a text message to a channel as the agent wallet. Handles fees, slot selection and chunking of long messages automatically. Posting is decoupled from growing the alloc chain: after the post confirms, a best-effort page extension is fired when the tail page is filling up (its failure never affects the post).",
|
|
49117
49033
|
inputSchema: {
|
|
49118
49034
|
channel: channelArg,
|
|
49119
49035
|
text: external_exports.string().min(1).describe("Message text (UTF-8, up to 8192 bytes)."),
|
|
@@ -49135,10 +49051,19 @@ function registerMessagingTools(server) {
|
|
|
49135
49051
|
replyTo
|
|
49136
49052
|
);
|
|
49137
49053
|
const signatures = await sendTransactions(payer, txs);
|
|
49054
|
+
let extendSignature = null;
|
|
49055
|
+
try {
|
|
49056
|
+
const extendTx = await buildExtendAllocTransaction(connection, programId, payer.publicKey, seed);
|
|
49057
|
+
if (extendTx) extendSignature = await trySendBestEffort(payer, extendTx);
|
|
49058
|
+
} catch {
|
|
49059
|
+
extendSignature = null;
|
|
49060
|
+
}
|
|
49138
49061
|
return jsonResult({
|
|
49139
49062
|
channel: seedToAddress(seed),
|
|
49140
49063
|
signatures,
|
|
49141
|
-
explorer: signatures.map(explorerTx)
|
|
49064
|
+
explorer: signatures.map(explorerTx),
|
|
49065
|
+
extendSignature,
|
|
49066
|
+
extendExplorer: extendSignature ? explorerTx(extendSignature) : null
|
|
49142
49067
|
});
|
|
49143
49068
|
})
|
|
49144
49069
|
);
|
|
@@ -49180,7 +49105,7 @@ function registerMessagingTools(server) {
|
|
|
49180
49105
|
"prepare_alloc",
|
|
49181
49106
|
{
|
|
49182
49107
|
title: "Prepare alloc",
|
|
49183
|
-
description: "
|
|
49108
|
+
description: "Manually pre-create the next alloc page (allocSeq + 1) in a channel so there are free slots ahead of demand. send_message already does this best-effort; use this to force-extend a high-traffic channel. Racy by design: it fails with InvalidAllocSeq if the chain tail moved on.",
|
|
49184
49109
|
inputSchema: {
|
|
49185
49110
|
channel: channelArg,
|
|
49186
49111
|
allocSeq: external_exports.number().int().describe("Current alloc seq to extend from.")
|
|
@@ -49644,7 +49569,7 @@ function registerThreadAdminTools(server) {
|
|
|
49644
49569
|
async function main() {
|
|
49645
49570
|
const config2 = loadConfig();
|
|
49646
49571
|
const wallet = loadWallet();
|
|
49647
|
-
const server = new McpServer({ name: "txtcel-mcp", version: "0.
|
|
49572
|
+
const server = new McpServer({ name: "txtcel-mcp", version: "0.2.0" });
|
|
49648
49573
|
registerMessagingTools(server);
|
|
49649
49574
|
registerFollowTools(server);
|
|
49650
49575
|
registerReadTools(server);
|