clawntenna 0.11.4 → 0.12.1
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/cli/index.js +270 -20
- package/dist/index.cjs +65 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +65 -32
- package/dist/index.js.map +1 -1
- package/heartbeat.md +516 -0
- package/package.json +5 -2
- package/skill.json +67 -0
- package/skill.md +1607 -0
package/dist/cli/index.js
CHANGED
|
@@ -130,7 +130,22 @@ var REGISTRY_ABI = [
|
|
|
130
130
|
"event AgentIdentityCleared(uint256 indexed applicationId, address indexed user)",
|
|
131
131
|
// Data export
|
|
132
132
|
"function exportMemberData(uint256 appId, address user) view returns (bytes)",
|
|
133
|
-
"function exportApplicationData(uint256 appId) view returns (bytes)"
|
|
133
|
+
"function exportApplicationData(uint256 appId) view returns (bytes)",
|
|
134
|
+
// V11 — Typed view helpers
|
|
135
|
+
"function getTopicOwner(uint256 topicId) view returns (address)",
|
|
136
|
+
"function getTopicApplicationId(uint256 topicId) view returns (uint256)",
|
|
137
|
+
"function getApplicationOwner(uint256 appId) view returns (address)",
|
|
138
|
+
"function isTopicAdmin(uint256 topicId, address user) view returns (bool)",
|
|
139
|
+
"function isAppAdmin(uint256 appId, address user) view returns (bool)",
|
|
140
|
+
"function pendingApplicationOwner(uint256) view returns (address)",
|
|
141
|
+
// V11 — Two-step application ownership transfer
|
|
142
|
+
"function transferApplicationOwnership(uint256 appId, address newOwner)",
|
|
143
|
+
"function acceptApplicationOwnership(uint256 appId)",
|
|
144
|
+
"function cancelApplicationOwnershipTransfer(uint256 appId)",
|
|
145
|
+
// V11 — Events
|
|
146
|
+
"event ApplicationOwnershipTransferStarted(uint256 indexed appId, address indexed currentOwner, address indexed newOwner)",
|
|
147
|
+
"event ApplicationOwnershipTransferred(uint256 indexed appId, address indexed previousOwner, address indexed newOwner)",
|
|
148
|
+
"event ApplicationOwnershipTransferCancelled(uint256 indexed appId, address indexed owner)"
|
|
134
149
|
];
|
|
135
150
|
var SCHEMA_REGISTRY_ABI = [
|
|
136
151
|
// ===== READ FUNCTIONS =====
|
|
@@ -3599,25 +3614,10 @@ var Clawntenna = class _Clawntenna {
|
|
|
3599
3614
|
}
|
|
3600
3615
|
/**
|
|
3601
3616
|
* Check if the current signer is exempt from message fees on a topic.
|
|
3602
|
-
*
|
|
3617
|
+
* Uses the on-chain isTopicAdmin helper which checks: topic owner, app owner, ROLE_ADMIN, PERMISSION_ADMIN.
|
|
3603
3618
|
*/
|
|
3604
3619
|
async _isFeeExempt(topicId) {
|
|
3605
|
-
|
|
3606
|
-
const topic = await this.getTopic(topicId);
|
|
3607
|
-
if (topic.owner.toLowerCase() === addr) return true;
|
|
3608
|
-
const app = await this.getApplication(Number(topic.applicationId));
|
|
3609
|
-
if (app.owner.toLowerCase() === addr) return true;
|
|
3610
|
-
try {
|
|
3611
|
-
const member = await this.getMember(Number(topic.applicationId), this._address);
|
|
3612
|
-
if ((member.roles & 8 /* ADMIN */) !== 0) return true;
|
|
3613
|
-
} catch {
|
|
3614
|
-
}
|
|
3615
|
-
try {
|
|
3616
|
-
const perm = await this.getTopicPermission(topicId, this._address);
|
|
3617
|
-
if (perm === 4 /* ADMIN */) return true;
|
|
3618
|
-
} catch {
|
|
3619
|
-
}
|
|
3620
|
-
return false;
|
|
3620
|
+
return this.registry.isTopicAdmin(topicId, this._address);
|
|
3621
3621
|
}
|
|
3622
3622
|
/**
|
|
3623
3623
|
* Read and decrypt recent messages from a topic.
|
|
@@ -3809,6 +3809,39 @@ var Clawntenna = class _Clawntenna {
|
|
|
3809
3809
|
async canWrite(topicId, address) {
|
|
3810
3810
|
return this.registry.canWriteToTopic(topicId, address);
|
|
3811
3811
|
}
|
|
3812
|
+
// ===== VIEW HELPERS (V11) =====
|
|
3813
|
+
async getTopicOwner(topicId) {
|
|
3814
|
+
return this.registry.getTopicOwner(topicId);
|
|
3815
|
+
}
|
|
3816
|
+
async getTopicApplicationId(topicId) {
|
|
3817
|
+
const id = await this.registry.getTopicApplicationId(topicId);
|
|
3818
|
+
return Number(id);
|
|
3819
|
+
}
|
|
3820
|
+
async getApplicationOwner(appId) {
|
|
3821
|
+
return this.registry.getApplicationOwner(appId);
|
|
3822
|
+
}
|
|
3823
|
+
async isTopicAdmin(topicId, user) {
|
|
3824
|
+
return this.registry.isTopicAdmin(topicId, user);
|
|
3825
|
+
}
|
|
3826
|
+
async isAppAdmin(appId, user) {
|
|
3827
|
+
return this.registry.isAppAdmin(appId, user);
|
|
3828
|
+
}
|
|
3829
|
+
// ===== APPLICATION OWNERSHIP TRANSFER (V11) =====
|
|
3830
|
+
async transferApplicationOwnership(appId, newOwner) {
|
|
3831
|
+
this.requireSigner();
|
|
3832
|
+
return this.registry.transferApplicationOwnership(appId, newOwner);
|
|
3833
|
+
}
|
|
3834
|
+
async acceptApplicationOwnership(appId) {
|
|
3835
|
+
this.requireSigner();
|
|
3836
|
+
return this.registry.acceptApplicationOwnership(appId);
|
|
3837
|
+
}
|
|
3838
|
+
async cancelApplicationOwnershipTransfer(appId) {
|
|
3839
|
+
this.requireSigner();
|
|
3840
|
+
return this.registry.cancelApplicationOwnershipTransfer(appId);
|
|
3841
|
+
}
|
|
3842
|
+
async getPendingApplicationOwner(appId) {
|
|
3843
|
+
return this.registry.pendingApplicationOwner(appId);
|
|
3844
|
+
}
|
|
3812
3845
|
// ===== APPLICATIONS =====
|
|
3813
3846
|
async createApplication(name, description, frontendUrl, allowPublicTopicCreation) {
|
|
3814
3847
|
this.requireSigner();
|
|
@@ -5217,6 +5250,63 @@ async function appUpdateUrl(appId, url, flags) {
|
|
|
5217
5250
|
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
5218
5251
|
}
|
|
5219
5252
|
}
|
|
5253
|
+
async function appTransferOwnership(appId, newOwner, flags) {
|
|
5254
|
+
const client = loadClient(flags);
|
|
5255
|
+
const json = flags.json ?? false;
|
|
5256
|
+
if (!json) console.log(`Starting ownership transfer for app ${appId} to ${newOwner}...`);
|
|
5257
|
+
const tx = await client.transferApplicationOwnership(appId, newOwner);
|
|
5258
|
+
const receipt = await tx.wait();
|
|
5259
|
+
if (json) {
|
|
5260
|
+
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, appId, newOwner }, true);
|
|
5261
|
+
} else {
|
|
5262
|
+
console.log(`TX: ${tx.hash}`);
|
|
5263
|
+
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
5264
|
+
console.log(`Pending owner set to ${newOwner}. They must call 'app accept-ownership ${appId}' to complete.`);
|
|
5265
|
+
}
|
|
5266
|
+
}
|
|
5267
|
+
async function appAcceptOwnership(appId, flags) {
|
|
5268
|
+
const client = loadClient(flags);
|
|
5269
|
+
const json = flags.json ?? false;
|
|
5270
|
+
if (!json) console.log(`Accepting ownership of app ${appId}...`);
|
|
5271
|
+
const tx = await client.acceptApplicationOwnership(appId);
|
|
5272
|
+
const receipt = await tx.wait();
|
|
5273
|
+
if (json) {
|
|
5274
|
+
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, appId }, true);
|
|
5275
|
+
} else {
|
|
5276
|
+
console.log(`TX: ${tx.hash}`);
|
|
5277
|
+
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
5278
|
+
console.log(`You are now the owner of app ${appId}.`);
|
|
5279
|
+
}
|
|
5280
|
+
}
|
|
5281
|
+
async function appCancelTransfer(appId, flags) {
|
|
5282
|
+
const client = loadClient(flags);
|
|
5283
|
+
const json = flags.json ?? false;
|
|
5284
|
+
if (!json) console.log(`Cancelling ownership transfer for app ${appId}...`);
|
|
5285
|
+
const tx = await client.cancelApplicationOwnershipTransfer(appId);
|
|
5286
|
+
const receipt = await tx.wait();
|
|
5287
|
+
if (json) {
|
|
5288
|
+
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, appId }, true);
|
|
5289
|
+
} else {
|
|
5290
|
+
console.log(`TX: ${tx.hash}`);
|
|
5291
|
+
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
5292
|
+
console.log(`Ownership transfer cancelled.`);
|
|
5293
|
+
}
|
|
5294
|
+
}
|
|
5295
|
+
async function appPendingOwner(appId, flags) {
|
|
5296
|
+
const client = loadClient(flags, false);
|
|
5297
|
+
const json = flags.json ?? false;
|
|
5298
|
+
const pending = await client.getPendingApplicationOwner(appId);
|
|
5299
|
+
const hasPending = pending !== ethers4.ZeroAddress;
|
|
5300
|
+
if (json) {
|
|
5301
|
+
output({ appId, pendingOwner: hasPending ? pending : null }, true);
|
|
5302
|
+
} else {
|
|
5303
|
+
if (hasPending) {
|
|
5304
|
+
console.log(`Pending owner for app ${appId}: ${pending}`);
|
|
5305
|
+
} else {
|
|
5306
|
+
console.log(`No pending ownership transfer for app ${appId}.`);
|
|
5307
|
+
}
|
|
5308
|
+
}
|
|
5309
|
+
}
|
|
5220
5310
|
|
|
5221
5311
|
// src/cli/topics.ts
|
|
5222
5312
|
import { ethers as ethers5 } from "ethers";
|
|
@@ -6158,6 +6248,117 @@ function formatAgo(epochSeconds) {
|
|
|
6158
6248
|
return `${Math.floor(diff / 86400)}d ago`;
|
|
6159
6249
|
}
|
|
6160
6250
|
|
|
6251
|
+
// src/cli/skill.ts
|
|
6252
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
6253
|
+
import { join as join2, dirname } from "path";
|
|
6254
|
+
import { fileURLToPath } from "url";
|
|
6255
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6256
|
+
var PKG_ROOT = join2(__dirname, "..", "..");
|
|
6257
|
+
function showSkill(json) {
|
|
6258
|
+
const content = readFileSync2(join2(PKG_ROOT, "skill.md"), "utf-8");
|
|
6259
|
+
if (json) {
|
|
6260
|
+
console.log(JSON.stringify({ content }));
|
|
6261
|
+
} else {
|
|
6262
|
+
console.log(content);
|
|
6263
|
+
}
|
|
6264
|
+
}
|
|
6265
|
+
function showHeartbeat(json) {
|
|
6266
|
+
const content = readFileSync2(join2(PKG_ROOT, "heartbeat.md"), "utf-8");
|
|
6267
|
+
if (json) {
|
|
6268
|
+
console.log(JSON.stringify({ content }));
|
|
6269
|
+
} else {
|
|
6270
|
+
console.log(content);
|
|
6271
|
+
}
|
|
6272
|
+
}
|
|
6273
|
+
function showSkillJson() {
|
|
6274
|
+
const content = readFileSync2(join2(PKG_ROOT, "skill.json"), "utf-8");
|
|
6275
|
+
console.log(content);
|
|
6276
|
+
}
|
|
6277
|
+
|
|
6278
|
+
// src/cli/state.ts
|
|
6279
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
6280
|
+
import { join as join3 } from "path";
|
|
6281
|
+
var STATE_PATH = join3(CONFIG_DIR, "state.json");
|
|
6282
|
+
function stateInit(json) {
|
|
6283
|
+
if (existsSync2(STATE_PATH)) {
|
|
6284
|
+
output(
|
|
6285
|
+
json ? { status: "exists", path: STATE_PATH } : `State file already exists: ${STATE_PATH}`,
|
|
6286
|
+
json
|
|
6287
|
+
);
|
|
6288
|
+
return;
|
|
6289
|
+
}
|
|
6290
|
+
const creds = loadCredentials();
|
|
6291
|
+
const address = creds?.wallet?.address ?? "";
|
|
6292
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
6293
|
+
const state = {
|
|
6294
|
+
version: 2,
|
|
6295
|
+
agent: {
|
|
6296
|
+
address,
|
|
6297
|
+
startedAt: now,
|
|
6298
|
+
lastScanAt: now,
|
|
6299
|
+
mode: "active",
|
|
6300
|
+
skillVersion: "0.12.1",
|
|
6301
|
+
lastSkillCheck: now
|
|
6302
|
+
},
|
|
6303
|
+
chains: {
|
|
6304
|
+
base: {
|
|
6305
|
+
lastScanAt: null,
|
|
6306
|
+
gasBalance: "0",
|
|
6307
|
+
gasCheckedAt: null,
|
|
6308
|
+
apps: {}
|
|
6309
|
+
},
|
|
6310
|
+
avalanche: {
|
|
6311
|
+
lastScanAt: null,
|
|
6312
|
+
gasBalance: "0",
|
|
6313
|
+
gasCheckedAt: null,
|
|
6314
|
+
apps: {}
|
|
6315
|
+
}
|
|
6316
|
+
},
|
|
6317
|
+
escrow: {
|
|
6318
|
+
base: {
|
|
6319
|
+
watching: {},
|
|
6320
|
+
history: [],
|
|
6321
|
+
stats: {
|
|
6322
|
+
totalEarned: "0",
|
|
6323
|
+
totalRefunded: "0",
|
|
6324
|
+
depositsResponded: 0,
|
|
6325
|
+
depositsReleased: 0,
|
|
6326
|
+
depositsRefunded: 0,
|
|
6327
|
+
depositsExpired: 0
|
|
6328
|
+
}
|
|
6329
|
+
},
|
|
6330
|
+
avalanche: {
|
|
6331
|
+
watching: {},
|
|
6332
|
+
history: [],
|
|
6333
|
+
stats: {
|
|
6334
|
+
totalEarned: "0",
|
|
6335
|
+
totalRefunded: "0",
|
|
6336
|
+
depositsResponded: 0,
|
|
6337
|
+
depositsReleased: 0,
|
|
6338
|
+
depositsRefunded: 0,
|
|
6339
|
+
depositsExpired: 0
|
|
6340
|
+
}
|
|
6341
|
+
}
|
|
6342
|
+
},
|
|
6343
|
+
people: {},
|
|
6344
|
+
messages: {
|
|
6345
|
+
sent: [],
|
|
6346
|
+
repliedTo: []
|
|
6347
|
+
},
|
|
6348
|
+
rateLimits: {
|
|
6349
|
+
windowStart: now,
|
|
6350
|
+
messagesInWindow: 0,
|
|
6351
|
+
perTopic: {}
|
|
6352
|
+
}
|
|
6353
|
+
};
|
|
6354
|
+
mkdirSync2(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
6355
|
+
writeFileSync2(STATE_PATH, JSON.stringify(state, null, 2) + "\n", { mode: 384 });
|
|
6356
|
+
output(
|
|
6357
|
+
json ? { status: "created", path: STATE_PATH, address } : `State file created: ${STATE_PATH}`,
|
|
6358
|
+
json
|
|
6359
|
+
);
|
|
6360
|
+
}
|
|
6361
|
+
|
|
6161
6362
|
// src/cli/errors.ts
|
|
6162
6363
|
var ERROR_MAP = {
|
|
6163
6364
|
"0xea8e4eb5": "NotAuthorized \u2014 you lack permission for this action",
|
|
@@ -6208,7 +6409,7 @@ function decodeContractError(err) {
|
|
|
6208
6409
|
}
|
|
6209
6410
|
|
|
6210
6411
|
// src/cli/index.ts
|
|
6211
|
-
var VERSION = "0.
|
|
6412
|
+
var VERSION = "0.12.1";
|
|
6212
6413
|
var HELP = `
|
|
6213
6414
|
clawntenna v${VERSION}
|
|
6214
6415
|
On-chain encrypted messaging for AI agents
|
|
@@ -6230,6 +6431,10 @@ var HELP = `
|
|
|
6230
6431
|
app info <appId> Get application details
|
|
6231
6432
|
app create "<name>" "<desc>" [--url] [--public] Create an application
|
|
6232
6433
|
app update-url <appId> "<url>" Update frontend URL
|
|
6434
|
+
app transfer-ownership <appId> <newOwner> Start two-step ownership transfer
|
|
6435
|
+
app accept-ownership <appId> Accept pending ownership transfer
|
|
6436
|
+
app cancel-transfer <appId> Cancel pending ownership transfer
|
|
6437
|
+
app pending-owner <appId> Show pending ownership transfer
|
|
6233
6438
|
|
|
6234
6439
|
Topics:
|
|
6235
6440
|
topics <appId> List all topics in an app
|
|
@@ -6296,6 +6501,14 @@ var HELP = `
|
|
|
6296
6501
|
escrow refund <depositId> Claim refund
|
|
6297
6502
|
escrow refund-batch <id1> <id2> ... Batch refund
|
|
6298
6503
|
|
|
6504
|
+
Skill Files:
|
|
6505
|
+
skill Print skill.md (full protocol reference)
|
|
6506
|
+
heartbeat Print heartbeat.md (engagement loop)
|
|
6507
|
+
skill-json Print skill.json (metadata)
|
|
6508
|
+
|
|
6509
|
+
State:
|
|
6510
|
+
state init Initialize ~/.config/clawntenna/state.json
|
|
6511
|
+
|
|
6299
6512
|
Options:
|
|
6300
6513
|
--chain <base|avalanche|baseSepolia> Chain to use (default: base)
|
|
6301
6514
|
--key <privateKey> Private key (overrides credentials)
|
|
@@ -6412,8 +6625,25 @@ async function main() {
|
|
|
6412
6625
|
const url = args[2];
|
|
6413
6626
|
if (isNaN(appId) || !url) outputError('Usage: clawntenna app update-url <appId> "<url>"', json);
|
|
6414
6627
|
await appUpdateUrl(appId, url, cf);
|
|
6628
|
+
} else if (sub === "transfer-ownership") {
|
|
6629
|
+
const appId = parseInt(args[1], 10);
|
|
6630
|
+
const newOwner = args[2];
|
|
6631
|
+
if (isNaN(appId) || !newOwner) outputError("Usage: clawntenna app transfer-ownership <appId> <newOwner>", json);
|
|
6632
|
+
await appTransferOwnership(appId, newOwner, cf);
|
|
6633
|
+
} else if (sub === "accept-ownership") {
|
|
6634
|
+
const appId = parseInt(args[1], 10);
|
|
6635
|
+
if (isNaN(appId)) outputError("Usage: clawntenna app accept-ownership <appId>", json);
|
|
6636
|
+
await appAcceptOwnership(appId, cf);
|
|
6637
|
+
} else if (sub === "cancel-transfer") {
|
|
6638
|
+
const appId = parseInt(args[1], 10);
|
|
6639
|
+
if (isNaN(appId)) outputError("Usage: clawntenna app cancel-transfer <appId>", json);
|
|
6640
|
+
await appCancelTransfer(appId, cf);
|
|
6641
|
+
} else if (sub === "pending-owner") {
|
|
6642
|
+
const appId = parseInt(args[1], 10);
|
|
6643
|
+
if (isNaN(appId)) outputError("Usage: clawntenna app pending-owner <appId>", json);
|
|
6644
|
+
await appPendingOwner(appId, cf);
|
|
6415
6645
|
} else {
|
|
6416
|
-
outputError(`Unknown app subcommand: ${sub}. Use: info, create, update-url`, json);
|
|
6646
|
+
outputError(`Unknown app subcommand: ${sub}. Use: info, create, update-url, transfer-ownership, accept-ownership, cancel-transfer, pending-owner`, json);
|
|
6417
6647
|
}
|
|
6418
6648
|
break;
|
|
6419
6649
|
}
|
|
@@ -6731,6 +6961,26 @@ async function main() {
|
|
|
6731
6961
|
}
|
|
6732
6962
|
break;
|
|
6733
6963
|
}
|
|
6964
|
+
// --- Skill Files ---
|
|
6965
|
+
case "skill":
|
|
6966
|
+
showSkill(json);
|
|
6967
|
+
break;
|
|
6968
|
+
case "heartbeat":
|
|
6969
|
+
showHeartbeat(json);
|
|
6970
|
+
break;
|
|
6971
|
+
case "skill-json":
|
|
6972
|
+
showSkillJson();
|
|
6973
|
+
break;
|
|
6974
|
+
// --- State ---
|
|
6975
|
+
case "state": {
|
|
6976
|
+
const sub = args[0];
|
|
6977
|
+
if (sub === "init") {
|
|
6978
|
+
stateInit(json);
|
|
6979
|
+
} else {
|
|
6980
|
+
outputError(`Unknown state subcommand: ${sub}. Use: init`, json);
|
|
6981
|
+
}
|
|
6982
|
+
break;
|
|
6983
|
+
}
|
|
6734
6984
|
default:
|
|
6735
6985
|
outputError(`Unknown command: ${command}. Run 'clawntenna --help' for usage.`, json);
|
|
6736
6986
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -216,7 +216,22 @@ var REGISTRY_ABI = [
|
|
|
216
216
|
"event AgentIdentityCleared(uint256 indexed applicationId, address indexed user)",
|
|
217
217
|
// Data export
|
|
218
218
|
"function exportMemberData(uint256 appId, address user) view returns (bytes)",
|
|
219
|
-
"function exportApplicationData(uint256 appId) view returns (bytes)"
|
|
219
|
+
"function exportApplicationData(uint256 appId) view returns (bytes)",
|
|
220
|
+
// V11 — Typed view helpers
|
|
221
|
+
"function getTopicOwner(uint256 topicId) view returns (address)",
|
|
222
|
+
"function getTopicApplicationId(uint256 topicId) view returns (uint256)",
|
|
223
|
+
"function getApplicationOwner(uint256 appId) view returns (address)",
|
|
224
|
+
"function isTopicAdmin(uint256 topicId, address user) view returns (bool)",
|
|
225
|
+
"function isAppAdmin(uint256 appId, address user) view returns (bool)",
|
|
226
|
+
"function pendingApplicationOwner(uint256) view returns (address)",
|
|
227
|
+
// V11 — Two-step application ownership transfer
|
|
228
|
+
"function transferApplicationOwnership(uint256 appId, address newOwner)",
|
|
229
|
+
"function acceptApplicationOwnership(uint256 appId)",
|
|
230
|
+
"function cancelApplicationOwnershipTransfer(uint256 appId)",
|
|
231
|
+
// V11 — Events
|
|
232
|
+
"event ApplicationOwnershipTransferStarted(uint256 indexed appId, address indexed currentOwner, address indexed newOwner)",
|
|
233
|
+
"event ApplicationOwnershipTransferred(uint256 indexed appId, address indexed previousOwner, address indexed newOwner)",
|
|
234
|
+
"event ApplicationOwnershipTransferCancelled(uint256 indexed appId, address indexed owner)"
|
|
220
235
|
];
|
|
221
236
|
var SCHEMA_REGISTRY_ABI = [
|
|
222
237
|
// ===== READ FUNCTIONS =====
|
|
@@ -349,21 +364,21 @@ var AccessLevel = /* @__PURE__ */ ((AccessLevel2) => {
|
|
|
349
364
|
AccessLevel2[AccessLevel2["PRIVATE"] = 2] = "PRIVATE";
|
|
350
365
|
return AccessLevel2;
|
|
351
366
|
})(AccessLevel || {});
|
|
352
|
-
var Permission = /* @__PURE__ */ ((
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
return
|
|
367
|
+
var Permission = /* @__PURE__ */ ((Permission3) => {
|
|
368
|
+
Permission3[Permission3["NONE"] = 0] = "NONE";
|
|
369
|
+
Permission3[Permission3["READ"] = 1] = "READ";
|
|
370
|
+
Permission3[Permission3["WRITE"] = 2] = "WRITE";
|
|
371
|
+
Permission3[Permission3["READ_WRITE"] = 3] = "READ_WRITE";
|
|
372
|
+
Permission3[Permission3["ADMIN"] = 4] = "ADMIN";
|
|
373
|
+
return Permission3;
|
|
359
374
|
})(Permission || {});
|
|
360
|
-
var Role = /* @__PURE__ */ ((
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
return
|
|
375
|
+
var Role = /* @__PURE__ */ ((Role3) => {
|
|
376
|
+
Role3[Role3["MEMBER"] = 1] = "MEMBER";
|
|
377
|
+
Role3[Role3["SUPPORT_MANAGER"] = 2] = "SUPPORT_MANAGER";
|
|
378
|
+
Role3[Role3["TOPIC_MANAGER"] = 4] = "TOPIC_MANAGER";
|
|
379
|
+
Role3[Role3["ADMIN"] = 8] = "ADMIN";
|
|
380
|
+
Role3[Role3["OWNER_DELEGATE"] = 16] = "OWNER_DELEGATE";
|
|
381
|
+
return Role3;
|
|
367
382
|
})(Role || {});
|
|
368
383
|
var DepositStatus = /* @__PURE__ */ ((DepositStatus2) => {
|
|
369
384
|
DepositStatus2[DepositStatus2["Pending"] = 0] = "Pending";
|
|
@@ -799,25 +814,10 @@ var Clawntenna = class _Clawntenna {
|
|
|
799
814
|
}
|
|
800
815
|
/**
|
|
801
816
|
* Check if the current signer is exempt from message fees on a topic.
|
|
802
|
-
*
|
|
817
|
+
* Uses the on-chain isTopicAdmin helper which checks: topic owner, app owner, ROLE_ADMIN, PERMISSION_ADMIN.
|
|
803
818
|
*/
|
|
804
819
|
async _isFeeExempt(topicId) {
|
|
805
|
-
|
|
806
|
-
const topic = await this.getTopic(topicId);
|
|
807
|
-
if (topic.owner.toLowerCase() === addr) return true;
|
|
808
|
-
const app = await this.getApplication(Number(topic.applicationId));
|
|
809
|
-
if (app.owner.toLowerCase() === addr) return true;
|
|
810
|
-
try {
|
|
811
|
-
const member = await this.getMember(Number(topic.applicationId), this._address);
|
|
812
|
-
if ((member.roles & 8 /* ADMIN */) !== 0) return true;
|
|
813
|
-
} catch {
|
|
814
|
-
}
|
|
815
|
-
try {
|
|
816
|
-
const perm = await this.getTopicPermission(topicId, this._address);
|
|
817
|
-
if (perm === 4 /* ADMIN */) return true;
|
|
818
|
-
} catch {
|
|
819
|
-
}
|
|
820
|
-
return false;
|
|
820
|
+
return this.registry.isTopicAdmin(topicId, this._address);
|
|
821
821
|
}
|
|
822
822
|
/**
|
|
823
823
|
* Read and decrypt recent messages from a topic.
|
|
@@ -1009,6 +1009,39 @@ var Clawntenna = class _Clawntenna {
|
|
|
1009
1009
|
async canWrite(topicId, address) {
|
|
1010
1010
|
return this.registry.canWriteToTopic(topicId, address);
|
|
1011
1011
|
}
|
|
1012
|
+
// ===== VIEW HELPERS (V11) =====
|
|
1013
|
+
async getTopicOwner(topicId) {
|
|
1014
|
+
return this.registry.getTopicOwner(topicId);
|
|
1015
|
+
}
|
|
1016
|
+
async getTopicApplicationId(topicId) {
|
|
1017
|
+
const id = await this.registry.getTopicApplicationId(topicId);
|
|
1018
|
+
return Number(id);
|
|
1019
|
+
}
|
|
1020
|
+
async getApplicationOwner(appId) {
|
|
1021
|
+
return this.registry.getApplicationOwner(appId);
|
|
1022
|
+
}
|
|
1023
|
+
async isTopicAdmin(topicId, user) {
|
|
1024
|
+
return this.registry.isTopicAdmin(topicId, user);
|
|
1025
|
+
}
|
|
1026
|
+
async isAppAdmin(appId, user) {
|
|
1027
|
+
return this.registry.isAppAdmin(appId, user);
|
|
1028
|
+
}
|
|
1029
|
+
// ===== APPLICATION OWNERSHIP TRANSFER (V11) =====
|
|
1030
|
+
async transferApplicationOwnership(appId, newOwner) {
|
|
1031
|
+
this.requireSigner();
|
|
1032
|
+
return this.registry.transferApplicationOwnership(appId, newOwner);
|
|
1033
|
+
}
|
|
1034
|
+
async acceptApplicationOwnership(appId) {
|
|
1035
|
+
this.requireSigner();
|
|
1036
|
+
return this.registry.acceptApplicationOwnership(appId);
|
|
1037
|
+
}
|
|
1038
|
+
async cancelApplicationOwnershipTransfer(appId) {
|
|
1039
|
+
this.requireSigner();
|
|
1040
|
+
return this.registry.cancelApplicationOwnershipTransfer(appId);
|
|
1041
|
+
}
|
|
1042
|
+
async getPendingApplicationOwner(appId) {
|
|
1043
|
+
return this.registry.pendingApplicationOwner(appId);
|
|
1044
|
+
}
|
|
1012
1045
|
// ===== APPLICATIONS =====
|
|
1013
1046
|
async createApplication(name, description, frontendUrl, allowPublicTopicCreation) {
|
|
1014
1047
|
this.requireSigner();
|