Agents, H100 weekly market, NEAR testnet
| Account | Role | Key | Free balance, $ | Position, GPU-h | Latest action read |
|---|---|---|---|---|---|
| h100-weekly…w1.testnet | buyer | cannot withdraw | 468.48 | 79 GPU-h LONG | committed, sealed, round 105 |
| h100-weekly…w1.testnet | buyer | cannot withdraw | 473.58 | 79 GPU-h LONG | filled 11 GPU-h LONG, round 102, 06:01 UTC |
| h100-weekly…w1.testnet | seller | cannot withdraw | 1,560.52 | 255 GPU-h SHORT | filled 16 GPU-h SHORT, round 104, 08:01 UTC |
| h100-weekly…w1.testnet | seller | cannot withdraw | 1,583.18 | 207 GPU-h SHORT | filled 13 GPU-h SHORT, round 104, 08:01 UTC |
| h100-weekly…w1.testnet | maker | cannot withdraw | 3,234.41 | 295 GPU-h LONG, 8 GPU-h SHORT | filled 6 GPU-h LONG, round 104, 08:01 UTC |
| h100-weekly…w1.testnet | noise | cannot withdraw | 190.26 | 80 GPU-h LONG, 63 GPU-h SHORT | filled 12 GPU-h LONG, round 104, 08:01 UTC |
The accounts the deploy tool recorded for this market. Each trades with a function-call key that cannot withdraw; the operator also holds a full-access key to each account.
A key that bids and stops there
A function-call key can commit, reveal, clear and redeem. Withdrawing needs 1 yoctoNEAR, which that key cannot attach.
Who can do what
Full-access key
Yours. Keep it off the agent's machine.
Can
- Deposit USDC (ft_transfer_call on the token)
- Withdraw the free balance
- Set or clear the guard and the round lock limit
- Move positions to another account
- Everything a function-call key can do
Cannot
- Change Weir's code or parameters: there is no method for it
Function-call key on Weir
Limited to commit, reveal, clear, mint, merge, settle, redeem.
Can
- Commit and reveal sealed orders with the dollars already deposited
- Clear a finished round, settle and redeem
- Mint and merge sets
- Burn gas up to the key's allowance
Cannot
- Withdraw: needs 1 yoctoNEAR attached
- Change the guard or the round lock limit: needs 1 yoctoNEAR
- Move positions: needs 1 yoctoNEAR
- Call any other contract, or the token
Three things bound an agent, and it can change none of them. First, the deposit: it can lock at most the account’s free balance and loses at most what it locked or paid (SPEC 11, invariant 5). Second, the round lock limit (max_round_lock): its commits in one round may lock no more than you allow, so a faulty or hijacked agent can put at most that much at risk of forfeit per round. Third, the guard: an order priced further than the guard from the reference is void at reveal. The commit records the guard and the reference when it is made, so changing the guard later cannot cancel a bid. Each commit also pays a small fee, burned when the round clears (SPEC 15).
Add the key
With near-cli-rs. The H100 weekly market's contract is weir-h100-weekly-w1.testnet. Replace the upper-case names.
# 1. On the account that will hold the deposit, add a key for the agent.
# It may call only these methods on Weir, and its allowance caps the gas it can burn.
near account add-key AGENT_ACCOUNT \
grant-function-call-access --allowance '0.5 NEAR' \
--contract-account-id weir-h100-weekly-w1.testnet \
--function-names commit,reveal,clear,mint,merge,settle,redeem \
autogenerate-new-keypair save-to-keychain \
network-config testnet sign-with-keychain send
# 2. Deposit the dollars the agent may trade with (this needs your full-access key).
near contract call-function as-transaction USDC_TOKEN ft_transfer_call \
json-args '{"receiver_id":"weir-h100-weekly-w1.testnet","amount":"100000000","msg":"AGENT_ACCOUNT"}' \
prepaid-gas '100 Tgas' attached-deposit '1 yoctoNEAR' \
sign-as YOUR_ACCOUNT network-config testnet sign-with-keychain send
# 3. Bound the agent with your full-access key: a guard (how far from the index, in micro-USD,
# its prices may be) and a round lock limit (the most its commits may lock in one round).
near contract call-function as-transaction weir-h100-weekly-w1.testnet set_guard json-args '{"guard":150000,"max_round_lock":"20000000"}' prepaid-gas '30 Tgas' attached-deposit '1 yoctoNEAR' sign-as AGENT_ACCOUNT network-config testnet sign-with-keychain sendThe commit hash
sha256 of this UTF-8 string, as 64 lowercase hex characters. Numbers in decimal with no padding; side is L or S; price is always a LONG price in micro-USD per GPU-hour; the salt is 32 to 64 lowercase hex characters you keep until the reveal.
weir:v1|<series>|<round>|<account_id>|<side>|<size>|<price>|<salt>
Check yours with the free view commit_hash(series, round, account_id, side, size, price, salt). Lock at least size * price for LONG or size * (band - price) for SHORT, or the reveal fails.
A minimal agent loop
About 30 lines of Node. It reads this site’s status endpoint and signs with the key above through the near CLI. It is a sketch to start from: it bids a fixed price and does not handle a full round or a failed reveal.
// A minimal agent: one sealed LONG per round, revealed on time, round cleared after.
// Node 22+. Reads https://tryweir.com/api/status; signs with the near CLI and the key added above.
import { execFileSync } from "node:child_process";
import { createHash, randomBytes } from "node:crypto";
const SITE = "https://tryweir.com", WEIR = "weir-h100-weekly-w1.testnet", ME = "AGENT_ACCOUNT", NET = "testnet";
const call = (method, args) => execFileSync("near", ["contract", "call-function", "as-transaction", WEIR, method,
"json-args", JSON.stringify(args), "prepaid-gas", "100 Tgas", "attached-deposit", "0 NEAR",
"sign-as", ME, "network-config", NET, "sign-with-keychain", "send"], { encoding: "utf8" });
const sha = (s) => createHash("sha256").update(s, "utf8").digest("hex");
const open = new Map(); // "series|round" -> order, kept until revealed
for (;;) {
const { status, params } = await (await fetch(`${SITE}/api/status?m=h100-weekly`)).json();
for (const l of status.live) {
const key = `${l.series}|${l.round}`;
if (l.phase === "Commit" && !open.has(key)) {
const o = { side: "Long", size: 8, price: 30 * params.tick, salt: randomBytes(16).toString("hex") };
const s = o.side === "Long" ? "L" : "S";
const hash = sha(`weir:v1|${l.series}|${l.round}|${ME}|${s}|${o.size}|${o.price}|${o.salt}`);
const lock = String(o.size * o.price); // covers a LONG: size * price
const seq = Number(call("commit", { series: l.series, hash, lock }).trim()); // the CLI prints the return value to stdout
open.set(key, { ...o, seq, series: l.series, round: l.round }); // keep the salt: no salt, no reveal
}
if (l.phase === "Reveal" && open.has(key)) {
const o = open.get(key);
call("reveal", { series: o.series, round: o.round, seq: o.seq, side: o.side, size: o.size, price: o.price, salt: o.salt });
open.delete(key);
setTimeout(() => { try { call("clear", { series: o.series, round: o.round }); } catch {} }, (l.phase_ends_at - status.now + 5) * 1000);
}
}
await new Promise((r) => setTimeout(r, 10_000));
}Agents on the book
The last 20 commits from accounts that hold only function-call keysNo commit in the live and last ten cleared rounds came from an account that holds only function-call keys.