clawntenna 0.11.1 → 0.11.2
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 +119 -11
- package/dist/index.cjs +83 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +83 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -216,7 +216,14 @@ var ESCROW_ABI = [
|
|
|
216
216
|
"event DepositRefunded(uint256 indexed depositId, uint256 indexed topicId, address indexed sender, uint256 amount)",
|
|
217
217
|
// V3
|
|
218
218
|
"event DepositReleasedByOwner(uint256 indexed depositId, uint256 indexed topicId, address indexed releasedBy, uint256 messageRef)",
|
|
219
|
-
"event DepositResponseRecorded(uint256 indexed depositId, uint256 indexed topicId, address indexed respondedBy)"
|
|
219
|
+
"event DepositResponseRecorded(uint256 indexed depositId, uint256 indexed topicId, address indexed respondedBy)",
|
|
220
|
+
// V4 — on-chain accumulators + credibility
|
|
221
|
+
"function getRecipientStats(address wallet) view returns (tuple(uint64 depositsReceived, uint64 depositsReleased, uint64 depositsRefunded, uint64 depositsExpired))",
|
|
222
|
+
"function getResponseRate(address wallet) view returns (uint256)",
|
|
223
|
+
"function getCredibility(address wallet) view returns (uint256 responseRate, uint64 depositsReceived, uint64 depositsReleased, uint64 depositsRefunded, uint256 totalEarned, uint256 totalRefunded)",
|
|
224
|
+
"function amountEarned(address wallet) view returns (uint256)",
|
|
225
|
+
"function amountRefunded(address wallet) view returns (uint256)",
|
|
226
|
+
"event RecipientStatsUpdated(address indexed wallet, uint64 received, uint64 released, uint64 refunded)"
|
|
220
227
|
];
|
|
221
228
|
var KEY_MANAGER_ABI = [
|
|
222
229
|
// ===== READ FUNCTIONS =====
|
|
@@ -3970,6 +3977,63 @@ var Clawntenna = class _Clawntenna {
|
|
|
3970
3977
|
async hasResponse(depositId) {
|
|
3971
3978
|
return this.requireEscrow().hasResponse(depositId);
|
|
3972
3979
|
}
|
|
3980
|
+
/**
|
|
3981
|
+
* Get lifetime escrow stats for a wallet (V4).
|
|
3982
|
+
*/
|
|
3983
|
+
async getRecipientStats(wallet) {
|
|
3984
|
+
const s = await this.requireEscrow().getRecipientStats(wallet);
|
|
3985
|
+
return {
|
|
3986
|
+
depositsReceived: BigInt(s.depositsReceived),
|
|
3987
|
+
depositsReleased: BigInt(s.depositsReleased),
|
|
3988
|
+
depositsRefunded: BigInt(s.depositsRefunded),
|
|
3989
|
+
depositsExpired: BigInt(s.depositsExpired)
|
|
3990
|
+
};
|
|
3991
|
+
}
|
|
3992
|
+
/**
|
|
3993
|
+
* Get credibility snapshot for a wallet (V4).
|
|
3994
|
+
* Returns response rate as 0-100 percentage and lifetime escrow totals.
|
|
3995
|
+
*/
|
|
3996
|
+
async getWalletCredibility(wallet) {
|
|
3997
|
+
const escrow = this.requireEscrow();
|
|
3998
|
+
const cred = await escrow.getCredibility(wallet);
|
|
3999
|
+
const responseRate = Number(cred.responseRate) / 100;
|
|
4000
|
+
let formattedEarned = null;
|
|
4001
|
+
let formattedRefunded = null;
|
|
4002
|
+
try {
|
|
4003
|
+
formattedEarned = ethers.formatEther(cred.totalEarned);
|
|
4004
|
+
formattedRefunded = ethers.formatEther(cred.totalRefunded);
|
|
4005
|
+
} catch {
|
|
4006
|
+
}
|
|
4007
|
+
return {
|
|
4008
|
+
responseRate,
|
|
4009
|
+
depositsReceived: BigInt(cred.depositsReceived),
|
|
4010
|
+
depositsReleased: BigInt(cred.depositsReleased),
|
|
4011
|
+
depositsRefunded: BigInt(cred.depositsRefunded),
|
|
4012
|
+
totalEarned: BigInt(cred.totalEarned),
|
|
4013
|
+
totalRefunded: BigInt(cred.totalRefunded),
|
|
4014
|
+
formattedEarned,
|
|
4015
|
+
formattedRefunded
|
|
4016
|
+
};
|
|
4017
|
+
}
|
|
4018
|
+
/**
|
|
4019
|
+
* Get the on-chain total amount earned by a wallet via escrow releases (V4).
|
|
4020
|
+
*/
|
|
4021
|
+
async getAmountEarned(wallet) {
|
|
4022
|
+
return this.requireEscrow().amountEarned(wallet);
|
|
4023
|
+
}
|
|
4024
|
+
/**
|
|
4025
|
+
* Get the on-chain total amount lost to refunds for a wallet (V4).
|
|
4026
|
+
*/
|
|
4027
|
+
async getAmountRefunded(wallet) {
|
|
4028
|
+
return this.requireEscrow().amountRefunded(wallet);
|
|
4029
|
+
}
|
|
4030
|
+
/**
|
|
4031
|
+
* Get response rate for a wallet as basis points (0-10000) (V4).
|
|
4032
|
+
*/
|
|
4033
|
+
async getResponseRate(wallet) {
|
|
4034
|
+
const rate = await this.requireEscrow().getResponseRate(wallet);
|
|
4035
|
+
return Number(rate);
|
|
4036
|
+
}
|
|
3973
4037
|
/**
|
|
3974
4038
|
* Parse a transaction receipt to extract the depositId from a DepositRecorded event.
|
|
3975
4039
|
* Returns null if no DepositRecorded event is found (e.g. no escrow on this tx).
|
|
@@ -4026,6 +4090,22 @@ var Clawntenna = class _Clawntenna {
|
|
|
4026
4090
|
canClaim
|
|
4027
4091
|
};
|
|
4028
4092
|
}
|
|
4093
|
+
// ===== PRIVATE HELPERS =====
|
|
4094
|
+
/**
|
|
4095
|
+
* Query contract events in chunked ranges to stay within public RPC limits.
|
|
4096
|
+
*/
|
|
4097
|
+
async _queryFilterChunked(contract, filter, fromBlock, toBlock, chunkSize = 1e4) {
|
|
4098
|
+
const results = [];
|
|
4099
|
+
for (let start = fromBlock; start <= toBlock; start += chunkSize) {
|
|
4100
|
+
const end = Math.min(start + chunkSize - 1, toBlock);
|
|
4101
|
+
const chunk = await this._wrapRpcError(
|
|
4102
|
+
() => contract.queryFilter(filter, start, end),
|
|
4103
|
+
"queryFilterChunked"
|
|
4104
|
+
);
|
|
4105
|
+
results.push(...chunk);
|
|
4106
|
+
}
|
|
4107
|
+
return results;
|
|
4108
|
+
}
|
|
4029
4109
|
// ===== ESCROW INBOX (deposit → message bridge) =====
|
|
4030
4110
|
/**
|
|
4031
4111
|
* Reverse lookup: find the transaction hash that created a deposit.
|
|
@@ -4037,10 +4117,7 @@ var Clawntenna = class _Clawntenna {
|
|
|
4037
4117
|
const currentBlock = await this.provider.getBlockNumber();
|
|
4038
4118
|
const startBlock = currentBlock - chain.defaultLookback;
|
|
4039
4119
|
const filter = escrow.filters.DepositRecorded(depositId);
|
|
4040
|
-
const events = await this.
|
|
4041
|
-
() => escrow.queryFilter(filter, startBlock, currentBlock),
|
|
4042
|
-
"getDepositTxHash"
|
|
4043
|
-
);
|
|
4120
|
+
const events = await this._queryFilterChunked(escrow, filter, startBlock, currentBlock);
|
|
4044
4121
|
if (events.length === 0) return null;
|
|
4045
4122
|
return events[0].transactionHash;
|
|
4046
4123
|
}
|
|
@@ -4072,10 +4149,7 @@ var Clawntenna = class _Clawntenna {
|
|
|
4072
4149
|
const currentBlock = await this.provider.getBlockNumber();
|
|
4073
4150
|
const startBlock = currentBlock - chain.defaultLookback;
|
|
4074
4151
|
const topicFilter = escrow.filters.DepositRecorded(null, topicId);
|
|
4075
|
-
const events = await this.
|
|
4076
|
-
() => escrow.queryFilter(topicFilter, startBlock, currentBlock),
|
|
4077
|
-
"getEscrowInbox"
|
|
4078
|
-
);
|
|
4152
|
+
const events = await this._queryFilterChunked(escrow, topicFilter, startBlock, currentBlock);
|
|
4079
4153
|
const txHashMap = /* @__PURE__ */ new Map();
|
|
4080
4154
|
for (const evt of events) {
|
|
4081
4155
|
const id = evt.args.depositId.toString();
|
|
@@ -5966,6 +6040,35 @@ Topic #${topicId} inbox (${inbox.length} pending):
|
|
|
5966
6040
|
console.log();
|
|
5967
6041
|
}
|
|
5968
6042
|
}
|
|
6043
|
+
async function escrowStats(address, flags) {
|
|
6044
|
+
const client = loadClient(flags, false);
|
|
6045
|
+
const json = flags.json ?? false;
|
|
6046
|
+
const cred = await client.getWalletCredibility(address);
|
|
6047
|
+
if (json) {
|
|
6048
|
+
output({
|
|
6049
|
+
address,
|
|
6050
|
+
responseRate: cred.responseRate,
|
|
6051
|
+
depositsReceived: cred.depositsReceived.toString(),
|
|
6052
|
+
depositsReleased: cred.depositsReleased.toString(),
|
|
6053
|
+
depositsRefunded: cred.depositsRefunded.toString(),
|
|
6054
|
+
totalEarned: cred.totalEarned.toString(),
|
|
6055
|
+
totalRefunded: cred.totalRefunded.toString(),
|
|
6056
|
+
formattedEarned: cred.formattedEarned,
|
|
6057
|
+
formattedRefunded: cred.formattedRefunded
|
|
6058
|
+
}, true);
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
const shortAddr = address.slice(0, 6) + "..." + address.slice(-4);
|
|
6062
|
+
console.log(`
|
|
6063
|
+
Escrow stats for ${shortAddr}:
|
|
6064
|
+
`);
|
|
6065
|
+
console.log(` Response rate: ${cred.responseRate.toFixed(1)}%`);
|
|
6066
|
+
console.log(` Deposits received: ${cred.depositsReceived}`);
|
|
6067
|
+
console.log(` Released: ${cred.depositsReleased} | Refunded: ${cred.depositsRefunded}`);
|
|
6068
|
+
console.log(` Total earned: ${cred.formattedEarned ?? cred.totalEarned.toString()} ETH`);
|
|
6069
|
+
console.log(` Total refunded: ${cred.formattedRefunded ?? cred.totalRefunded.toString()} ETH`);
|
|
6070
|
+
console.log();
|
|
6071
|
+
}
|
|
5969
6072
|
function formatAgo(epochSeconds) {
|
|
5970
6073
|
const diff = Math.floor(Date.now() / 1e3) - epochSeconds;
|
|
5971
6074
|
if (diff < 60) return `${diff}s ago`;
|
|
@@ -6024,7 +6127,7 @@ function decodeContractError(err) {
|
|
|
6024
6127
|
}
|
|
6025
6128
|
|
|
6026
6129
|
// src/cli/index.ts
|
|
6027
|
-
var VERSION = "0.11.
|
|
6130
|
+
var VERSION = "0.11.2";
|
|
6028
6131
|
var HELP = `
|
|
6029
6132
|
clawntenna v${VERSION}
|
|
6030
6133
|
On-chain encrypted messaging for AI agents
|
|
@@ -6108,6 +6211,7 @@ var HELP = `
|
|
|
6108
6211
|
escrow respond <topicId> <id1> [id2...] --payload 0x Respond to deposits (topic owner)
|
|
6109
6212
|
escrow release <depositId> [--ref N] Release deposit (topic owner)
|
|
6110
6213
|
escrow release-batch <id1> <id2> ... Batch release deposits
|
|
6214
|
+
escrow stats <address> Show wallet credibility & escrow stats
|
|
6111
6215
|
escrow refund <depositId> Claim refund
|
|
6112
6216
|
escrow refund-batch <id1> <id2> ... Batch refund
|
|
6113
6217
|
|
|
@@ -6537,8 +6641,12 @@ async function main() {
|
|
|
6537
6641
|
const ids = args.slice(1).map((a) => parseInt(a, 10));
|
|
6538
6642
|
if (ids.length === 0 || ids.some(isNaN)) outputError("Usage: clawntenna escrow refund-batch <id1> <id2> ...", json);
|
|
6539
6643
|
await escrowRefundBatch(ids, cf);
|
|
6644
|
+
} else if (sub === "stats") {
|
|
6645
|
+
const address = args[1];
|
|
6646
|
+
if (!address) outputError("Usage: clawntenna escrow stats <address>", json);
|
|
6647
|
+
await escrowStats(address, cf);
|
|
6540
6648
|
} else {
|
|
6541
|
-
outputError(`Unknown escrow subcommand: ${sub}. Use: inbox, enable, disable, status, deposits, deposit, respond, release, release-batch, refund, refund-batch`, json);
|
|
6649
|
+
outputError(`Unknown escrow subcommand: ${sub}. Use: inbox, enable, disable, status, stats, deposits, deposit, respond, release, release-batch, refund, refund-batch`, json);
|
|
6542
6650
|
}
|
|
6543
6651
|
break;
|
|
6544
6652
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -302,7 +302,14 @@ var ESCROW_ABI = [
|
|
|
302
302
|
"event DepositRefunded(uint256 indexed depositId, uint256 indexed topicId, address indexed sender, uint256 amount)",
|
|
303
303
|
// V3
|
|
304
304
|
"event DepositReleasedByOwner(uint256 indexed depositId, uint256 indexed topicId, address indexed releasedBy, uint256 messageRef)",
|
|
305
|
-
"event DepositResponseRecorded(uint256 indexed depositId, uint256 indexed topicId, address indexed respondedBy)"
|
|
305
|
+
"event DepositResponseRecorded(uint256 indexed depositId, uint256 indexed topicId, address indexed respondedBy)",
|
|
306
|
+
// V4 — on-chain accumulators + credibility
|
|
307
|
+
"function getRecipientStats(address wallet) view returns (tuple(uint64 depositsReceived, uint64 depositsReleased, uint64 depositsRefunded, uint64 depositsExpired))",
|
|
308
|
+
"function getResponseRate(address wallet) view returns (uint256)",
|
|
309
|
+
"function getCredibility(address wallet) view returns (uint256 responseRate, uint64 depositsReceived, uint64 depositsReleased, uint64 depositsRefunded, uint256 totalEarned, uint256 totalRefunded)",
|
|
310
|
+
"function amountEarned(address wallet) view returns (uint256)",
|
|
311
|
+
"function amountRefunded(address wallet) view returns (uint256)",
|
|
312
|
+
"event RecipientStatsUpdated(address indexed wallet, uint64 received, uint64 released, uint64 refunded)"
|
|
306
313
|
];
|
|
307
314
|
var KEY_MANAGER_ABI = [
|
|
308
315
|
// ===== READ FUNCTIONS =====
|
|
@@ -1170,6 +1177,63 @@ var Clawntenna = class _Clawntenna {
|
|
|
1170
1177
|
async hasResponse(depositId) {
|
|
1171
1178
|
return this.requireEscrow().hasResponse(depositId);
|
|
1172
1179
|
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Get lifetime escrow stats for a wallet (V4).
|
|
1182
|
+
*/
|
|
1183
|
+
async getRecipientStats(wallet) {
|
|
1184
|
+
const s = await this.requireEscrow().getRecipientStats(wallet);
|
|
1185
|
+
return {
|
|
1186
|
+
depositsReceived: BigInt(s.depositsReceived),
|
|
1187
|
+
depositsReleased: BigInt(s.depositsReleased),
|
|
1188
|
+
depositsRefunded: BigInt(s.depositsRefunded),
|
|
1189
|
+
depositsExpired: BigInt(s.depositsExpired)
|
|
1190
|
+
};
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Get credibility snapshot for a wallet (V4).
|
|
1194
|
+
* Returns response rate as 0-100 percentage and lifetime escrow totals.
|
|
1195
|
+
*/
|
|
1196
|
+
async getWalletCredibility(wallet) {
|
|
1197
|
+
const escrow = this.requireEscrow();
|
|
1198
|
+
const cred = await escrow.getCredibility(wallet);
|
|
1199
|
+
const responseRate = Number(cred.responseRate) / 100;
|
|
1200
|
+
let formattedEarned = null;
|
|
1201
|
+
let formattedRefunded = null;
|
|
1202
|
+
try {
|
|
1203
|
+
formattedEarned = import_ethers.ethers.formatEther(cred.totalEarned);
|
|
1204
|
+
formattedRefunded = import_ethers.ethers.formatEther(cred.totalRefunded);
|
|
1205
|
+
} catch {
|
|
1206
|
+
}
|
|
1207
|
+
return {
|
|
1208
|
+
responseRate,
|
|
1209
|
+
depositsReceived: BigInt(cred.depositsReceived),
|
|
1210
|
+
depositsReleased: BigInt(cred.depositsReleased),
|
|
1211
|
+
depositsRefunded: BigInt(cred.depositsRefunded),
|
|
1212
|
+
totalEarned: BigInt(cred.totalEarned),
|
|
1213
|
+
totalRefunded: BigInt(cred.totalRefunded),
|
|
1214
|
+
formattedEarned,
|
|
1215
|
+
formattedRefunded
|
|
1216
|
+
};
|
|
1217
|
+
}
|
|
1218
|
+
/**
|
|
1219
|
+
* Get the on-chain total amount earned by a wallet via escrow releases (V4).
|
|
1220
|
+
*/
|
|
1221
|
+
async getAmountEarned(wallet) {
|
|
1222
|
+
return this.requireEscrow().amountEarned(wallet);
|
|
1223
|
+
}
|
|
1224
|
+
/**
|
|
1225
|
+
* Get the on-chain total amount lost to refunds for a wallet (V4).
|
|
1226
|
+
*/
|
|
1227
|
+
async getAmountRefunded(wallet) {
|
|
1228
|
+
return this.requireEscrow().amountRefunded(wallet);
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* Get response rate for a wallet as basis points (0-10000) (V4).
|
|
1232
|
+
*/
|
|
1233
|
+
async getResponseRate(wallet) {
|
|
1234
|
+
const rate = await this.requireEscrow().getResponseRate(wallet);
|
|
1235
|
+
return Number(rate);
|
|
1236
|
+
}
|
|
1173
1237
|
/**
|
|
1174
1238
|
* Parse a transaction receipt to extract the depositId from a DepositRecorded event.
|
|
1175
1239
|
* Returns null if no DepositRecorded event is found (e.g. no escrow on this tx).
|
|
@@ -1226,6 +1290,22 @@ var Clawntenna = class _Clawntenna {
|
|
|
1226
1290
|
canClaim
|
|
1227
1291
|
};
|
|
1228
1292
|
}
|
|
1293
|
+
// ===== PRIVATE HELPERS =====
|
|
1294
|
+
/**
|
|
1295
|
+
* Query contract events in chunked ranges to stay within public RPC limits.
|
|
1296
|
+
*/
|
|
1297
|
+
async _queryFilterChunked(contract, filter, fromBlock, toBlock, chunkSize = 1e4) {
|
|
1298
|
+
const results = [];
|
|
1299
|
+
for (let start = fromBlock; start <= toBlock; start += chunkSize) {
|
|
1300
|
+
const end = Math.min(start + chunkSize - 1, toBlock);
|
|
1301
|
+
const chunk = await this._wrapRpcError(
|
|
1302
|
+
() => contract.queryFilter(filter, start, end),
|
|
1303
|
+
"queryFilterChunked"
|
|
1304
|
+
);
|
|
1305
|
+
results.push(...chunk);
|
|
1306
|
+
}
|
|
1307
|
+
return results;
|
|
1308
|
+
}
|
|
1229
1309
|
// ===== ESCROW INBOX (deposit → message bridge) =====
|
|
1230
1310
|
/**
|
|
1231
1311
|
* Reverse lookup: find the transaction hash that created a deposit.
|
|
@@ -1237,10 +1317,7 @@ var Clawntenna = class _Clawntenna {
|
|
|
1237
1317
|
const currentBlock = await this.provider.getBlockNumber();
|
|
1238
1318
|
const startBlock = currentBlock - chain.defaultLookback;
|
|
1239
1319
|
const filter = escrow.filters.DepositRecorded(depositId);
|
|
1240
|
-
const events = await this.
|
|
1241
|
-
() => escrow.queryFilter(filter, startBlock, currentBlock),
|
|
1242
|
-
"getDepositTxHash"
|
|
1243
|
-
);
|
|
1320
|
+
const events = await this._queryFilterChunked(escrow, filter, startBlock, currentBlock);
|
|
1244
1321
|
if (events.length === 0) return null;
|
|
1245
1322
|
return events[0].transactionHash;
|
|
1246
1323
|
}
|
|
@@ -1272,10 +1349,7 @@ var Clawntenna = class _Clawntenna {
|
|
|
1272
1349
|
const currentBlock = await this.provider.getBlockNumber();
|
|
1273
1350
|
const startBlock = currentBlock - chain.defaultLookback;
|
|
1274
1351
|
const topicFilter = escrow.filters.DepositRecorded(null, topicId);
|
|
1275
|
-
const events = await this.
|
|
1276
|
-
() => escrow.queryFilter(topicFilter, startBlock, currentBlock),
|
|
1277
|
-
"getEscrowInbox"
|
|
1278
|
-
);
|
|
1352
|
+
const events = await this._queryFilterChunked(escrow, topicFilter, startBlock, currentBlock);
|
|
1279
1353
|
const txHashMap = /* @__PURE__ */ new Map();
|
|
1280
1354
|
for (const evt of events) {
|
|
1281
1355
|
const id = evt.args.depositId.toString();
|