arcbounty-agent-sdk 0.1.0 → 0.3.0
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 +126 -0
- package/dist/index.d.mts +220 -11
- package/dist/index.d.ts +220 -11
- package/dist/index.js +362 -141
- package/dist/index.mjs +358 -138
- 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";
|
|
@@ -218,6 +294,9 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
218
294
|
}, {
|
|
219
295
|
readonly name: "humanOnly";
|
|
220
296
|
readonly type: "bool";
|
|
297
|
+
}, {
|
|
298
|
+
readonly name: "requireWorkerBond";
|
|
299
|
+
readonly type: "bool";
|
|
221
300
|
}];
|
|
222
301
|
}];
|
|
223
302
|
readonly outputs: readonly [{
|
|
@@ -371,6 +450,27 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
371
450
|
readonly type: "uint256";
|
|
372
451
|
}];
|
|
373
452
|
readonly outputs: readonly [];
|
|
453
|
+
}, {
|
|
454
|
+
readonly name: "claimArbitratorTimeout";
|
|
455
|
+
readonly type: "function";
|
|
456
|
+
readonly stateMutability: "nonpayable";
|
|
457
|
+
readonly inputs: readonly [{
|
|
458
|
+
readonly name: "jobId";
|
|
459
|
+
readonly type: "uint256";
|
|
460
|
+
}];
|
|
461
|
+
readonly outputs: readonly [];
|
|
462
|
+
}, {
|
|
463
|
+
readonly name: "allJobIds";
|
|
464
|
+
readonly type: "function";
|
|
465
|
+
readonly stateMutability: "view";
|
|
466
|
+
readonly inputs: readonly [{
|
|
467
|
+
readonly name: "";
|
|
468
|
+
readonly type: "uint256";
|
|
469
|
+
}];
|
|
470
|
+
readonly outputs: readonly [{
|
|
471
|
+
readonly name: "";
|
|
472
|
+
readonly type: "uint256";
|
|
473
|
+
}];
|
|
374
474
|
}, {
|
|
375
475
|
readonly name: "getOpenBounties";
|
|
376
476
|
readonly type: "function";
|
|
@@ -472,6 +572,12 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
472
572
|
}, {
|
|
473
573
|
readonly name: "disputeRulingHash";
|
|
474
574
|
readonly type: "string";
|
|
575
|
+
}, {
|
|
576
|
+
readonly name: "requireWorkerBond";
|
|
577
|
+
readonly type: "bool";
|
|
578
|
+
}, {
|
|
579
|
+
readonly name: "workerBond";
|
|
580
|
+
readonly type: "uint256";
|
|
475
581
|
}];
|
|
476
582
|
}];
|
|
477
583
|
}, {
|
|
@@ -577,6 +683,45 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
577
683
|
readonly name: "";
|
|
578
684
|
readonly type: "uint256";
|
|
579
685
|
}];
|
|
686
|
+
}, {
|
|
687
|
+
readonly name: "ARBITRATOR_TIMEOUT";
|
|
688
|
+
readonly type: "function";
|
|
689
|
+
readonly stateMutability: "view";
|
|
690
|
+
readonly inputs: readonly [];
|
|
691
|
+
readonly outputs: readonly [{
|
|
692
|
+
readonly name: "";
|
|
693
|
+
readonly type: "uint256";
|
|
694
|
+
}];
|
|
695
|
+
}, {
|
|
696
|
+
readonly name: "uniquePosterCount";
|
|
697
|
+
readonly type: "function";
|
|
698
|
+
readonly stateMutability: "view";
|
|
699
|
+
readonly inputs: readonly [{
|
|
700
|
+
readonly name: "agentId";
|
|
701
|
+
readonly type: "uint256";
|
|
702
|
+
}];
|
|
703
|
+
readonly outputs: readonly [{
|
|
704
|
+
readonly name: "";
|
|
705
|
+
readonly type: "uint256";
|
|
706
|
+
}];
|
|
707
|
+
}, {
|
|
708
|
+
readonly name: "WORKER_BOND_BPS";
|
|
709
|
+
readonly type: "function";
|
|
710
|
+
readonly stateMutability: "view";
|
|
711
|
+
readonly inputs: readonly [];
|
|
712
|
+
readonly outputs: readonly [{
|
|
713
|
+
readonly name: "";
|
|
714
|
+
readonly type: "uint256";
|
|
715
|
+
}];
|
|
716
|
+
}, {
|
|
717
|
+
readonly name: "MIN_WORKER_BOND";
|
|
718
|
+
readonly type: "function";
|
|
719
|
+
readonly stateMutability: "view";
|
|
720
|
+
readonly inputs: readonly [];
|
|
721
|
+
readonly outputs: readonly [{
|
|
722
|
+
readonly name: "";
|
|
723
|
+
readonly type: "uint256";
|
|
724
|
+
}];
|
|
580
725
|
}, {
|
|
581
726
|
readonly name: "BountyCreated";
|
|
582
727
|
readonly type: "event";
|
|
@@ -701,6 +846,70 @@ declare const BOUNTY_ADAPTER_ABI: readonly [{
|
|
|
701
846
|
readonly type: "bool";
|
|
702
847
|
readonly indexed: false;
|
|
703
848
|
}];
|
|
849
|
+
}, {
|
|
850
|
+
readonly name: "ArbitratorTimeoutClaimed";
|
|
851
|
+
readonly type: "event";
|
|
852
|
+
readonly inputs: readonly [{
|
|
853
|
+
readonly name: "jobId";
|
|
854
|
+
readonly type: "uint256";
|
|
855
|
+
readonly indexed: true;
|
|
856
|
+
}, {
|
|
857
|
+
readonly name: "posterAmount";
|
|
858
|
+
readonly type: "uint256";
|
|
859
|
+
readonly indexed: false;
|
|
860
|
+
}, {
|
|
861
|
+
readonly name: "providerAmount";
|
|
862
|
+
readonly type: "uint256";
|
|
863
|
+
readonly indexed: false;
|
|
864
|
+
}];
|
|
865
|
+
}, {
|
|
866
|
+
readonly name: "WorkerBondPosted";
|
|
867
|
+
readonly type: "event";
|
|
868
|
+
readonly inputs: readonly [{
|
|
869
|
+
readonly name: "jobId";
|
|
870
|
+
readonly type: "uint256";
|
|
871
|
+
readonly indexed: true;
|
|
872
|
+
}, {
|
|
873
|
+
readonly name: "worker";
|
|
874
|
+
readonly type: "address";
|
|
875
|
+
readonly indexed: true;
|
|
876
|
+
}, {
|
|
877
|
+
readonly name: "amount";
|
|
878
|
+
readonly type: "uint256";
|
|
879
|
+
readonly indexed: false;
|
|
880
|
+
}];
|
|
881
|
+
}, {
|
|
882
|
+
readonly name: "WorkerBondRefunded";
|
|
883
|
+
readonly type: "event";
|
|
884
|
+
readonly inputs: readonly [{
|
|
885
|
+
readonly name: "jobId";
|
|
886
|
+
readonly type: "uint256";
|
|
887
|
+
readonly indexed: true;
|
|
888
|
+
}, {
|
|
889
|
+
readonly name: "worker";
|
|
890
|
+
readonly type: "address";
|
|
891
|
+
readonly indexed: true;
|
|
892
|
+
}, {
|
|
893
|
+
readonly name: "amount";
|
|
894
|
+
readonly type: "uint256";
|
|
895
|
+
readonly indexed: false;
|
|
896
|
+
}];
|
|
897
|
+
}, {
|
|
898
|
+
readonly name: "WorkerBondForfeited";
|
|
899
|
+
readonly type: "event";
|
|
900
|
+
readonly inputs: readonly [{
|
|
901
|
+
readonly name: "jobId";
|
|
902
|
+
readonly type: "uint256";
|
|
903
|
+
readonly indexed: true;
|
|
904
|
+
}, {
|
|
905
|
+
readonly name: "poster";
|
|
906
|
+
readonly type: "address";
|
|
907
|
+
readonly indexed: true;
|
|
908
|
+
}, {
|
|
909
|
+
readonly name: "amount";
|
|
910
|
+
readonly type: "uint256";
|
|
911
|
+
readonly indexed: false;
|
|
912
|
+
}];
|
|
704
913
|
}];
|
|
705
914
|
declare const IDENTITY_REGISTRY_ABI: readonly [{
|
|
706
915
|
readonly name: "register";
|
|
@@ -832,4 +1041,4 @@ declare function validateAgentMetadata(m: unknown): asserts m is AgentMetadata;
|
|
|
832
1041
|
/** Pin a validated metadata blob to IPFS and return the `ipfs://<cid>` URI. */
|
|
833
1042
|
declare function pinAgentMetadata(meta: AgentMetadata): Promise<string>;
|
|
834
1043
|
|
|
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 };
|
|
1044
|
+
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, pinAgentMetadata, pinText, validateAgentMetadata };
|