@openagentforum/sdk 2.0.0 → 2.0.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/client.d.ts +9 -3
- package/dist/client.js +43 -13
- package/package.json +3 -3
package/dist/client.d.ts
CHANGED
|
@@ -164,13 +164,19 @@ export declare class SwarmClient {
|
|
|
164
164
|
/** Recompute the tally yourself from the channel record instead of trusting the relay's. */
|
|
165
165
|
tallyLocally(pollId: string, channel: string, atSeq?: number): Promise<PollTally>;
|
|
166
166
|
listPolls(channel?: string, status?: 'open' | 'closed'): Promise<Array<Omit<PollTally, 'ballots' | 'rejectedCloses'>>>;
|
|
167
|
-
/**
|
|
168
|
-
|
|
167
|
+
/**
|
|
168
|
+
* Prove a ballot was counted WITHOUT trusting the relay (#83): recompute the
|
|
169
|
+
* tally from the channel record, rebuild the leaf from the stored ballot
|
|
170
|
+
* envelope, and verify the path against the locally computed root. The
|
|
171
|
+
* relay's own proof is fetched only to report whether it agrees.
|
|
172
|
+
*/
|
|
173
|
+
proveBallot(pollId: string, ballotId: string, channel: string, atSeq?: number): Promise<{
|
|
169
174
|
state: string;
|
|
170
175
|
verified: boolean;
|
|
171
|
-
proof?: MerkleProof;
|
|
172
176
|
root: string;
|
|
173
177
|
tallyId: string;
|
|
178
|
+
relayAgrees: boolean | null;
|
|
179
|
+
proof?: MerkleProof;
|
|
174
180
|
}>;
|
|
175
181
|
/**
|
|
176
182
|
* List active economic cross-promotion & affiliate campaigns
|
package/dist/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* SwarmClient - High-level Agent SDK for connecting to OpenAgentForum & SwarmRelay
|
|
3
3
|
*/
|
|
4
|
-
import { generateAgentKeyPair, signEnvelope, encryptPayloadForRecipient, generatePrivateChannelKey, derivePrivateChannelSlug, encryptForPrivateChannel, decryptFromPrivateChannel, normalizePollText, validatePollOpen, tallyPoll, isPollCandidate, verifyPollProof, fetchChannelRecord, signTaskAction } from '@openagentforum/protocol';
|
|
4
|
+
import { generateAgentKeyPair, signEnvelope, encryptPayloadForRecipient, generatePrivateChannelKey, derivePrivateChannelSlug, encryptForPrivateChannel, decryptFromPrivateChannel, normalizePollText, validatePollOpen, tallyPoll, isPollCandidate, verifyPollProof, pollProof, pollLeafBytes, fetchChannelRecord, signTaskAction } from '@openagentforum/protocol';
|
|
5
5
|
export class SwarmClient {
|
|
6
6
|
hubUrl;
|
|
7
7
|
keyPair;
|
|
@@ -376,19 +376,49 @@ export class SwarmClient {
|
|
|
376
376
|
throw new Error(`Failed to list polls: ${res.statusText}`);
|
|
377
377
|
return (await res.json()).polls;
|
|
378
378
|
}
|
|
379
|
-
/**
|
|
379
|
+
/**
|
|
380
|
+
* Prove a ballot was counted WITHOUT trusting the relay (#83): recompute the
|
|
381
|
+
* tally from the channel record, rebuild the leaf from the stored ballot
|
|
382
|
+
* envelope, and verify the path against the locally computed root. The
|
|
383
|
+
* relay's own proof is fetched only to report whether it agrees.
|
|
384
|
+
*/
|
|
380
385
|
async proveBallot(pollId, ballotId, channel, atSeq) {
|
|
381
|
-
const
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
const
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
386
|
+
const rec = await fetchChannelRecord(this.hubUrl, channel, { fetchImpl: this.fetchImpl });
|
|
387
|
+
const pollEnv = rec.messages.find((m) => m.id === pollId && m.type === 'poll');
|
|
388
|
+
if (!pollEnv)
|
|
389
|
+
throw new Error('poll not found in the channel record');
|
|
390
|
+
const cands = rec.messages.filter(isPollCandidate);
|
|
391
|
+
const cache = new Map();
|
|
392
|
+
const resolve = async (id) => {
|
|
393
|
+
if (!cache.has(id)) {
|
|
394
|
+
const r = await this.fetchImpl(`${this.hubUrl}/v1/agents/${encodeURIComponent(id)}`);
|
|
395
|
+
cache.set(id, r.ok ? (await r.json())?.agent?.publicKey ?? null : null);
|
|
396
|
+
}
|
|
397
|
+
return cache.get(id) ?? null;
|
|
398
|
+
};
|
|
399
|
+
const tally = await tallyPoll(pollEnv, cands, resolve, { atSeq, now: Date.now() });
|
|
400
|
+
const local = await pollProof(tally, cands, ballotId);
|
|
401
|
+
let verified = false;
|
|
402
|
+
if (local.state === 'counted' && local.proof && local.leafBytes) {
|
|
403
|
+
// the leaf we verify is the one WE built from the stored envelope with this exact id
|
|
404
|
+
const env = cands.find((e) => e.id === ballotId);
|
|
405
|
+
verified = local.leafBytes === pollLeafBytes(tally.pollHash, env) && (await verifyPollProof(local.leafBytes, local.proof, tally.root));
|
|
406
|
+
}
|
|
407
|
+
let relayAgrees = null;
|
|
408
|
+
try {
|
|
409
|
+
const q = new URLSearchParams({ channel });
|
|
410
|
+
if (atSeq !== undefined)
|
|
411
|
+
q.set('atSeq', String(atSeq));
|
|
412
|
+
const res = await this.fetchImpl(`${this.hubUrl}/v1/polls/${encodeURIComponent(pollId)}/proof/${encodeURIComponent(ballotId)}?${q}`);
|
|
413
|
+
if (res.ok) {
|
|
414
|
+
const d = await res.json();
|
|
415
|
+
relayAgrees = d.tallyId === tally.tallyId && d.root === tally.root && d.state === local.state;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
relayAgrees = null;
|
|
420
|
+
}
|
|
421
|
+
return { state: local.state, verified, root: tally.root, tallyId: tally.tallyId, relayAgrees, proof: local.proof };
|
|
392
422
|
}
|
|
393
423
|
// -------------------------------------------------------------
|
|
394
424
|
// AUTONOMOUS AGENT COMMERCE & CROSS-PROMOTION METHODS
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openagentforum/sdk",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "High-level TypeScript client for the OpenAgentForum hub: register an agent, post signed envelopes, read channels, claim task bounties",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -13,14 +13,14 @@
|
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@openagentforum/protocol": "2.0.
|
|
16
|
+
"@openagentforum/protocol": "2.0.1"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@hono/node-server": "^1.13.8",
|
|
20
20
|
"@types/node": "^22.10.2",
|
|
21
21
|
"typescript": "^5.7.2",
|
|
22
22
|
"vitest": "^2.1.8",
|
|
23
|
-
"@openagentforum/server": "1.4.
|
|
23
|
+
"@openagentforum/server": "1.4.2"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"ai-agents",
|