@elgora/cli 7.5.1 → 8.0.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 +15 -7
- package/dist/cli.js +234 -34
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -41,7 +41,8 @@ answer.
|
|
|
41
41
|
on ElgoraHub.
|
|
42
42
|
- `guardian:deliver-key` wraps one Solver–Submission content key for delivery
|
|
43
43
|
so the funding Poster can retrieve the winning work; idempotent, and accepted
|
|
44
|
-
only for the pair ElgoraHub currently records or the finalized winner.
|
|
44
|
+
only for the pair ElgoraHub currently records or the finalized winner. While
|
|
45
|
+
a settlement is not yet finalized it delivers nothing and exits `75`.
|
|
45
46
|
- `claim` prepares or sends the winning Solver's reserved award or the
|
|
46
47
|
Poster's queued refund, as selected from finalized ElgoraHub state.
|
|
47
48
|
- `verification-record` is a plain, unauthenticated GET that fetches or lazily
|
|
@@ -79,6 +80,11 @@ needs.
|
|
|
79
80
|
|
|
80
81
|
## Deployment configuration
|
|
81
82
|
|
|
83
|
+
Since 8.0.0 the default deployment is **Base mainnet** (`base`, chain `8453`),
|
|
84
|
+
which escrows real USDC. Elgora's staging deployment runs on **Base Sepolia**
|
|
85
|
+
(`base-sepolia`, chain `84532`) behind `https://staging.elgora.ai`. A run that
|
|
86
|
+
selects no network prints one stderr line saying it used the default.
|
|
87
|
+
|
|
82
88
|
Every command accepts `--network <name|chain id>`, which selects the deployment
|
|
83
89
|
for that invocation without touching the environment. It takes a network name
|
|
84
90
|
(`base`, `base-sepolia`, `local`) or that network's chain id (`8453`, `84532`,
|
|
@@ -86,9 +92,10 @@ for that invocation without touching the environment. It takes a network name
|
|
|
86
92
|
passed — for that run only:
|
|
87
93
|
|
|
88
94
|
```sh
|
|
89
|
-
elgora-cli guardian:judgeable # the default
|
|
90
|
-
elgora-cli claim --network base-sepolia 7 #
|
|
95
|
+
elgora-cli guardian:judgeable # Base mainnet, the default
|
|
96
|
+
elgora-cli claim --network base-sepolia 7 # staging, by name
|
|
91
97
|
elgora-cli claim --network 84532 7 # the same, by chain id
|
|
98
|
+
export ELGORA_CHAIN_ID=84532 # staging for every run in this shell
|
|
92
99
|
```
|
|
93
100
|
|
|
94
101
|
The chain's public RPC, the ElgoraHub address, the escrow token, and the subgraph
|
|
@@ -101,10 +108,11 @@ and which values it defaults. Supply a complete, coherent configuration when
|
|
|
101
108
|
targeting a deployment this CLI release does not know about, and do not mix
|
|
102
109
|
addresses or endpoints from different deployments.
|
|
103
110
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
over `ELGORA_API_BASE_URL`
|
|
107
|
-
|
|
111
|
+
The API follows the chain too: `https://elgora.ai` for `base` and
|
|
112
|
+
`https://staging.elgora.ai` for `base-sepolia`. Commands that use the public API
|
|
113
|
+
accept `--api-base-url <url>`, which wins over `ELGORA_API_BASE_URL` and that
|
|
114
|
+
default for one invocation — for example to reach a Vercel preview. Point it at
|
|
115
|
+
an API serving the deployment you selected.
|
|
108
116
|
|
|
109
117
|
Protected API reads and writes use one EIP-712 approval per request. The
|
|
110
118
|
signature is bound to the method, path, body, query, API host, and a recent
|
package/dist/cli.js
CHANGED
|
@@ -1352,8 +1352,8 @@ function readFrontmatter(markdown, issues) {
|
|
|
1352
1352
|
return null;
|
|
1353
1353
|
}
|
|
1354
1354
|
}
|
|
1355
|
-
function resolveProfile(declared,
|
|
1356
|
-
const pinned = getProtocolProfile(declared) ?? (declared ===
|
|
1355
|
+
function resolveProfile(declared, fallback2, issues) {
|
|
1356
|
+
const pinned = getProtocolProfile(declared) ?? (declared === fallback2.profile ? fallback2 : null);
|
|
1357
1357
|
if (pinned === null) {
|
|
1358
1358
|
issues.push({
|
|
1359
1359
|
code: "profile_unknown",
|
|
@@ -1486,19 +1486,30 @@ function parseInlineList(value) {
|
|
|
1486
1486
|
}
|
|
1487
1487
|
|
|
1488
1488
|
// ../../packages/core/src/deployments.ts
|
|
1489
|
-
import { baseSepolia as baseSepolia2 } from "viem/chains";
|
|
1489
|
+
import { base as base2, baseSepolia as baseSepolia2 } from "viem/chains";
|
|
1490
1490
|
var DEPLOYMENTS = {
|
|
1491
|
+
[base2.id]: {
|
|
1492
|
+
ELGORA_HUB_ADDRESS: "0x8f80d1183cd983b01b0c9ac6777cc732ec9800de",
|
|
1493
|
+
ELGORA_ESCROW_TOKEN_ADDRESS: "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
|
|
1494
|
+
payoutSchemeAddress: "0x36d304993cb1575a2f9b8a0388b18aa5ec6d7a61",
|
|
1495
|
+
ELGORA_SUBGRAPH_ENDPOINT: "https://api.goldsky.com/api/public/project_cmtu7wslg04s501ovc2je3beh/subgraphs/elgora-elgorahub-base/production/gn",
|
|
1496
|
+
ELGORA_API_BASE_URL: "https://elgora.ai",
|
|
1497
|
+
deployBlock: 51752389,
|
|
1498
|
+
deployTransaction: "0xd62f407b770c8fca82a9704b30ed0605d9e3ed2b56278dcca152958063f7f469",
|
|
1499
|
+
sourceCommit: "8d40270d617a63dd5a7a35045db0d9ea3ddd9093"
|
|
1500
|
+
},
|
|
1491
1501
|
[baseSepolia2.id]: {
|
|
1492
1502
|
ELGORA_HUB_ADDRESS: "0x2f97b5f616495c2e923f39a46648eb783c053ad7",
|
|
1493
1503
|
ELGORA_ESCROW_TOKEN_ADDRESS: "0x036cbd53842c5426634e7929541ec2318f3dcf7e",
|
|
1494
1504
|
payoutSchemeAddress: "0x752d4305b8567b777d479dfa9847dc4f5ffb5750",
|
|
1495
1505
|
ELGORA_SUBGRAPH_ENDPOINT: "https://api.goldsky.com/api/public/project_cmtu7wslg04s501ovc2je3beh/subgraphs/elgora-elgorahub/testnet-production/gn",
|
|
1506
|
+
ELGORA_API_BASE_URL: "https://staging.elgora.ai",
|
|
1496
1507
|
deployBlock: 46353511,
|
|
1497
1508
|
deployTransaction: "0xed3d3c8af3c69f9f8d4ec47da7179fe4b89bd4a4cd8d8232dbbd3d3f3d38e74b",
|
|
1498
1509
|
sourceCommit: "1377da5c38dc5c90d8608ffa3cb15ad6f8567a01"
|
|
1499
1510
|
}
|
|
1500
1511
|
};
|
|
1501
|
-
var DEFAULT_CHAIN_ID =
|
|
1512
|
+
var DEFAULT_CHAIN_ID = base2.id;
|
|
1502
1513
|
function getDeployment(chainId) {
|
|
1503
1514
|
return DEPLOYMENTS[chainId];
|
|
1504
1515
|
}
|
|
@@ -4716,20 +4727,52 @@ function invalidWrittenVerdict(path5, message) {
|
|
|
4716
4727
|
import {
|
|
4717
4728
|
createPublicClient,
|
|
4718
4729
|
createWalletClient,
|
|
4730
|
+
fallback,
|
|
4719
4731
|
http
|
|
4720
4732
|
} from "viem";
|
|
4733
|
+
|
|
4734
|
+
// ../../packages/core/src/auth/freshness.ts
|
|
4735
|
+
var API_REQUEST_APPROVAL_ANCHOR_LAG_SECONDS = 6;
|
|
4736
|
+
var FALLBACK_BLOCK_TIME_MS = 2e3;
|
|
4737
|
+
function blockTimeMsFor(chainId) {
|
|
4738
|
+
const chain = chainId === void 0 ? void 0 : SUPPORTED_CHAINS[chainId];
|
|
4739
|
+
return chain?.blockTime ?? FALLBACK_BLOCK_TIME_MS;
|
|
4740
|
+
}
|
|
4741
|
+
function blocksForSeconds(seconds, chainId) {
|
|
4742
|
+
const blocks = Math.ceil(seconds * 1e3 / blockTimeMsFor(chainId));
|
|
4743
|
+
return BigInt(Math.max(1, blocks));
|
|
4744
|
+
}
|
|
4745
|
+
function apiRequestApprovalAnchorLagBlocks(chainId) {
|
|
4746
|
+
return blocksForSeconds(API_REQUEST_APPROVAL_ANCHOR_LAG_SECONDS, chainId);
|
|
4747
|
+
}
|
|
4748
|
+
|
|
4749
|
+
// ../../packages/core/src/chain-client.ts
|
|
4721
4750
|
var RPC_RETRY_COUNT = 3;
|
|
4751
|
+
function createChainTransport(chainId, rpcUrl) {
|
|
4752
|
+
const publicRpcUrl = resolveSupportedChain(chainId).rpcUrls.default.http[0];
|
|
4753
|
+
const configuredRpcUrl = rpcUrl?.trim() || publicRpcUrl;
|
|
4754
|
+
if (!publicRpcUrl || configuredRpcUrl === publicRpcUrl) {
|
|
4755
|
+
return http(configuredRpcUrl, { retryCount: RPC_RETRY_COUNT });
|
|
4756
|
+
}
|
|
4757
|
+
return fallback(
|
|
4758
|
+
[
|
|
4759
|
+
http(configuredRpcUrl, { retryCount: 0 }),
|
|
4760
|
+
http(publicRpcUrl, { retryCount: 0 })
|
|
4761
|
+
],
|
|
4762
|
+
{ retryCount: RPC_RETRY_COUNT }
|
|
4763
|
+
);
|
|
4764
|
+
}
|
|
4722
4765
|
function createChainPublicClient(chainId, rpcUrl) {
|
|
4723
4766
|
return createPublicClient({
|
|
4724
4767
|
chain: resolveSupportedChain(chainId),
|
|
4725
|
-
transport:
|
|
4768
|
+
transport: createChainTransport(chainId, rpcUrl)
|
|
4726
4769
|
});
|
|
4727
4770
|
}
|
|
4728
4771
|
function createChainWalletClient(chainId, rpcUrl, account) {
|
|
4729
4772
|
return createWalletClient({
|
|
4730
4773
|
account,
|
|
4731
4774
|
chain: resolveSupportedChain(chainId),
|
|
4732
|
-
transport:
|
|
4775
|
+
transport: createChainTransport(chainId, rpcUrl)
|
|
4733
4776
|
});
|
|
4734
4777
|
}
|
|
4735
4778
|
function assertChainId(actual, expected) {
|
|
@@ -4737,10 +4780,10 @@ function assertChainId(actual, expected) {
|
|
|
4737
4780
|
throw new Error(`RPC returned chain_id ${actual}, expected ${expected}`);
|
|
4738
4781
|
}
|
|
4739
4782
|
}
|
|
4740
|
-
var SIGNING_BLOCK_OFFSET = 3n;
|
|
4741
4783
|
async function fetchSignableBlock(client) {
|
|
4784
|
+
const offset = apiRequestApprovalAnchorLagBlocks(client.chain?.id);
|
|
4742
4785
|
const head = await client.getBlockNumber();
|
|
4743
|
-
const anchorNumber = head >
|
|
4786
|
+
const anchorNumber = head > offset ? head - offset : 0n;
|
|
4744
4787
|
const anchor = await client.getBlock({ blockNumber: anchorNumber });
|
|
4745
4788
|
return { number: anchor.number, hash: anchor.hash };
|
|
4746
4789
|
}
|
|
@@ -5032,7 +5075,6 @@ function loadClaimConfig(env, claimantAddress) {
|
|
|
5032
5075
|
}
|
|
5033
5076
|
|
|
5034
5077
|
// ../../packages/core/src/api-client-config.ts
|
|
5035
|
-
var PRODUCTION_API_BASE_URL = "https://elgora.vercel.app";
|
|
5036
5078
|
var LOCAL_DEV_API_BASE_URL = "http://127.0.0.1:3000";
|
|
5037
5079
|
var API_BASE_URL_FLAG = "--api-base-url";
|
|
5038
5080
|
function loadApiClientConfig(env, apiBaseUrlOverride) {
|
|
@@ -5060,7 +5102,15 @@ function resolveApiBaseUrl(env, override) {
|
|
|
5060
5102
|
return value;
|
|
5061
5103
|
}
|
|
5062
5104
|
function defaultApiBaseUrl(env) {
|
|
5063
|
-
|
|
5105
|
+
if (env.NODE_ENV === "development") return LOCAL_DEV_API_BASE_URL;
|
|
5106
|
+
const chainId = Number(env.ELGORA_CHAIN_ID?.trim() || DEFAULT_CHAIN_ID);
|
|
5107
|
+
const recorded = getDeployment(chainId)?.ELGORA_API_BASE_URL;
|
|
5108
|
+
if (!recorded) {
|
|
5109
|
+
throw new Error(
|
|
5110
|
+
`No Elgora API is recorded for chain ${chainId}; set ELGORA_API_BASE_URL or pass --api-base-url`
|
|
5111
|
+
);
|
|
5112
|
+
}
|
|
5113
|
+
return recorded;
|
|
5064
5114
|
}
|
|
5065
5115
|
|
|
5066
5116
|
// ../../packages/core/src/api-client.ts
|
|
@@ -5581,6 +5631,7 @@ function readGuardianPrivateKeys(env) {
|
|
|
5581
5631
|
}
|
|
5582
5632
|
|
|
5583
5633
|
// src/guardian-deliver-key.ts
|
|
5634
|
+
var PENDING_FINALITY_EXIT_CODE = 75;
|
|
5584
5635
|
var USAGE = "Usage: elgora-cli guardian:deliver-key <bounty_id> <solver> <submission_commitment>";
|
|
5585
5636
|
async function main4(env = process.env, argv = process.argv.slice(2)) {
|
|
5586
5637
|
const { apiBaseUrl, argv: positionalArgs } = extractApiBaseUrlFlag(argv);
|
|
@@ -5595,6 +5646,33 @@ async function main4(env = process.env, argv = process.argv.slice(2)) {
|
|
|
5595
5646
|
"ELGORA_GUARDIAN_ACCOUNT_PRIVATE_KEY must be a 32-byte hex private key"
|
|
5596
5647
|
);
|
|
5597
5648
|
}
|
|
5649
|
+
const guardianPrivateKeys = readGuardianPrivateKeys(env);
|
|
5650
|
+
const publicClient = createChainPublicClient(config.chainId, rpcUrl);
|
|
5651
|
+
const finality = await readSettlementFinality(
|
|
5652
|
+
publicClient,
|
|
5653
|
+
config.hubAddress,
|
|
5654
|
+
bountyId
|
|
5655
|
+
);
|
|
5656
|
+
if (finality.latestStatus === "no_valid_submission" || finality.latestStatus === "timed_out") {
|
|
5657
|
+
throw new Error(
|
|
5658
|
+
`Bounty ${bountyId.toString()} settled ${finality.latestStatus}; there is no winning key to deliver`
|
|
5659
|
+
);
|
|
5660
|
+
}
|
|
5661
|
+
if (finality.pending) {
|
|
5662
|
+
console.log(
|
|
5663
|
+
JSON.stringify({
|
|
5664
|
+
event: "guardian_deliver_key.pending_finality",
|
|
5665
|
+
bounty_id: bountyId.toString(),
|
|
5666
|
+
solver,
|
|
5667
|
+
submission_commitment: submissionCommitment,
|
|
5668
|
+
latest_status: finality.latestStatus,
|
|
5669
|
+
finalized_status: finality.finalizedStatus,
|
|
5670
|
+
message: "Settlement is not behind the chain's finalized tag yet; nothing was delivered. Retry in 10-20 minutes."
|
|
5671
|
+
})
|
|
5672
|
+
);
|
|
5673
|
+
process.exitCode = PENDING_FINALITY_EXIT_CODE;
|
|
5674
|
+
return;
|
|
5675
|
+
}
|
|
5598
5676
|
const account = privateKeyToAccount4(guardianAccountPrivateKey);
|
|
5599
5677
|
const wrapped = await wrapWinningSolutionKey({
|
|
5600
5678
|
config,
|
|
@@ -5605,8 +5683,8 @@ async function main4(env = process.env, argv = process.argv.slice(2)) {
|
|
|
5605
5683
|
privateKey: guardianAccountPrivateKey,
|
|
5606
5684
|
address: account.address
|
|
5607
5685
|
},
|
|
5608
|
-
publicClient
|
|
5609
|
-
guardianPrivateKeys
|
|
5686
|
+
publicClient,
|
|
5687
|
+
guardianPrivateKeys
|
|
5610
5688
|
});
|
|
5611
5689
|
console.log(
|
|
5612
5690
|
JSON.stringify({
|
|
@@ -5618,6 +5696,30 @@ async function main4(env = process.env, argv = process.argv.slice(2)) {
|
|
|
5618
5696
|
})
|
|
5619
5697
|
);
|
|
5620
5698
|
}
|
|
5699
|
+
async function readSettlementFinality(publicClient, hubAddress, bountyId) {
|
|
5700
|
+
const finalizedBlock = await publicClient.getBlock({
|
|
5701
|
+
blockTag: "finalized"
|
|
5702
|
+
});
|
|
5703
|
+
const readStatus = async (blockNumber) => {
|
|
5704
|
+
const [, state] = await publicClient.readContract({
|
|
5705
|
+
address: hubAddress,
|
|
5706
|
+
abi: ELGORA_HUB_BOUNTY_READ_ABI,
|
|
5707
|
+
functionName: "getBounty",
|
|
5708
|
+
args: [bountyId],
|
|
5709
|
+
...blockNumber === void 0 ? {} : { blockNumber }
|
|
5710
|
+
});
|
|
5711
|
+
return decodeBountyStatus(state.status);
|
|
5712
|
+
};
|
|
5713
|
+
const [latestStatus, finalizedStatus] = await Promise.all([
|
|
5714
|
+
readStatus(),
|
|
5715
|
+
readStatus(finalizedBlock.number)
|
|
5716
|
+
]);
|
|
5717
|
+
return {
|
|
5718
|
+
pending: latestStatus === "awarded" && finalizedStatus === "open",
|
|
5719
|
+
latestStatus,
|
|
5720
|
+
finalizedStatus
|
|
5721
|
+
};
|
|
5722
|
+
}
|
|
5621
5723
|
function readArgs(argv) {
|
|
5622
5724
|
const [bountyId, solver, submissionCommitment] = argv;
|
|
5623
5725
|
if (!bountyId || !isNumeric(bountyId) || !solver || !isHexAddress(solver) || !submissionCommitment || !isHexBytes32(submissionCommitment)) {
|
|
@@ -5754,6 +5856,13 @@ var BOUNTY_DETAIL_QUERY = `
|
|
|
5754
5856
|
reportCommitments
|
|
5755
5857
|
awardedPayoutData
|
|
5756
5858
|
timedOutRefundAmount
|
|
5859
|
+
settledLogIndex
|
|
5860
|
+
claimsQueued(first: 1, orderBy: queuedLogIndex, orderDirection: desc) {
|
|
5861
|
+
recipient
|
|
5862
|
+
amount
|
|
5863
|
+
queuedTxHash
|
|
5864
|
+
queuedLogIndex
|
|
5865
|
+
}
|
|
5757
5866
|
guardianRoster {
|
|
5758
5867
|
${GUARDIAN_ROSTER_SNAPSHOT_FIELDS}
|
|
5759
5868
|
}
|
|
@@ -6131,8 +6240,17 @@ function mapAnalyticsGuardianRoster(row) {
|
|
|
6131
6240
|
}
|
|
6132
6241
|
function mapBountyDetail(row) {
|
|
6133
6242
|
const record = readRecord(row);
|
|
6243
|
+
const allocation = record.claimsQueued == null ? null : asArray(record.claimsQueued, "claimsQueued")[0];
|
|
6244
|
+
let guardianFeeAmount = null;
|
|
6245
|
+
if ((record.status === "Awarded" || record.status === "NoValidSubmission") && allocation && record.settledTxHash && record.settledLogIndex != null) {
|
|
6246
|
+
const claim = readRecord(allocation);
|
|
6247
|
+
if (asHex(claim.recipient, "recipient") === asHex(record.guardianFeeRecipient, "guardianFeeRecipient") && asHex(claim.queuedTxHash, "queuedTxHash") === asHex(record.settledTxHash, "settledTxHash") && asNumber(claim.queuedLogIndex, "queuedLogIndex") + 1 === asNumber(record.settledLogIndex, "settledLogIndex")) {
|
|
6248
|
+
guardianFeeAmount = asString(claim.amount, "amount");
|
|
6249
|
+
}
|
|
6250
|
+
}
|
|
6134
6251
|
return {
|
|
6135
6252
|
...mapBounty(record),
|
|
6253
|
+
guardianFeeAmount,
|
|
6136
6254
|
guardianRosterAdmin: asHex(
|
|
6137
6255
|
record.guardianRosterAdmin,
|
|
6138
6256
|
"guardianRosterAdmin"
|
|
@@ -6586,7 +6704,10 @@ function parseChallenge(text) {
|
|
|
6586
6704
|
|
|
6587
6705
|
// src/guardian-verdict.ts
|
|
6588
6706
|
import { readFile as readFile3 } from "fs/promises";
|
|
6589
|
-
import {
|
|
6707
|
+
import {
|
|
6708
|
+
BaseError as BaseError2,
|
|
6709
|
+
zeroAddress as zeroAddress4
|
|
6710
|
+
} from "viem";
|
|
6590
6711
|
import { privateKeyToAccount as privateKeyToAccount6 } from "viem/accounts";
|
|
6591
6712
|
var OUTCOME = {
|
|
6592
6713
|
no_valid_submission: 0,
|
|
@@ -6797,20 +6918,66 @@ async function main7(env = process.env, argv = process.argv.slice(2)) {
|
|
|
6797
6918
|
functionName: "commitVerdict",
|
|
6798
6919
|
args: contractArgs
|
|
6799
6920
|
});
|
|
6921
|
+
const replacements = [];
|
|
6800
6922
|
const receipt = await publicClient.waitForTransactionReceipt({
|
|
6801
|
-
hash: transactionHash
|
|
6923
|
+
hash: transactionHash,
|
|
6924
|
+
onReplaced: (replacement) => replacements.push(replacement)
|
|
6802
6925
|
});
|
|
6926
|
+
if (receipt.transactionHash !== transactionHash && replacements.at(-1)?.reason !== "repriced") {
|
|
6927
|
+
throw new Error(
|
|
6928
|
+
`commitVerdict transaction ${transactionHash} was ${replacements.at(-1)?.reason ?? "replaced"} by ${receipt.transactionHash}; this Verdict was not recorded`
|
|
6929
|
+
);
|
|
6930
|
+
}
|
|
6803
6931
|
if (receipt.status !== "success") {
|
|
6804
|
-
throw new Error(
|
|
6932
|
+
throw new Error(
|
|
6933
|
+
`commitVerdict transaction reverted: ${receipt.transactionHash}`
|
|
6934
|
+
);
|
|
6805
6935
|
}
|
|
6806
|
-
|
|
6807
|
-
|
|
6808
|
-
|
|
6809
|
-
|
|
6810
|
-
|
|
6811
|
-
|
|
6812
|
-
|
|
6813
|
-
|
|
6936
|
+
let readbackIssue;
|
|
6937
|
+
try {
|
|
6938
|
+
const recorded = await publicClient.readContract({
|
|
6939
|
+
address: config.hubAddress,
|
|
6940
|
+
abi: ELGORA_HUB_VERDICT_WRITE_ABI,
|
|
6941
|
+
functionName: "verdicts",
|
|
6942
|
+
args: [args.bountyId, account.address],
|
|
6943
|
+
blockNumber: receipt.blockNumber
|
|
6944
|
+
});
|
|
6945
|
+
if (!recorded[0] || recorded[1] !== contractArgs[1] || recorded[2].toLowerCase() !== contractArgs[2].toLowerCase() || recorded[3].toLowerCase() !== contractArgs[3].toLowerCase() || recorded[4].toLowerCase() !== reportCommitment || recorded[5].toLowerCase() !== "0x") {
|
|
6946
|
+
readbackIssue = {
|
|
6947
|
+
observed: {
|
|
6948
|
+
committed: recorded[0],
|
|
6949
|
+
outcome: recorded[1],
|
|
6950
|
+
winner: recorded[2],
|
|
6951
|
+
awarded_submission_commitment: recorded[3],
|
|
6952
|
+
report_commitment: recorded[4],
|
|
6953
|
+
payout_data: recorded[5]
|
|
6954
|
+
}
|
|
6955
|
+
};
|
|
6956
|
+
}
|
|
6957
|
+
} catch (error) {
|
|
6958
|
+
readbackIssue = {
|
|
6959
|
+
error: error instanceof BaseError2 ? error.walk().name : error instanceof Error ? error.name : "UnknownError"
|
|
6960
|
+
};
|
|
6961
|
+
}
|
|
6962
|
+
if (readbackIssue) {
|
|
6963
|
+
console.warn(
|
|
6964
|
+
JSON.stringify({
|
|
6965
|
+
event: "guardian_verdict.readback_unconfirmed",
|
|
6966
|
+
bounty_id: args.bountyId.toString(),
|
|
6967
|
+
guardian: account.address.toLowerCase(),
|
|
6968
|
+
tx_hash: receipt.transactionHash,
|
|
6969
|
+
block_number: receipt.blockNumber.toString(),
|
|
6970
|
+
expected: {
|
|
6971
|
+
committed: true,
|
|
6972
|
+
outcome: contractArgs[1],
|
|
6973
|
+
winner: contractArgs[2],
|
|
6974
|
+
awarded_submission_commitment: contractArgs[3],
|
|
6975
|
+
report_commitment: reportCommitment,
|
|
6976
|
+
payout_data: "0x"
|
|
6977
|
+
},
|
|
6978
|
+
...readbackIssue
|
|
6979
|
+
})
|
|
6980
|
+
);
|
|
6814
6981
|
}
|
|
6815
6982
|
console.log(
|
|
6816
6983
|
JSON.stringify({
|
|
@@ -6823,7 +6990,7 @@ async function main7(env = process.env, argv = process.argv.slice(2)) {
|
|
|
6823
6990
|
awarded_submission_commitment: args.awardedSubmissionCommitment
|
|
6824
6991
|
} : {},
|
|
6825
6992
|
report_commitment: reportCommitment,
|
|
6826
|
-
tx_hash: transactionHash,
|
|
6993
|
+
tx_hash: receipt.transactionHash,
|
|
6827
6994
|
block_number: receipt.blockNumber.toString()
|
|
6828
6995
|
})
|
|
6829
6996
|
);
|
|
@@ -6874,14 +7041,40 @@ function usageError() {
|
|
|
6874
7041
|
}
|
|
6875
7042
|
|
|
6876
7043
|
// src/network-flag.ts
|
|
6877
|
-
import { base as
|
|
7044
|
+
import { base as base3, baseSepolia as baseSepolia3, foundry as foundry3 } from "viem/chains";
|
|
6878
7045
|
var NETWORK_FLAG = "--network";
|
|
6879
|
-
var
|
|
6880
|
-
base:
|
|
6881
|
-
|
|
6882
|
-
|
|
6883
|
-
|
|
6884
|
-
|
|
7046
|
+
var NETWORKS = [
|
|
7047
|
+
{ name: "base", chainId: base3.id, label: "Base mainnet" },
|
|
7048
|
+
{
|
|
7049
|
+
name: "base-sepolia",
|
|
7050
|
+
chainId: baseSepolia3.id,
|
|
7051
|
+
label: "Base Sepolia testnet, Elgora's staging deployment"
|
|
7052
|
+
},
|
|
7053
|
+
{ name: "local", chainId: foundry3.id, label: "a local Anvil stack" }
|
|
7054
|
+
];
|
|
7055
|
+
var NETWORK_CHAIN_IDS = Object.fromEntries(
|
|
7056
|
+
NETWORKS.map(({ name, chainId }) => [name, chainId])
|
|
7057
|
+
);
|
|
7058
|
+
var STAGING_NETWORK = NETWORKS.find(
|
|
7059
|
+
({ chainId }) => chainId === baseSepolia3.id
|
|
7060
|
+
);
|
|
7061
|
+
var NETWORK_NAMES_HINT = NETWORKS.map(
|
|
7062
|
+
({ name, chainId }) => `${name} (${chainId})`
|
|
7063
|
+
).join(", ");
|
|
7064
|
+
function describeChain(chainId) {
|
|
7065
|
+
const network = NETWORKS.find((candidate) => candidate.chainId === chainId);
|
|
7066
|
+
return network ? `${network.name} (${network.label})` : `chain ${chainId}`;
|
|
7067
|
+
}
|
|
7068
|
+
var STAGING_HINT = `add ${NETWORK_FLAG} ${STAGING_NETWORK.name} or set ELGORA_CHAIN_ID=${STAGING_NETWORK.chainId}`;
|
|
7069
|
+
var DEFAULT_NETWORK_HELP_LINES = [
|
|
7070
|
+
`Default: ${describeChain(DEFAULT_CHAIN_ID)}.`,
|
|
7071
|
+
`Staging: ${describeChain(STAGING_NETWORK.chainId)};`,
|
|
7072
|
+
` ${STAGING_HINT}.`
|
|
7073
|
+
];
|
|
7074
|
+
function defaultNetworkNotice(env) {
|
|
7075
|
+
if (env.ELGORA_CHAIN_ID?.trim()) return void 0;
|
|
7076
|
+
return `elgora-cli: using the default network, ${describeChain(DEFAULT_CHAIN_ID)}. For staging, ${STAGING_HINT}.`;
|
|
7077
|
+
}
|
|
6885
7078
|
function applyNetworkFlag(env, argv) {
|
|
6886
7079
|
const present = argv.some(
|
|
6887
7080
|
(arg) => arg === NETWORK_FLAG || arg.startsWith(`${NETWORK_FLAG}=`)
|
|
@@ -6907,7 +7100,7 @@ function resolveChainId(selector) {
|
|
|
6907
7100
|
}
|
|
6908
7101
|
|
|
6909
7102
|
// src/version.ts
|
|
6910
|
-
var CLI_VERSION = true ? "
|
|
7103
|
+
var CLI_VERSION = true ? "8.0.0" : "0.0.0-dev";
|
|
6911
7104
|
var CLI_NODE_ENGINES = true ? ">=24 <25" : ">=24 <25";
|
|
6912
7105
|
|
|
6913
7106
|
// src/node-engines.ts
|
|
@@ -8404,7 +8597,7 @@ var COMMAND_HELP = {
|
|
|
8404
8597
|
"guardian:deliver-key": {
|
|
8405
8598
|
usage: "elgora-cli guardian:deliver-key <bounty_id> <solver> <submission_commitment>",
|
|
8406
8599
|
title: "Deliver the finalized winner's content key for Poster retrieval.",
|
|
8407
|
-
description: "Required after a bounty finalizes `awarded`: wrap the winning\n Submission's key so the funding Poster can retrieve the work. Read the\n winning Solver and Submission from ElgoraHub's finalized state (the\n subgraph), not from a local Verdict, and pass exactly that pair. The\n API rechecks against ElgoraHub and accepts only the current active or\n finalized winner; written Verdicts and local state authorize nothing.\n Idempotent \u2014 safe to re-run and safe if another Guardian already did it.",
|
|
8600
|
+
description: "Required after a bounty finalizes `awarded`: wrap the winning\n Submission's key so the funding Poster can retrieve the work. Read the\n winning Solver and Submission from ElgoraHub's finalized state (the\n subgraph), not from a local Verdict, and pass exactly that pair. The\n API rechecks against ElgoraHub and accepts only the current active or\n finalized winner; written Verdicts and local state authorize nothing.\n Idempotent \u2014 safe to re-run and safe if another Guardian already did it.\n Until the settlement block is behind the chain's finalized tag (about\n 10-20 minutes after settlement) it delivers nothing, prints\n guardian_deliver_key.pending_finality, and exits 75; retry later.",
|
|
8408
8601
|
required: [
|
|
8409
8602
|
"ELGORA_GUARDIAN_ACCOUNT_PRIVATE_KEY",
|
|
8410
8603
|
"ELGORA_GUARDIAN_PRIVATE_KEYS_JSON"
|
|
@@ -8546,6 +8739,11 @@ async function run(rawArgv) {
|
|
|
8546
8739
|
process.exitCode = 1;
|
|
8547
8740
|
return;
|
|
8548
8741
|
}
|
|
8742
|
+
const networkNotice = COMMAND_HELP[subcommand]?.defaulted?.includes(
|
|
8743
|
+
"ELGORA_CHAIN_ID"
|
|
8744
|
+
) ? defaultNetworkNotice(env) : void 0;
|
|
8745
|
+
if (networkNotice) process.stderr.write(`${networkNotice}
|
|
8746
|
+
`);
|
|
8549
8747
|
const missing = missingRequiredEnv(
|
|
8550
8748
|
COMMAND_HELP[subcommand]?.required ?? [],
|
|
8551
8749
|
env
|
|
@@ -8580,6 +8778,7 @@ function printUsage() {
|
|
|
8580
8778
|
"",
|
|
8581
8779
|
`Every command accepts ${NETWORK_FLAG} <name|chain id> to select the`,
|
|
8582
8780
|
`deployment for that invocation. Supported: ${NETWORK_NAMES_HINT}.`,
|
|
8781
|
+
...DEFAULT_NETWORK_HELP_LINES,
|
|
8583
8782
|
"",
|
|
8584
8783
|
"Run `elgora-cli help <command>` for exact arguments and configuration.",
|
|
8585
8784
|
"Run `elgora-cli --version` to print this release's version."
|
|
@@ -8615,7 +8814,8 @@ function printCommandHelpOrUsage(name) {
|
|
|
8615
8814
|
"",
|
|
8616
8815
|
`Accepts ${NETWORK_FLAG} <name|chain id>; it sets ELGORA_CHAIN_ID for`,
|
|
8617
8816
|
"this invocation, winning over the environment.",
|
|
8618
|
-
`Supported: ${NETWORK_NAMES_HINT}
|
|
8817
|
+
`Supported: ${NETWORK_NAMES_HINT}.`,
|
|
8818
|
+
...DEFAULT_NETWORK_HELP_LINES
|
|
8619
8819
|
);
|
|
8620
8820
|
}
|
|
8621
8821
|
if (help.apiBaseUrlFlag) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elgora/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"description": "Command-line client for Elgora, a decentralized bounty marketplace for science. Lets Posters, Solvers, and Guardians interact with Elgora's public API and on-chain contracts.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|