arcbounty-agent-sdk 0.1.0 → 0.3.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/README.md +136 -2
- package/dist/index.d.mts +232 -11
- package/dist/index.d.ts +232 -11
- package/dist/index.js +392 -143
- package/dist/index.mjs +383 -139
- package/package.json +11 -3
- package/.env.example +0 -13
- package/examples/demo-agent.ts +0 -94
- package/src/ArcBountyAgent.ts +0 -645
- package/src/abi.ts +0 -386
- package/src/constants.ts +0 -20
- package/src/index.ts +0 -21
- package/src/ipfs.ts +0 -80
- package/src/metadata.ts +0 -69
- package/src/types.ts +0 -105
- package/tsconfig.json +0 -13
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { Address, Hash } from 'viem';
|
|
2
2
|
|
|
3
|
-
type
|
|
4
|
-
/**
|
|
5
|
-
|
|
3
|
+
type CircleWalletConfig = {
|
|
4
|
+
/** Circle API key (Circle Console → Testnet/Mainnet → API Keys → API Key, Standard). */
|
|
5
|
+
apiKey: string;
|
|
6
|
+
/** Registered entity secret — see docs/circle-wallet.md. Controls every wallet under this API key. */
|
|
7
|
+
entitySecret: string;
|
|
8
|
+
/** Circle wallet ID (from `createWallets`/`listWallets`), not the on-chain address. */
|
|
9
|
+
walletId: string;
|
|
10
|
+
/** The wallet's on-chain address — fetch once via `getWallet({ id })` and store it; avoids an extra round-trip on every agent startup. */
|
|
11
|
+
address: Address;
|
|
12
|
+
/** Override Circle's API base URL (defaults to https://api.circle.com). */
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
type ArcBountyAgentConfigBase = {
|
|
6
17
|
/** Arc RPC URL */
|
|
7
18
|
rpcUrl?: string;
|
|
8
19
|
/** IPFS metadata URI for agent registration (ipfs://Qm...) */
|
|
@@ -10,6 +21,15 @@ type ArcBountyAgentConfig = {
|
|
|
10
21
|
/** BountyAdapter contract address (overrides default) */
|
|
11
22
|
bountyAdapterAddress?: Address;
|
|
12
23
|
};
|
|
24
|
+
type ArcBountyAgentConfig = ArcBountyAgentConfigBase & ({
|
|
25
|
+
/** Private key of the agent wallet (0x-prefixed hex). Mutually exclusive with `circleWallet`. */
|
|
26
|
+
privateKey: Hash;
|
|
27
|
+
circleWallet?: never;
|
|
28
|
+
} | {
|
|
29
|
+
privateKey?: never;
|
|
30
|
+
/** Sign via a Circle developer-controlled wallet instead of a raw private key. Mutually exclusive with `privateKey`. */
|
|
31
|
+
circleWallet: CircleWalletConfig;
|
|
32
|
+
});
|
|
13
33
|
type BountyMeta = {
|
|
14
34
|
jobId: bigint;
|
|
15
35
|
poster: Address;
|
|
@@ -35,6 +55,8 @@ type BountyMeta = {
|
|
|
35
55
|
disputeReasonHash: string;
|
|
36
56
|
disputeResponseHash: string;
|
|
37
57
|
disputeRulingHash: string;
|
|
58
|
+
requireWorkerBond: boolean;
|
|
59
|
+
workerBond: bigint;
|
|
38
60
|
};
|
|
39
61
|
type ReputationScore = {
|
|
40
62
|
averageScore: bigint;
|
|
@@ -65,6 +87,8 @@ type CreateBountyOptions = {
|
|
|
65
87
|
provider?: Address;
|
|
66
88
|
agentOnly?: boolean;
|
|
67
89
|
humanOnly?: boolean;
|
|
90
|
+
/** V4: require the worker to post a bond (refunded at submitWork, forfeited to you if they vanish). */
|
|
91
|
+
requireWorkerBond?: boolean;
|
|
68
92
|
};
|
|
69
93
|
type SubmitWorkOptions = {
|
|
70
94
|
/** Raw text/markdown result — will be pinned to IPFS */
|
|
@@ -90,8 +114,7 @@ type TxResult = {
|
|
|
90
114
|
|
|
91
115
|
declare class ArcBountyAgent {
|
|
92
116
|
private readonly publicClient;
|
|
93
|
-
private readonly
|
|
94
|
-
private readonly account;
|
|
117
|
+
private readonly signer;
|
|
95
118
|
private readonly bountyAdapter;
|
|
96
119
|
private readonly metadataURI;
|
|
97
120
|
private readonly chain;
|
|
@@ -99,8 +122,6 @@ declare class ArcBountyAgent {
|
|
|
99
122
|
constructor(config: ArcBountyAgentConfig);
|
|
100
123
|
get address(): Address;
|
|
101
124
|
register(): Promise<bigint>;
|
|
102
|
-
/** Pull the minted tokenId from a Transfer(from=0x0, to=self) log in a receipt. */
|
|
103
|
-
private _agentIdFromReceiptLogs;
|
|
104
125
|
get agentId(): bigint;
|
|
105
126
|
setAgentId(id: bigint): void;
|
|
106
127
|
listOpenBounties(filter?: OpenBountiesFilter): Promise<BountyMeta[]>;
|
|
@@ -133,14 +154,39 @@ declare class ArcBountyAgent {
|
|
|
133
154
|
resolveDispute(jobId: bigint, payProvider: boolean, ruling: DisputeEvidenceOptions, reputationPenalty?: number): Promise<TxResult>;
|
|
134
155
|
/** After 48h with no response, anyone may claim the default ruling. */
|
|
135
156
|
claimDefaultRuling(jobId: bigint): Promise<TxResult>;
|
|
157
|
+
/**
|
|
158
|
+
* V3.3 liveness fallback: if the respondent DID reply (so claimDefaultRuling
|
|
159
|
+
* no longer applies) but the arbitrator never called resolveDispute within
|
|
160
|
+
* ARBITRATOR_TIMEOUT (30d) of disputeRaisedAt, anyone may trigger a neutral
|
|
161
|
+
* 50/50 split between poster and worker. No reputation penalty either way.
|
|
162
|
+
*/
|
|
163
|
+
claimArbitratorTimeout(jobId: bigint): Promise<TxResult>;
|
|
136
164
|
/** Worker challenges a pending rejection — flips bounty into dispute with worker as initiator. */
|
|
137
165
|
challengeRejection(jobId: bigint, evidence: DisputeEvidenceOptions): Promise<TxResult>;
|
|
138
166
|
/** Open a dispute (either party — after submission, before resolution). */
|
|
139
167
|
disputeBounty(jobId: bigint, evidence: DisputeEvidenceOptions): Promise<TxResult>;
|
|
140
168
|
/** Respond to an open dispute (only the non-initiator may call). */
|
|
141
169
|
respondToDispute(jobId: bigint, evidence: DisputeEvidenceOptions): Promise<TxResult>;
|
|
170
|
+
/**
|
|
171
|
+
* Scans the full bounty set and calls expireBounty() on anything past its
|
|
172
|
+
* deadline with no submission and not yet resolved. Stops after finding
|
|
173
|
+
* `limit` candidates to expire.
|
|
174
|
+
*
|
|
175
|
+
* NOTE: `getOpenBounties` (used pre-V3.3) can NEVER return a candidate for
|
|
176
|
+
* this — it excludes any bounty whose deadline has already passed by
|
|
177
|
+
* definition (`_isOpenMatch` checks `block.timestamp <= deadline`). This
|
|
178
|
+
* scan walks `allJobIds` directly instead, mirroring the keeper cron route
|
|
179
|
+
* (`frontend/app/api/cron/keeper/route.ts`).
|
|
180
|
+
*/
|
|
142
181
|
expireStale(category?: string, limit?: number): Promise<bigint[]>;
|
|
143
182
|
getReputation(agentId?: bigint): Promise<ReputationScore>;
|
|
183
|
+
/**
|
|
184
|
+
* V4 anti-Sybil signal: count of distinct posters who've actually paid out
|
|
185
|
+
* a completed bounty to this agent. Costs N real funded wallets to fake N —
|
|
186
|
+
* unlike the raw ERC-8004 average score, which one alt account can inflate
|
|
187
|
+
* for a few cents. See V4_DESIGN_ANTI_SYBIL.md.
|
|
188
|
+
*/
|
|
189
|
+
getUniquePosterCount(agentId?: bigint): Promise<bigint>;
|
|
144
190
|
getAgentInfo(): Promise<AgentInfo>;
|
|
145
191
|
usdcBalance(): Promise<bigint>;
|
|
146
192
|
formatUsdc(raw: bigint): string;
|
|
@@ -153,7 +199,39 @@ declare class ArcBountyAgent {
|
|
|
153
199
|
* If you need durable dedup across restarts, persist `seenJobIds` yourself.
|
|
154
200
|
*/
|
|
155
201
|
subscribeToNewBounties(filter: OpenBountiesFilter, onMatch: (meta: BountyMeta) => void | Promise<void>): () => void;
|
|
156
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Background watchdog over this agent's own assigned bounties. An agent
|
|
204
|
+
* that only calls `takeBounty`/`submitWork` and then goes idle is exposed
|
|
205
|
+
* to every counterparty-controlled window in the contract: a poster can
|
|
206
|
+
* reject a correct submission (48h to challenge), open a dispute the agent
|
|
207
|
+
* never responds to (48h to respond, then the *other* side wins by
|
|
208
|
+
* default), or the agent may simply be owed a payout nobody triggered yet
|
|
209
|
+
* (14d autoApprove / 30d claimArbitratorTimeout). `protect()` polls
|
|
210
|
+
* `getMyBounties()` and reacts automatically:
|
|
211
|
+
*
|
|
212
|
+
* - **Pending rejection, not yet challenged** → calls `onRejection` (if
|
|
213
|
+
* provided) for evidence and calls `challengeRejection`. Without a
|
|
214
|
+
* callback, a rejection is only logged, never auto-challenged — silently
|
|
215
|
+
* auto-disputing every rejection would be its own failure mode.
|
|
216
|
+
* - **Dispute raised by the other party, not yet responded** → calls
|
|
217
|
+
* `onDisputeAgainstMe` for evidence and calls `respondToDispute`. Same
|
|
218
|
+
* caveat: no callback means log-only.
|
|
219
|
+
* - **Dispute resolved-by-response but arbitrator never ruled (30d)** →
|
|
220
|
+
* calls `claimArbitratorTimeout` automatically (permissionless, no
|
|
221
|
+
* evidence needed — this just unsticks the agent's own frozen funds).
|
|
222
|
+
* - **Submitted, approval window elapsed (14d), poster silent** → calls
|
|
223
|
+
* `autoApprove` automatically.
|
|
224
|
+
*
|
|
225
|
+
* Returns an `unwatch()` function. Errors on any single bounty are logged
|
|
226
|
+
* and swallowed so one bad case can't kill the whole watchdog.
|
|
227
|
+
*/
|
|
228
|
+
protect(options?: {
|
|
229
|
+
pollingIntervalMs?: number;
|
|
230
|
+
onRejection?: (meta: BountyMeta) => Promise<DisputeEvidenceOptions>;
|
|
231
|
+
onDisputeAgainstMe?: (meta: BountyMeta) => Promise<DisputeEvidenceOptions>;
|
|
232
|
+
onEvent?: (event: string, meta: BountyMeta) => void;
|
|
233
|
+
}): () => void;
|
|
234
|
+
private _protectOnce;
|
|
157
235
|
runOnce(filter: OpenBountiesFilter, runTask: (description: string, meta: BountyMeta) => Promise<string>): Promise<bigint | null>;
|
|
158
236
|
private _waitForTx;
|
|
159
237
|
/**
|
|
@@ -174,8 +252,6 @@ declare class ArcBountyAgent {
|
|
|
174
252
|
private _findExistingAgentId;
|
|
175
253
|
private _ensureUsdcAllowance;
|
|
176
254
|
private _resolveEvidenceCid;
|
|
177
|
-
private _resolveDeadline;
|
|
178
|
-
private _parseUsdc;
|
|
179
255
|
}
|
|
180
256
|
|
|
181
257
|
declare const ARC_TESTNET_RPC = "https://rpc.testnet.arc.network";
|
|
@@ -187,6 +263,18 @@ declare const CONTRACTS: {
|
|
|
187
263
|
readonly USDC: Address;
|
|
188
264
|
};
|
|
189
265
|
|
|
266
|
+
declare function parseUsdc(dollars: number): bigint;
|
|
267
|
+
/** `d` < 1e9 is interpreted as duration-in-seconds from `nowSec` (~30yr cutoff). */
|
|
268
|
+
declare function resolveDeadline(d: number | Date, nowSec?: number): bigint;
|
|
269
|
+
/**
|
|
270
|
+
* V4 worker bond: max(minBond, reward * bondBps / 10_000). Mirrors
|
|
271
|
+
* BountyAdapter._workerBondFor. Defaults are the live V4 parameters
|
|
272
|
+
* (15% / $0.50 floor); pass the on-chain WORKER_BOND_BPS / MIN_WORKER_BOND
|
|
273
|
+
* values to stay correct across redeploys with different parameters.
|
|
274
|
+
*/
|
|
275
|
+
declare function workerBondFor(reward: bigint, bondBps?: bigint, minBond?: bigint): bigint;
|
|
276
|
+
declare function matchesBountyFilter(m: BountyMeta, f: OpenBountiesFilter): boolean;
|
|
277
|
+
|
|
190
278
|
declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
191
279
|
readonly name: "createBounty";
|
|
192
280
|
readonly type: "function";
|
|
@@ -218,6 +306,9 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
218
306
|
}, {
|
|
219
307
|
readonly name: "humanOnly";
|
|
220
308
|
readonly type: "bool";
|
|
309
|
+
}, {
|
|
310
|
+
readonly name: "requireWorkerBond";
|
|
311
|
+
readonly type: "bool";
|
|
221
312
|
}];
|
|
222
313
|
}];
|
|
223
314
|
readonly outputs: readonly [{
|
|
@@ -371,6 +462,27 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
371
462
|
readonly type: "uint256";
|
|
372
463
|
}];
|
|
373
464
|
readonly outputs: readonly [];
|
|
465
|
+
}, {
|
|
466
|
+
readonly name: "claimArbitratorTimeout";
|
|
467
|
+
readonly type: "function";
|
|
468
|
+
readonly stateMutability: "nonpayable";
|
|
469
|
+
readonly inputs: readonly [{
|
|
470
|
+
readonly name: "jobId";
|
|
471
|
+
readonly type: "uint256";
|
|
472
|
+
}];
|
|
473
|
+
readonly outputs: readonly [];
|
|
474
|
+
}, {
|
|
475
|
+
readonly name: "allJobIds";
|
|
476
|
+
readonly type: "function";
|
|
477
|
+
readonly stateMutability: "view";
|
|
478
|
+
readonly inputs: readonly [{
|
|
479
|
+
readonly name: "";
|
|
480
|
+
readonly type: "uint256";
|
|
481
|
+
}];
|
|
482
|
+
readonly outputs: readonly [{
|
|
483
|
+
readonly name: "";
|
|
484
|
+
readonly type: "uint256";
|
|
485
|
+
}];
|
|
374
486
|
}, {
|
|
375
487
|
readonly name: "getOpenBounties";
|
|
376
488
|
readonly type: "function";
|
|
@@ -472,6 +584,12 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
472
584
|
}, {
|
|
473
585
|
readonly name: "disputeRulingHash";
|
|
474
586
|
readonly type: "string";
|
|
587
|
+
}, {
|
|
588
|
+
readonly name: "requireWorkerBond";
|
|
589
|
+
readonly type: "bool";
|
|
590
|
+
}, {
|
|
591
|
+
readonly name: "workerBond";
|
|
592
|
+
readonly type: "uint256";
|
|
475
593
|
}];
|
|
476
594
|
}];
|
|
477
595
|
}, {
|
|
@@ -577,6 +695,45 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
577
695
|
readonly name: "";
|
|
578
696
|
readonly type: "uint256";
|
|
579
697
|
}];
|
|
698
|
+
}, {
|
|
699
|
+
readonly name: "ARBITRATOR_TIMEOUT";
|
|
700
|
+
readonly type: "function";
|
|
701
|
+
readonly stateMutability: "view";
|
|
702
|
+
readonly inputs: readonly [];
|
|
703
|
+
readonly outputs: readonly [{
|
|
704
|
+
readonly name: "";
|
|
705
|
+
readonly type: "uint256";
|
|
706
|
+
}];
|
|
707
|
+
}, {
|
|
708
|
+
readonly name: "uniquePosterCount";
|
|
709
|
+
readonly type: "function";
|
|
710
|
+
readonly stateMutability: "view";
|
|
711
|
+
readonly inputs: readonly [{
|
|
712
|
+
readonly name: "agentId";
|
|
713
|
+
readonly type: "uint256";
|
|
714
|
+
}];
|
|
715
|
+
readonly outputs: readonly [{
|
|
716
|
+
readonly name: "";
|
|
717
|
+
readonly type: "uint256";
|
|
718
|
+
}];
|
|
719
|
+
}, {
|
|
720
|
+
readonly name: "WORKER_BOND_BPS";
|
|
721
|
+
readonly type: "function";
|
|
722
|
+
readonly stateMutability: "view";
|
|
723
|
+
readonly inputs: readonly [];
|
|
724
|
+
readonly outputs: readonly [{
|
|
725
|
+
readonly name: "";
|
|
726
|
+
readonly type: "uint256";
|
|
727
|
+
}];
|
|
728
|
+
}, {
|
|
729
|
+
readonly name: "MIN_WORKER_BOND";
|
|
730
|
+
readonly type: "function";
|
|
731
|
+
readonly stateMutability: "view";
|
|
732
|
+
readonly inputs: readonly [];
|
|
733
|
+
readonly outputs: readonly [{
|
|
734
|
+
readonly name: "";
|
|
735
|
+
readonly type: "uint256";
|
|
736
|
+
}];
|
|
580
737
|
}, {
|
|
581
738
|
readonly name: "BountyCreated";
|
|
582
739
|
readonly type: "event";
|
|
@@ -701,6 +858,70 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
701
858
|
readonly type: "bool";
|
|
702
859
|
readonly indexed: false;
|
|
703
860
|
}];
|
|
861
|
+
}, {
|
|
862
|
+
readonly name: "ArbitratorTimeoutClaimed";
|
|
863
|
+
readonly type: "event";
|
|
864
|
+
readonly inputs: readonly [{
|
|
865
|
+
readonly name: "jobId";
|
|
866
|
+
readonly type: "uint256";
|
|
867
|
+
readonly indexed: true;
|
|
868
|
+
}, {
|
|
869
|
+
readonly name: "posterAmount";
|
|
870
|
+
readonly type: "uint256";
|
|
871
|
+
readonly indexed: false;
|
|
872
|
+
}, {
|
|
873
|
+
readonly name: "providerAmount";
|
|
874
|
+
readonly type: "uint256";
|
|
875
|
+
readonly indexed: false;
|
|
876
|
+
}];
|
|
877
|
+
}, {
|
|
878
|
+
readonly name: "WorkerBondPosted";
|
|
879
|
+
readonly type: "event";
|
|
880
|
+
readonly inputs: readonly [{
|
|
881
|
+
readonly name: "jobId";
|
|
882
|
+
readonly type: "uint256";
|
|
883
|
+
readonly indexed: true;
|
|
884
|
+
}, {
|
|
885
|
+
readonly name: "worker";
|
|
886
|
+
readonly type: "address";
|
|
887
|
+
readonly indexed: true;
|
|
888
|
+
}, {
|
|
889
|
+
readonly name: "amount";
|
|
890
|
+
readonly type: "uint256";
|
|
891
|
+
readonly indexed: false;
|
|
892
|
+
}];
|
|
893
|
+
}, {
|
|
894
|
+
readonly name: "WorkerBondRefunded";
|
|
895
|
+
readonly type: "event";
|
|
896
|
+
readonly inputs: readonly [{
|
|
897
|
+
readonly name: "jobId";
|
|
898
|
+
readonly type: "uint256";
|
|
899
|
+
readonly indexed: true;
|
|
900
|
+
}, {
|
|
901
|
+
readonly name: "worker";
|
|
902
|
+
readonly type: "address";
|
|
903
|
+
readonly indexed: true;
|
|
904
|
+
}, {
|
|
905
|
+
readonly name: "amount";
|
|
906
|
+
readonly type: "uint256";
|
|
907
|
+
readonly indexed: false;
|
|
908
|
+
}];
|
|
909
|
+
}, {
|
|
910
|
+
readonly name: "WorkerBondForfeited";
|
|
911
|
+
readonly type: "event";
|
|
912
|
+
readonly inputs: readonly [{
|
|
913
|
+
readonly name: "jobId";
|
|
914
|
+
readonly type: "uint256";
|
|
915
|
+
readonly indexed: true;
|
|
916
|
+
}, {
|
|
917
|
+
readonly name: "poster";
|
|
918
|
+
readonly type: "address";
|
|
919
|
+
readonly indexed: true;
|
|
920
|
+
}, {
|
|
921
|
+
readonly name: "amount";
|
|
922
|
+
readonly type: "uint256";
|
|
923
|
+
readonly indexed: false;
|
|
924
|
+
}];
|
|
704
925
|
}];
|
|
705
926
|
declare const IDENTITY_REGISTRY_ABI: readonly [{
|
|
706
927
|
readonly name: "register";
|
|
@@ -832,4 +1053,4 @@ declare function validateAgentMetadata(m: unknown): asserts m is AgentMetadata;
|
|
|
832
1053
|
/** Pin a validated metadata blob to IPFS and return the `ipfs://<cid>` URI. */
|
|
833
1054
|
declare function pinAgentMetadata(meta: AgentMetadata): Promise<string>;
|
|
834
1055
|
|
|
835
|
-
export { ARC_TESTNET_CHAIN_ID, ARC_TESTNET_RPC, type AgentInfo, type AgentMetadata, ArcBountyAgent, type ArcBountyAgentConfig, type ArcBountySection, BOUNTY_ADAPTER_ABI, type BountyMeta, CONTRACTS, type CreateBountyOptions, type DisputeEvidenceOptions, ERC20_ABI, IDENTITY_REGISTRY_ABI, type OpenBountiesFilter, type ReputationScore, type SubmitWorkOptions, type TxResult, fetchIpfsJson, fetchIpfsText, isPinningConfigured, pinAgentMetadata, pinText, validateAgentMetadata };
|
|
1056
|
+
export { ARC_TESTNET_CHAIN_ID, ARC_TESTNET_RPC, type AgentInfo, type AgentMetadata, ArcBountyAgent, type ArcBountyAgentConfig, type ArcBountySection, BOUNTY_ADAPTER_ABI, type BountyMeta, CONTRACTS, type CircleWalletConfig, type CreateBountyOptions, type DisputeEvidenceOptions, ERC20_ABI, IDENTITY_REGISTRY_ABI, type OpenBountiesFilter, type ReputationScore, type SubmitWorkOptions, type TxResult, fetchIpfsJson, fetchIpfsText, isPinningConfigured, matchesBountyFilter, parseUsdc, pinAgentMetadata, pinText, resolveDeadline, validateAgentMetadata, workerBondFor };
|