clawntenna 0.11.2 → 0.11.4
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 +1 -1
- package/dist/cli/index.js +85 -4
- package/dist/index.cjs +69 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +69 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -315,7 +315,7 @@ await client.sendMessage(topicId, 'reply', {
|
|
|
315
315
|
### Schemas
|
|
316
316
|
|
|
317
317
|
```ts
|
|
318
|
-
// Create app-scoped schema (app admin)
|
|
318
|
+
// Create app-scoped schema (app admin) — CLI --json returns { txHash, blockNumber, appId, schemaId }
|
|
319
319
|
await client.createAppSchema(appId, 'chat-v1', 'Chat format', JSON.stringify({
|
|
320
320
|
"$schema": "clawntenna-message-v1",
|
|
321
321
|
"type": "object",
|
package/dist/cli/index.js
CHANGED
|
@@ -3571,7 +3571,53 @@ var Clawntenna = class _Clawntenna {
|
|
|
3571
3571
|
replyAuthor,
|
|
3572
3572
|
mentions: options?.mentions
|
|
3573
3573
|
});
|
|
3574
|
-
|
|
3574
|
+
const txOverrides = {};
|
|
3575
|
+
try {
|
|
3576
|
+
const fee = await this.getTopicMessageFee(topicId);
|
|
3577
|
+
if (fee.amount > BigInt(0)) {
|
|
3578
|
+
const exempt = await this._isFeeExempt(topicId);
|
|
3579
|
+
if (!exempt) {
|
|
3580
|
+
if (fee.token === ethers.ZeroAddress) {
|
|
3581
|
+
txOverrides.value = fee.amount;
|
|
3582
|
+
} else {
|
|
3583
|
+
const token = new ethers.Contract(fee.token, [
|
|
3584
|
+
"function allowance(address,address) view returns (uint256)",
|
|
3585
|
+
"function approve(address,uint256) returns (bool)"
|
|
3586
|
+
], this._signer);
|
|
3587
|
+
const registryAddr = await this._registry.getAddress();
|
|
3588
|
+
const allowance = await token.allowance(this._address, registryAddr);
|
|
3589
|
+
if (allowance < fee.amount) {
|
|
3590
|
+
const approveTx = await token.approve(registryAddr, fee.amount);
|
|
3591
|
+
await approveTx.wait();
|
|
3592
|
+
}
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
}
|
|
3596
|
+
} catch {
|
|
3597
|
+
}
|
|
3598
|
+
return this.registry.sendMessage(topicId, ethers.toUtf8Bytes(encrypted), txOverrides);
|
|
3599
|
+
}
|
|
3600
|
+
/**
|
|
3601
|
+
* Check if the current signer is exempt from message fees on a topic.
|
|
3602
|
+
* Mirrors contract logic: topic owner, app owner, ROLE_ADMIN, PERMISSION_ADMIN.
|
|
3603
|
+
*/
|
|
3604
|
+
async _isFeeExempt(topicId) {
|
|
3605
|
+
const addr = this._address.toLowerCase();
|
|
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;
|
|
3575
3621
|
}
|
|
3576
3622
|
/**
|
|
3577
3623
|
* Read and decrypt recent messages from a topic.
|
|
@@ -3672,7 +3718,28 @@ var Clawntenna = class _Clawntenna {
|
|
|
3672
3718
|
// ===== TOPICS =====
|
|
3673
3719
|
async createTopic(appId, name, description, accessLevel) {
|
|
3674
3720
|
this.requireSigner();
|
|
3675
|
-
|
|
3721
|
+
const txOverrides = {};
|
|
3722
|
+
try {
|
|
3723
|
+
const app = await this.getApplication(appId);
|
|
3724
|
+
const feeAmount = app.topicCreationFeeAmount ?? BigInt(0);
|
|
3725
|
+
const feeToken = app.topicCreationFeeToken ?? ethers.ZeroAddress;
|
|
3726
|
+
if (feeAmount > BigInt(0) && feeToken === ethers.ZeroAddress) {
|
|
3727
|
+
txOverrides.value = feeAmount;
|
|
3728
|
+
} else if (feeAmount > BigInt(0)) {
|
|
3729
|
+
const token = new ethers.Contract(feeToken, [
|
|
3730
|
+
"function allowance(address,address) view returns (uint256)",
|
|
3731
|
+
"function approve(address,uint256) returns (bool)"
|
|
3732
|
+
], this._signer);
|
|
3733
|
+
const registryAddr = await this._registry.getAddress();
|
|
3734
|
+
const allowance = await token.allowance(this._address, registryAddr);
|
|
3735
|
+
if (allowance < feeAmount) {
|
|
3736
|
+
const approveTx = await token.approve(registryAddr, feeAmount);
|
|
3737
|
+
await approveTx.wait();
|
|
3738
|
+
}
|
|
3739
|
+
}
|
|
3740
|
+
} catch {
|
|
3741
|
+
}
|
|
3742
|
+
return this.registry.createTopic(appId, name, description, accessLevel, txOverrides);
|
|
3676
3743
|
}
|
|
3677
3744
|
async getTopic(topicId) {
|
|
3678
3745
|
return this._wrapRpcError(async () => {
|
|
@@ -5487,9 +5554,23 @@ async function schemaCreate(appId, name, description, body, flags) {
|
|
|
5487
5554
|
if (!json) console.log(`Creating schema "${name}" in app ${appId}...`);
|
|
5488
5555
|
const tx = await client.createAppSchema(appId, name, description, body);
|
|
5489
5556
|
const receipt = await tx.wait();
|
|
5557
|
+
let schemaId = null;
|
|
5558
|
+
if (receipt) {
|
|
5559
|
+
for (const log of receipt.logs) {
|
|
5560
|
+
try {
|
|
5561
|
+
const parsed = client.schemaRegistry.interface.parseLog(log);
|
|
5562
|
+
if (parsed?.name === "AppSchemaCreated" || parsed?.name === "SchemaCreated") {
|
|
5563
|
+
schemaId = Number(parsed.args.schemaId);
|
|
5564
|
+
break;
|
|
5565
|
+
}
|
|
5566
|
+
} catch {
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5569
|
+
}
|
|
5490
5570
|
if (json) {
|
|
5491
|
-
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, appId }, true);
|
|
5571
|
+
output({ txHash: tx.hash, blockNumber: receipt?.blockNumber, appId, schemaId }, true);
|
|
5492
5572
|
} else {
|
|
5573
|
+
console.log(`Schema created${schemaId ? ` (ID: ${schemaId})` : ""}`);
|
|
5493
5574
|
console.log(`TX: ${tx.hash}`);
|
|
5494
5575
|
console.log(`Confirmed in block ${receipt?.blockNumber}`);
|
|
5495
5576
|
}
|
|
@@ -6127,7 +6208,7 @@ function decodeContractError(err) {
|
|
|
6127
6208
|
}
|
|
6128
6209
|
|
|
6129
6210
|
// src/cli/index.ts
|
|
6130
|
-
var VERSION = "0.11.
|
|
6211
|
+
var VERSION = "0.11.4";
|
|
6131
6212
|
var HELP = `
|
|
6132
6213
|
clawntenna v${VERSION}
|
|
6133
6214
|
On-chain encrypted messaging for AI agents
|
package/dist/index.cjs
CHANGED
|
@@ -771,7 +771,53 @@ var Clawntenna = class _Clawntenna {
|
|
|
771
771
|
replyAuthor,
|
|
772
772
|
mentions: options?.mentions
|
|
773
773
|
});
|
|
774
|
-
|
|
774
|
+
const txOverrides = {};
|
|
775
|
+
try {
|
|
776
|
+
const fee = await this.getTopicMessageFee(topicId);
|
|
777
|
+
if (fee.amount > BigInt(0)) {
|
|
778
|
+
const exempt = await this._isFeeExempt(topicId);
|
|
779
|
+
if (!exempt) {
|
|
780
|
+
if (fee.token === import_ethers.ethers.ZeroAddress) {
|
|
781
|
+
txOverrides.value = fee.amount;
|
|
782
|
+
} else {
|
|
783
|
+
const token = new import_ethers.ethers.Contract(fee.token, [
|
|
784
|
+
"function allowance(address,address) view returns (uint256)",
|
|
785
|
+
"function approve(address,uint256) returns (bool)"
|
|
786
|
+
], this._signer);
|
|
787
|
+
const registryAddr = await this._registry.getAddress();
|
|
788
|
+
const allowance = await token.allowance(this._address, registryAddr);
|
|
789
|
+
if (allowance < fee.amount) {
|
|
790
|
+
const approveTx = await token.approve(registryAddr, fee.amount);
|
|
791
|
+
await approveTx.wait();
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
} catch {
|
|
797
|
+
}
|
|
798
|
+
return this.registry.sendMessage(topicId, import_ethers.ethers.toUtf8Bytes(encrypted), txOverrides);
|
|
799
|
+
}
|
|
800
|
+
/**
|
|
801
|
+
* Check if the current signer is exempt from message fees on a topic.
|
|
802
|
+
* Mirrors contract logic: topic owner, app owner, ROLE_ADMIN, PERMISSION_ADMIN.
|
|
803
|
+
*/
|
|
804
|
+
async _isFeeExempt(topicId) {
|
|
805
|
+
const addr = this._address.toLowerCase();
|
|
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;
|
|
775
821
|
}
|
|
776
822
|
/**
|
|
777
823
|
* Read and decrypt recent messages from a topic.
|
|
@@ -872,7 +918,28 @@ var Clawntenna = class _Clawntenna {
|
|
|
872
918
|
// ===== TOPICS =====
|
|
873
919
|
async createTopic(appId, name, description, accessLevel) {
|
|
874
920
|
this.requireSigner();
|
|
875
|
-
|
|
921
|
+
const txOverrides = {};
|
|
922
|
+
try {
|
|
923
|
+
const app = await this.getApplication(appId);
|
|
924
|
+
const feeAmount = app.topicCreationFeeAmount ?? BigInt(0);
|
|
925
|
+
const feeToken = app.topicCreationFeeToken ?? import_ethers.ethers.ZeroAddress;
|
|
926
|
+
if (feeAmount > BigInt(0) && feeToken === import_ethers.ethers.ZeroAddress) {
|
|
927
|
+
txOverrides.value = feeAmount;
|
|
928
|
+
} else if (feeAmount > BigInt(0)) {
|
|
929
|
+
const token = new import_ethers.ethers.Contract(feeToken, [
|
|
930
|
+
"function allowance(address,address) view returns (uint256)",
|
|
931
|
+
"function approve(address,uint256) returns (bool)"
|
|
932
|
+
], this._signer);
|
|
933
|
+
const registryAddr = await this._registry.getAddress();
|
|
934
|
+
const allowance = await token.allowance(this._address, registryAddr);
|
|
935
|
+
if (allowance < feeAmount) {
|
|
936
|
+
const approveTx = await token.approve(registryAddr, feeAmount);
|
|
937
|
+
await approveTx.wait();
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
} catch {
|
|
941
|
+
}
|
|
942
|
+
return this.registry.createTopic(appId, name, description, accessLevel, txOverrides);
|
|
876
943
|
}
|
|
877
944
|
async getTopic(topicId) {
|
|
878
945
|
return this._wrapRpcError(async () => {
|