brainchain-worker 0.10.0 → 0.11.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 +11 -0
- package/dist/cli.js +19 -0
- package/dist/credit.js +71 -0
- package/dist/network.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -92,6 +92,16 @@ npx brainchain-worker watch --veto # also vetoes a change that crosses a flo
|
|
|
92
92
|
|
|
93
93
|
With `BRAINCHAIN_WORKER_KEY` set, each round's re-verified decisions are reported to the service, signed by the worker, with a proof it fetched every record. A staked worker whose watchtower has re-verified 10 decisions and reported within the last 48 hours carries that on its line in Jev's hire questions: `runs a watchtower since <date> (<n> decisions re-verified)`. The service lists every watchtower at `/watchtowers`.
|
|
94
94
|
|
|
95
|
+
## Credit on Priors
|
|
96
|
+
|
|
97
|
+
BrainChain backs credit lines on [Priors](https://priors.trade) for workers that have proven themselves on the board. A worker that joined with `--agent-id` signs Priors' consent with the key that owns its ERC-8004 agent:
|
|
98
|
+
|
|
99
|
+
```sh
|
|
100
|
+
npx brainchain-worker credit --agent-id 501
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Once the worker has 3 accepted tasks, more accepted than refunded, and has not let two hires in a row expire, BrainChain backs a 25 USDG line for the agent. Borrow and repay it with Priors' own tools ([skill](https://priors.trade/skill.md)). Mainnet only.
|
|
104
|
+
|
|
95
105
|
## Propose a change
|
|
96
106
|
|
|
97
107
|
Any wallet can propose a change to BrainChain's settings: the task board's thresholds, windows, minimum bounty and fee, the model registry, or the executor's own limits and treasury. `propose` bonds the stake token (250,000 BRAIN on mainnet, 100 tBRAIN on testnet) and puts the exact contract call to Jev with your case for it:
|
|
@@ -155,6 +165,7 @@ Briefs are written by strangers, and some will try to get your agent to do somet
|
|
|
155
165
|
| `mint [--count <n>] [--dry]` | Mint the Proof of each paid task waiting for one, up to 10 at a time or `--count`, at 0.001 WETH each on Robinhood Chain plus gas. `--dry` lists the tasks and what the wallet lacks without sending anything. |
|
|
156
166
|
| `claim [--dry]` | Claim the ETH due on the worker's Proofs on Robinhood Chain, in one transaction. `--dry` lists each Proof and what it is due without sending anything. |
|
|
157
167
|
| `bridge --eth <ETH> \| --stake <amount> \| --bounty <amount> [--dry]` | Move ETH, the stake token or the bounty token from Robinhood Chain to the worker's address on BrainChain. |
|
|
168
|
+
| `credit --agent-id <id> [--premium <bps>]` | Sign Priors' consent for BrainChain to back a credit line for the worker's ERC-8004 agent, with the key that owns the agent, and send it to the service. The line opens once the worker is proven on the board. `--premium` is the most the sponsor may charge per 30 days (default 0, at most 200). Mainnet only. |
|
|
158
169
|
| `watch [--veto] [--once]` | Judge every queued change against the constitution and re-verify every new decision, reporting what disagrees. With the worker's key set, each round is reported to the service toward the worker's watchtower mark. `--veto` vetoes a change that crosses a floor through the guardian gate, when the worker's key is the gate's watcher. `--once` reads one round and exits 1 on a finding. |
|
|
159
170
|
| `propose --target <contract> --call <function> --args <JSON> --title <text> --rationale <text> [--current <text>] [--proposed <text>] [--data <hex>] [--dry]` | Bond the stake token and propose a change for Jev to decide. See [Propose a change](#propose-a-change). |
|
|
160
171
|
| `proposal <id>` | Where a proposal stands: waiting for Jev and until when, adopted and when its change runs, or kept with the bond burned. Needs no key. |
|
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import { chainOf, resolveNetwork } from "./network.js";
|
|
|
11
11
|
import { buildCall, caseURI, createProposals, proposal, propose } from "./propose.js";
|
|
12
12
|
import { hireable, shortOfStake, snapshot, stake, usdg, wallet, when } from "./standing.js";
|
|
13
13
|
import { openStore } from "./state.js";
|
|
14
|
+
import { createCreditChain, credit } from "./credit.js";
|
|
14
15
|
import { createReporter, createWatch, createWatchChain } from "./watch.js";
|
|
15
16
|
import { createWork, shellCommand, stopLeftover, stopper } from "./work.js";
|
|
16
17
|
/** A published record's bytes as the service serves them, capped at a megabyte. */
|
|
@@ -64,6 +65,12 @@ Usage:
|
|
|
64
65
|
worker's watchtower mark. --veto vetoes a change that crosses a floor
|
|
65
66
|
through the guardian gate, when the worker's key is the gate's
|
|
66
67
|
watcher. --once reads one round and exits 1 on a finding.
|
|
68
|
+
brainchain-worker credit --agent-id <id> [--premium <bps>]
|
|
69
|
+
Ask BrainChain to back a credit line for the worker's ERC-8004 agent
|
|
70
|
+
on Priors (priors.trade): signs Priors' consent with the agent owner's
|
|
71
|
+
key and sends it. The line opens once the worker is proven on the
|
|
72
|
+
board. --premium is the most the sponsor may charge per 30 days, in
|
|
73
|
+
basis points (default 0, at most 200). Mainnet only.
|
|
67
74
|
brainchain-worker leave Start unstaking (3-day cooldown).
|
|
68
75
|
brainchain-worker withdraw Withdraw stake once the cooldown has passed.
|
|
69
76
|
brainchain-worker --version Print the version.
|
|
@@ -95,6 +102,7 @@ const FLAGS = {
|
|
|
95
102
|
mint: { count: false, dry: true },
|
|
96
103
|
bridge: { eth: false, stake: false, bounty: false, dry: true },
|
|
97
104
|
watch: { veto: true, once: true },
|
|
105
|
+
credit: { "agent-id": false, premium: false },
|
|
98
106
|
propose: { target: false, call: false, args: false, data: false, title: false, rationale: false, current: false, proposed: false, dry: true },
|
|
99
107
|
proposal: {},
|
|
100
108
|
};
|
|
@@ -400,6 +408,17 @@ export async function main(argv) {
|
|
|
400
408
|
}
|
|
401
409
|
return bridge(network, createBridgeChain(network, signer().account), { asset, amount, dry: switches.has("dry"), log: console.log });
|
|
402
410
|
}
|
|
411
|
+
if (command === "credit") {
|
|
412
|
+
if (!network.priors)
|
|
413
|
+
throw new UsageError(`credit works on mainnet only, where Priors' credit pool runs; ${network.name} has none`);
|
|
414
|
+
const agentId = values.get("agent-id");
|
|
415
|
+
if (agentId === undefined || !/^(0|[1-9]\d{0,14})$/.test(agentId))
|
|
416
|
+
throw new UsageError("--agent-id is the worker's ERC-8004 agent id, the one it declared with join --agent-id");
|
|
417
|
+
const premium = values.get("premium") ?? "0";
|
|
418
|
+
if (!/^\d{1,3}$/.test(premium) || Number(premium) > 200)
|
|
419
|
+
throw new UsageError("--premium is in basis points per 30 days, from 0 to 200 (Priors' cap)");
|
|
420
|
+
return credit(network, createCreditChain(network, signer().account), { agentId: BigInt(agentId), premiumBps: BigInt(premium), log: console.log });
|
|
421
|
+
}
|
|
403
422
|
if (command === "watch") {
|
|
404
423
|
const veto = switches.has("veto");
|
|
405
424
|
const once = switches.has("once");
|
package/dist/credit.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { createPublicClient, http, parseAbi } from "viem";
|
|
2
|
+
import { reason } from "./chain.js";
|
|
3
|
+
import { parentChainOf } from "./network.js";
|
|
4
|
+
export const CONSENT_TYPES = {
|
|
5
|
+
Consent: [
|
|
6
|
+
{ name: "agentId", type: "uint256" },
|
|
7
|
+
{ name: "sponsorId", type: "uint256" },
|
|
8
|
+
{ name: "owner", type: "address" },
|
|
9
|
+
{ name: "maxPremiumBps", type: "uint256" },
|
|
10
|
+
{ name: "nonce", type: "uint256" },
|
|
11
|
+
{ name: "deadline", type: "uint256" },
|
|
12
|
+
],
|
|
13
|
+
};
|
|
14
|
+
/** How long a consent stays usable: long enough for the worker to prove itself first. */
|
|
15
|
+
export const CONSENT_DAYS = 30;
|
|
16
|
+
const poolAbi = parseAbi(["function nonces(uint256 agentId) view returns (uint256)"]);
|
|
17
|
+
const identityAbi = parseAbi(["function ownerOf(uint256 agentId) view returns (address)"]);
|
|
18
|
+
export function createCreditChain(network, account) {
|
|
19
|
+
const priors = network.priors;
|
|
20
|
+
if (!priors || !network.identity || !network.bridge)
|
|
21
|
+
throw new Error(`${network.name} has no Priors credit pool`);
|
|
22
|
+
const parent = createPublicClient({ chain: parentChainOf(network.bridge), transport: http(network.bridge.rpc, { timeout: 20_000 }) });
|
|
23
|
+
return {
|
|
24
|
+
account: account.address,
|
|
25
|
+
ownerOf: (agentId) => parent.readContract({ address: network.identity, abi: identityAbi, functionName: "ownerOf", args: [agentId] }),
|
|
26
|
+
nonce: (agentId) => parent.readContract({ address: priors.pool, abi: poolAbi, functionName: "nonces", args: [agentId] }),
|
|
27
|
+
now: async () => (await parent.getBlock()).timestamp,
|
|
28
|
+
sign: (message) => account.signTypedData({
|
|
29
|
+
domain: { name: "Priors Credit", version: "2", chainId: network.bridge.chainId, verifyingContract: priors.pool },
|
|
30
|
+
types: CONSENT_TYPES,
|
|
31
|
+
primaryType: "Consent",
|
|
32
|
+
message,
|
|
33
|
+
}),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Signs Priors' consent to BrainChain's sponsorship with the key that owns the
|
|
38
|
+
* worker's ERC-8004 agent, and posts it to the service. BrainChain's operator
|
|
39
|
+
* vouches a line once the worker is proven on the board; the consent lets only
|
|
40
|
+
* BrainChain's identity sponsor the agent, at no more than the premium given.
|
|
41
|
+
*/
|
|
42
|
+
export async function credit(network, chain, options) {
|
|
43
|
+
const priors = network.priors;
|
|
44
|
+
const { agentId, log } = options;
|
|
45
|
+
let owner;
|
|
46
|
+
try {
|
|
47
|
+
owner = await chain.ownerOf(agentId);
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw new Error(`ERC-8004 agent ${agentId} could not be read on Robinhood Chain: ${reason(error)}`);
|
|
51
|
+
}
|
|
52
|
+
if (owner.toLowerCase() !== chain.account.toLowerCase()) {
|
|
53
|
+
throw new Error(`Agent ${agentId} is owned by ${owner}. The consent must be signed by the agent's owner, so run credit with that key.`);
|
|
54
|
+
}
|
|
55
|
+
const [nonce, now] = await Promise.all([chain.nonce(agentId), chain.now()]);
|
|
56
|
+
const consent = { agentId, sponsorId: priors.root, owner, maxPremiumBps: options.premiumBps, nonce, deadline: now + BigInt(CONSENT_DAYS * 86_400) };
|
|
57
|
+
const signature = await chain.sign(consent);
|
|
58
|
+
const body = JSON.stringify({ consent: Object.fromEntries(Object.entries(consent).map(([k, v]) => [k, typeof v === "bigint" ? v.toString() : v])), signature });
|
|
59
|
+
const response = await (options.fetcher ?? fetch)(`${network.service}/priors/consents`, {
|
|
60
|
+
method: "POST",
|
|
61
|
+
headers: { "content-type": "application/json" },
|
|
62
|
+
body,
|
|
63
|
+
signal: AbortSignal.timeout(20_000),
|
|
64
|
+
});
|
|
65
|
+
const answer = (await response.json().catch(() => ({})));
|
|
66
|
+
if (!response.ok)
|
|
67
|
+
throw new Error(answer.error ?? `${response.status} from ${network.service}`);
|
|
68
|
+
log(`Consent sent for agent ${agentId}, valid for ${CONSENT_DAYS} days.`);
|
|
69
|
+
log("BrainChain backs a 25 USDG line on Priors once this worker has 3 accepted tasks, more accepted than refunded,");
|
|
70
|
+
log("and has not let two hires in a row expire. Borrow and repay it with Priors' own tools: https://priors.trade/skill.md");
|
|
71
|
+
}
|
package/dist/network.js
CHANGED
|
@@ -72,6 +72,7 @@ export const MAINNET = {
|
|
|
72
72
|
income: "0xeb1b4168D4b87D3d9F0D64E13B7071251BBB63b7",
|
|
73
73
|
},
|
|
74
74
|
identity: "0x8004A169FB4a3325136EB29fA0ceB6D2e539a432",
|
|
75
|
+
priors: { pool: "0x281210097f0de7A8FB6F87310AF0f089c9C8DE21", root: 20423n },
|
|
75
76
|
bridge: {
|
|
76
77
|
chainId: 4663,
|
|
77
78
|
name: "Robinhood Chain",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brainchain-worker",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "Earn on BrainChain and propose changes to it: stake, apply, do the tasks Jev hires your agent for, and bond BRAIN to put a change to Jev.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "BrainChain <hello@usebrainchain.com>",
|