@reppo/cli 0.1.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/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/api/platform.d.ts +39 -0
- package/dist/api/platform.d.ts.map +1 -0
- package/dist/api/platform.js +148 -0
- package/dist/api/platform.js.map +1 -0
- package/dist/bin.d.ts +3 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +60 -0
- package/dist/bin.js.map +1 -0
- package/dist/chain/abis.d.ts +576 -0
- package/dist/chain/abis.d.ts.map +1 -0
- package/dist/chain/abis.js +66 -0
- package/dist/chain/abis.js.map +1 -0
- package/dist/chain/addresses.d.ts +27 -0
- package/dist/chain/addresses.d.ts.map +1 -0
- package/dist/chain/addresses.js +39 -0
- package/dist/chain/addresses.js.map +1 -0
- package/dist/chain/clients.d.ts +46 -0
- package/dist/chain/clients.d.ts.map +1 -0
- package/dist/chain/clients.js +48 -0
- package/dist/chain/clients.js.map +1 -0
- package/dist/chain/contracts.d.ts +28 -0
- package/dist/chain/contracts.d.ts.map +1 -0
- package/dist/chain/contracts.js +70 -0
- package/dist/chain/contracts.js.map +1 -0
- package/dist/chain/errors.d.ts +14 -0
- package/dist/chain/errors.d.ts.map +1 -0
- package/dist/chain/errors.js +72 -0
- package/dist/chain/errors.js.map +1 -0
- package/dist/commands/_base.d.ts +19 -0
- package/dist/commands/_base.d.ts.map +1 -0
- package/dist/commands/_base.js +40 -0
- package/dist/commands/_base.js.map +1 -0
- package/dist/commands/auth.d.ts +9 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +93 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/claim-emissions.d.ts +11 -0
- package/dist/commands/claim-emissions.d.ts.map +1 -0
- package/dist/commands/claim-emissions.js +192 -0
- package/dist/commands/claim-emissions.js.map +1 -0
- package/dist/commands/extend-lock.d.ts +11 -0
- package/dist/commands/extend-lock.d.ts.map +1 -0
- package/dist/commands/extend-lock.js +196 -0
- package/dist/commands/extend-lock.js.map +1 -0
- package/dist/commands/grant-access.d.ts +11 -0
- package/dist/commands/grant-access.d.ts.map +1 -0
- package/dist/commands/grant-access.js +191 -0
- package/dist/commands/grant-access.js.map +1 -0
- package/dist/commands/lock.d.ts +11 -0
- package/dist/commands/lock.d.ts.map +1 -0
- package/dist/commands/lock.js +192 -0
- package/dist/commands/lock.js.map +1 -0
- package/dist/commands/mint-pod.d.ts +15 -0
- package/dist/commands/mint-pod.d.ts.map +1 -0
- package/dist/commands/mint-pod.js +286 -0
- package/dist/commands/mint-pod.js.map +1 -0
- package/dist/commands/query/balance.d.ts +9 -0
- package/dist/commands/query/balance.d.ts.map +1 -0
- package/dist/commands/query/balance.js +91 -0
- package/dist/commands/query/balance.js.map +1 -0
- package/dist/commands/query/datanet.d.ts +10 -0
- package/dist/commands/query/datanet.d.ts.map +1 -0
- package/dist/commands/query/datanet.js +128 -0
- package/dist/commands/query/datanet.js.map +1 -0
- package/dist/commands/query/emissions-due.d.ts +18 -0
- package/dist/commands/query/emissions-due.d.ts.map +1 -0
- package/dist/commands/query/emissions-due.js +170 -0
- package/dist/commands/query/emissions-due.js.map +1 -0
- package/dist/commands/query/pod.d.ts +8 -0
- package/dist/commands/query/pod.d.ts.map +1 -0
- package/dist/commands/query/pod.js +88 -0
- package/dist/commands/query/pod.js.map +1 -0
- package/dist/commands/query/voting-power.d.ts +9 -0
- package/dist/commands/query/voting-power.d.ts.map +1 -0
- package/dist/commands/query/voting-power.js +82 -0
- package/dist/commands/query/voting-power.js.map +1 -0
- package/dist/commands/register-agent.d.ts +9 -0
- package/dist/commands/register-agent.d.ts.map +1 -0
- package/dist/commands/register-agent.js +115 -0
- package/dist/commands/register-agent.js.map +1 -0
- package/dist/commands/unlock.d.ts +11 -0
- package/dist/commands/unlock.d.ts.map +1 -0
- package/dist/commands/unlock.js +181 -0
- package/dist/commands/unlock.js.map +1 -0
- package/dist/commands/vote.d.ts +13 -0
- package/dist/commands/vote.d.ts.map +1 -0
- package/dist/commands/vote.js +174 -0
- package/dist/commands/vote.js.map +1 -0
- package/dist/config/load.d.ts +19 -0
- package/dist/config/load.d.ts.map +1 -0
- package/dist/config/load.js +66 -0
- package/dist/config/load.js.map +1 -0
- package/dist/output/format.d.ts +43 -0
- package/dist/output/format.d.ts.map +1 -0
- package/dist/output/format.js +58 -0
- package/dist/output/format.js.map +1 -0
- package/dist/state/db.d.ts +47 -0
- package/dist/state/db.d.ts.map +1 -0
- package/dist/state/db.js +169 -0
- package/dist/state/db.js.map +1 -0
- package/dist/state/idempotency.d.ts +66 -0
- package/dist/state/idempotency.d.ts.map +1 -0
- package/dist/state/idempotency.js +173 -0
- package/dist/state/idempotency.js.map +1 -0
- package/package.json +63 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { cliError } from '../output/format.js';
|
|
2
|
+
const TBD = '0x0000000000000000000000000000000000000000';
|
|
3
|
+
const MAINNET = {
|
|
4
|
+
podManager: '0xcfF0511089D0Fbe92E1788E4aFFF3E7930b3D47c',
|
|
5
|
+
subnetManager: TBD, // TODO: confirm mainnet SubnetManager address with Reppo
|
|
6
|
+
reppoToken: '0xFf8104251E7761163faC3211eF5583FB3F8583d6',
|
|
7
|
+
veReppo: TBD, // TODO: confirm mainnet veReppo address with Reppo
|
|
8
|
+
usdc: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
|
|
9
|
+
uniswapRouter: '0x2626664c2603336E57B271c5C0b26F421741e481',
|
|
10
|
+
uniswapQuoter: '0x3d4e44Eb1374240CE5F1B871ab261CD16335B76a',
|
|
11
|
+
chainId: 8453,
|
|
12
|
+
};
|
|
13
|
+
const TESTNET = {
|
|
14
|
+
podManager: '0x113CcFEcdc8Fb1662fCebd195D9573D1c5e5DFD3',
|
|
15
|
+
subnetManager: '0x33c70A9f578Dc22012AEab40A10758f026004A27',
|
|
16
|
+
reppoToken: '0xE224a711e18212Cf08EF3808dfa39ccBBd2f18c6',
|
|
17
|
+
veReppo: '0x76b4Ee62fF835142B3b29D9F91867697657b556D',
|
|
18
|
+
usdc: TBD, // testnet USDC via faucet — set when needed
|
|
19
|
+
uniswapRouter: null, // no V3 deployment on Sepolia for the REPPO/USDC pool
|
|
20
|
+
uniswapQuoter: null,
|
|
21
|
+
chainId: 84532,
|
|
22
|
+
};
|
|
23
|
+
export function getAddresses(network) {
|
|
24
|
+
return network === 'mainnet' ? MAINNET : TESTNET;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Throws if the address is the TBD placeholder. Use at the call site.
|
|
28
|
+
* The thrown error carries `code: 'ADDRESS_NOT_CONFIGURED'` so agents
|
|
29
|
+
* can distinguish "missing contract address for this network" from
|
|
30
|
+
* generic INTERNAL_ERROR bugs.
|
|
31
|
+
*/
|
|
32
|
+
export function requireAddress(addr, label) {
|
|
33
|
+
if (addr === TBD) {
|
|
34
|
+
throw cliError('ADDRESS_NOT_CONFIGURED', `${label} address is not configured for this network yet. ` +
|
|
35
|
+
`Edit src/chain/addresses.ts once Reppo publishes it.`, `${label} has no address baked in for the selected network. Switch networks with --network, or wait for the address to be published.`);
|
|
36
|
+
}
|
|
37
|
+
return addr;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=addresses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"addresses.js","sourceRoot":"","sources":["../../src/chain/addresses.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAe/C,MAAM,GAAG,GAAG,4CAAqD,CAAC;AAElE,MAAM,OAAO,GAAkB;IAC7B,UAAU,EAAK,4CAA4C;IAC3D,aAAa,EAAE,GAAG,EAAE,yDAAyD;IAC7E,UAAU,EAAK,4CAA4C;IAC3D,OAAO,EAAQ,GAAG,EAAE,mDAAmD;IACvE,IAAI,EAAW,4CAA4C;IAC3D,aAAa,EAAE,4CAA4C;IAC3D,aAAa,EAAE,4CAA4C;IAC3D,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,MAAM,OAAO,GAAkB;IAC7B,UAAU,EAAK,4CAA4C;IAC3D,aAAa,EAAE,4CAA4C;IAC3D,UAAU,EAAK,4CAA4C;IAC3D,OAAO,EAAQ,4CAA4C;IAC3D,IAAI,EAAW,GAAG,EAAE,4CAA4C;IAChE,aAAa,EAAE,IAAI,EAAE,sDAAsD;IAC3E,aAAa,EAAE,IAAI;IACnB,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,UAAU,YAAY,CAAC,OAAgB;IAC3C,OAAO,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,IAAa,EAAE,KAAa;IACzD,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;QACjB,MAAM,QAAQ,CACZ,wBAAwB,EACxB,GAAG,KAAK,mDAAmD;YACzD,sDAAsD,EACxD,GAAG,KAAK,6HAA6H,CACtI,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-network viem client factory.
|
|
3
|
+
*
|
|
4
|
+
* Single-process CLI: each invocation runs one command, so we don't need
|
|
5
|
+
* an in-process tx mutex. Self-collision is prevented by always reading
|
|
6
|
+
* the next nonce with `blockTag: 'pending'` (see `nextNonce`). If the CLI
|
|
7
|
+
* ever grows a multi-command-per-process driver, reintroduce a mutex
|
|
8
|
+
* around `writeContract` then.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: viem's PublicClient/WalletClient generic signatures drift across
|
|
11
|
+
* minor versions and across `viem/chains` re-exports. Returning the
|
|
12
|
+
* inferred type from createPublicClient/createWalletClient (rather than
|
|
13
|
+
* naming the alias) sidesteps the "two unrelated types with the same
|
|
14
|
+
* name" error TS2719.
|
|
15
|
+
*/
|
|
16
|
+
import { createPublicClient, createWalletClient, type Address } from 'viem';
|
|
17
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
18
|
+
import type { Network } from './addresses.js';
|
|
19
|
+
export type ReadClient = ReturnType<typeof createPublicClient>;
|
|
20
|
+
export type SignerClient = ReturnType<typeof createWalletClient>;
|
|
21
|
+
export interface Clients {
|
|
22
|
+
network: Network;
|
|
23
|
+
account: ReturnType<typeof privateKeyToAccount>;
|
|
24
|
+
publicClient: ReadClient;
|
|
25
|
+
walletClient: SignerClient;
|
|
26
|
+
}
|
|
27
|
+
export declare function createClients(opts: {
|
|
28
|
+
network: Network;
|
|
29
|
+
privateKey: `0x${string}`;
|
|
30
|
+
rpcUrl?: string;
|
|
31
|
+
}): Clients;
|
|
32
|
+
/**
|
|
33
|
+
* Read-only client (no signing key required). Used by `reppo query …`
|
|
34
|
+
* commands that don't need a wallet.
|
|
35
|
+
*/
|
|
36
|
+
export declare function createReadClient(opts: {
|
|
37
|
+
network: Network;
|
|
38
|
+
rpcUrl?: string;
|
|
39
|
+
}): ReadClient;
|
|
40
|
+
/**
|
|
41
|
+
* Get the next pending nonce for an address. Use `pending` block tag
|
|
42
|
+
* always — `latest` returns confirmed-only and causes nonce collisions
|
|
43
|
+
* when two writes go out within the same block.
|
|
44
|
+
*/
|
|
45
|
+
export declare function nextNonce(client: ReadClient, addr: Address): Promise<number>;
|
|
46
|
+
//# sourceMappingURL=clients.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.d.ts","sourceRoot":"","sources":["../../src/chain/clients.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAElB,KAAK,OAAO,EAEb,MAAM,MAAM,CAAC;AAEd,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAQ9C,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAC/D,MAAM,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEjE,MAAM,WAAW,OAAO;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;IAChD,YAAY,EAAE,UAAU,CAAC;IACzB,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,KAAK,MAAM,EAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GAAG,OAAO,CAOV;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,CAGxF;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAElF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-network viem client factory.
|
|
3
|
+
*
|
|
4
|
+
* Single-process CLI: each invocation runs one command, so we don't need
|
|
5
|
+
* an in-process tx mutex. Self-collision is prevented by always reading
|
|
6
|
+
* the next nonce with `blockTag: 'pending'` (see `nextNonce`). If the CLI
|
|
7
|
+
* ever grows a multi-command-per-process driver, reintroduce a mutex
|
|
8
|
+
* around `writeContract` then.
|
|
9
|
+
*
|
|
10
|
+
* NOTE: viem's PublicClient/WalletClient generic signatures drift across
|
|
11
|
+
* minor versions and across `viem/chains` re-exports. Returning the
|
|
12
|
+
* inferred type from createPublicClient/createWalletClient (rather than
|
|
13
|
+
* naming the alias) sidesteps the "two unrelated types with the same
|
|
14
|
+
* name" error TS2719.
|
|
15
|
+
*/
|
|
16
|
+
import { createPublicClient, createWalletClient, http, } from 'viem';
|
|
17
|
+
import { base as _base, baseSepolia as _baseSepolia } from 'viem/chains';
|
|
18
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
19
|
+
// Cast to plain Chain to escape viem's opstack/deposit-tx generic widening
|
|
20
|
+
// — that widening is what produces the TS2322 "two unrelated types"
|
|
21
|
+
// errors when we try to declare ReadClient/SignerClient aliases.
|
|
22
|
+
const base = _base;
|
|
23
|
+
const baseSepolia = _baseSepolia;
|
|
24
|
+
export function createClients(opts) {
|
|
25
|
+
const account = privateKeyToAccount(opts.privateKey);
|
|
26
|
+
const chain = opts.network === 'mainnet' ? base : baseSepolia;
|
|
27
|
+
const transport = http(opts.rpcUrl);
|
|
28
|
+
const publicClient = createPublicClient({ chain, transport });
|
|
29
|
+
const walletClient = createWalletClient({ account, chain, transport });
|
|
30
|
+
return { network: opts.network, account, publicClient, walletClient };
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read-only client (no signing key required). Used by `reppo query …`
|
|
34
|
+
* commands that don't need a wallet.
|
|
35
|
+
*/
|
|
36
|
+
export function createReadClient(opts) {
|
|
37
|
+
const chain = opts.network === 'mainnet' ? base : baseSepolia;
|
|
38
|
+
return createPublicClient({ chain, transport: http(opts.rpcUrl) });
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Get the next pending nonce for an address. Use `pending` block tag
|
|
42
|
+
* always — `latest` returns confirmed-only and causes nonce collisions
|
|
43
|
+
* when two writes go out within the same block.
|
|
44
|
+
*/
|
|
45
|
+
export async function nextNonce(client, addr) {
|
|
46
|
+
return client.getTransactionCount({ address: addr, blockTag: 'pending' });
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=clients.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../../src/chain/clients.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,IAAI,GAGL,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,IAAI,IAAI,KAAK,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AAGpD,2EAA2E;AAC3E,oEAAoE;AACpE,iEAAiE;AACjE,MAAM,IAAI,GAAG,KAAc,CAAC;AAC5B,MAAM,WAAW,GAAG,YAAqB,CAAC;AAY1C,MAAM,UAAU,aAAa,CAAC,IAI7B;IACC,MAAM,OAAO,GAAG,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IAC9D,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACpC,MAAM,YAAY,GAAG,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,kBAAkB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IACvE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AACxE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAA2C;IAC1E,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;IAC9D,OAAO,kBAAkB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,MAAkB,EAAE,IAAa;IAC/D,OAAO,MAAM,CAAC,mBAAmB,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;AAC5E,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Network-aware contract resolver. Returns `{ address, abi }` for each
|
|
3
|
+
* contract so callers can't accidentally pair the wrong ABI with the
|
|
4
|
+
* wrong address (the mainnet vs testnet PodManager param variant is the most common
|
|
5
|
+
* footgun: mainnet uses `mintPod(to, share)` while testnet uses
|
|
6
|
+
* `mintPodWithREPPO(to, subnetId)`).
|
|
7
|
+
*
|
|
8
|
+
* Throws via requireAddress() if the network's address is the TBD
|
|
9
|
+
* placeholder — fails loud rather than silently calling 0x0.
|
|
10
|
+
*/
|
|
11
|
+
import type { Address } from 'viem';
|
|
12
|
+
import { type Network } from './addresses.js';
|
|
13
|
+
import { POD_MANAGER_MAINNET_ABI, POD_MANAGER_TESTNET_ABI, SUBNET_MANAGER_ABI, VE_REPPO_ABI, ERC20_ABI } from './abis.js';
|
|
14
|
+
export interface Contract<TAbi> {
|
|
15
|
+
address: Address;
|
|
16
|
+
abi: TAbi;
|
|
17
|
+
}
|
|
18
|
+
export declare function podManager(network: Network): Contract<typeof POD_MANAGER_MAINNET_ABI | typeof POD_MANAGER_TESTNET_ABI>;
|
|
19
|
+
export declare function subnetManager(network: Network): Contract<typeof SUBNET_MANAGER_ABI>;
|
|
20
|
+
export declare function veReppo(network: Network): Contract<typeof VE_REPPO_ABI>;
|
|
21
|
+
export declare function reppoToken(network: Network): Contract<typeof ERC20_ABI>;
|
|
22
|
+
export declare function usdcToken(network: Network): Contract<typeof ERC20_ABI>;
|
|
23
|
+
export declare function tryPodManager(network: Network): Contract<typeof POD_MANAGER_MAINNET_ABI | typeof POD_MANAGER_TESTNET_ABI> | null;
|
|
24
|
+
export declare function trySubnetManager(network: Network): Contract<typeof SUBNET_MANAGER_ABI> | null;
|
|
25
|
+
export declare function tryVeReppo(network: Network): Contract<typeof VE_REPPO_ABI> | null;
|
|
26
|
+
export declare function tryReppoToken(network: Network): Contract<typeof ERC20_ABI> | null;
|
|
27
|
+
export declare function tryUsdcToken(network: Network): Contract<typeof ERC20_ABI> | null;
|
|
28
|
+
//# sourceMappingURL=contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.d.ts","sourceRoot":"","sources":["../../src/chain/contracts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACpC,OAAO,EAAgC,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EACL,uBAAuB,EACvB,uBAAuB,EACvB,kBAAkB,EAClB,YAAY,EACZ,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB,MAAM,WAAW,QAAQ,CAAC,IAAI;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,GAAG,EAAE,IAAI,CAAC;CACX;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,uBAAuB,GAAG,OAAO,uBAAuB,CAAC,CAMtH;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,kBAAkB,CAAC,CAMnF;AAED,wBAAgB,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,CAMvE;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,CAMvE;AAED,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,CAMtE;AAeD,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,GACf,QAAQ,CAAC,OAAO,uBAAuB,GAAG,OAAO,uBAAuB,CAAC,GAAG,IAAI,CAIlF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,kBAAkB,CAAC,GAAG,IAAI,CAG7F;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,YAAY,CAAC,GAAG,IAAI,CAGjF;AAED,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,GAAG,IAAI,CAGjF;AAED,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,QAAQ,CAAC,OAAO,SAAS,CAAC,GAAG,IAAI,CAGhF"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { getAddresses, requireAddress } from './addresses.js';
|
|
2
|
+
import { POD_MANAGER_MAINNET_ABI, POD_MANAGER_TESTNET_ABI, SUBNET_MANAGER_ABI, VE_REPPO_ABI, ERC20_ABI, } from './abis.js';
|
|
3
|
+
export function podManager(network) {
|
|
4
|
+
const addrs = getAddresses(network);
|
|
5
|
+
return {
|
|
6
|
+
address: requireAddress(addrs.podManager, 'PodManager'),
|
|
7
|
+
abi: network === 'mainnet' ? POD_MANAGER_MAINNET_ABI : POD_MANAGER_TESTNET_ABI,
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function subnetManager(network) {
|
|
11
|
+
const addrs = getAddresses(network);
|
|
12
|
+
return {
|
|
13
|
+
address: requireAddress(addrs.subnetManager, 'SubnetManager'),
|
|
14
|
+
abi: SUBNET_MANAGER_ABI,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
export function veReppo(network) {
|
|
18
|
+
const addrs = getAddresses(network);
|
|
19
|
+
return {
|
|
20
|
+
address: requireAddress(addrs.veReppo, 'veReppo'),
|
|
21
|
+
abi: VE_REPPO_ABI,
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export function reppoToken(network) {
|
|
25
|
+
const addrs = getAddresses(network);
|
|
26
|
+
return {
|
|
27
|
+
address: requireAddress(addrs.reppoToken, 'REPPO Token'),
|
|
28
|
+
abi: ERC20_ABI,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function usdcToken(network) {
|
|
32
|
+
const addrs = getAddresses(network);
|
|
33
|
+
return {
|
|
34
|
+
address: requireAddress(addrs.usdc, 'USDC'),
|
|
35
|
+
abi: ERC20_ABI,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// ── Non-throwing variants ──────────────────────────────────────────────
|
|
39
|
+
//
|
|
40
|
+
// Read commands (e.g. `query balance`) need to render an `unavailable`
|
|
41
|
+
// marker for contracts whose address is still TBD on the chosen network,
|
|
42
|
+
// rather than throwing. The `tryX()` helpers return null in that case so
|
|
43
|
+
// callers can decide policy without re-implementing the TBD check.
|
|
44
|
+
const TBD_PLACEHOLDER = '0x0000000000000000000000000000000000000000';
|
|
45
|
+
function tryAddress(addr) {
|
|
46
|
+
return addr === TBD_PLACEHOLDER ? null : addr;
|
|
47
|
+
}
|
|
48
|
+
export function tryPodManager(network) {
|
|
49
|
+
const a = tryAddress(getAddresses(network).podManager);
|
|
50
|
+
if (!a)
|
|
51
|
+
return null;
|
|
52
|
+
return { address: a, abi: network === 'mainnet' ? POD_MANAGER_MAINNET_ABI : POD_MANAGER_TESTNET_ABI };
|
|
53
|
+
}
|
|
54
|
+
export function trySubnetManager(network) {
|
|
55
|
+
const a = tryAddress(getAddresses(network).subnetManager);
|
|
56
|
+
return a ? { address: a, abi: SUBNET_MANAGER_ABI } : null;
|
|
57
|
+
}
|
|
58
|
+
export function tryVeReppo(network) {
|
|
59
|
+
const a = tryAddress(getAddresses(network).veReppo);
|
|
60
|
+
return a ? { address: a, abi: VE_REPPO_ABI } : null;
|
|
61
|
+
}
|
|
62
|
+
export function tryReppoToken(network) {
|
|
63
|
+
const a = tryAddress(getAddresses(network).reppoToken);
|
|
64
|
+
return a ? { address: a, abi: ERC20_ABI } : null;
|
|
65
|
+
}
|
|
66
|
+
export function tryUsdcToken(network) {
|
|
67
|
+
const a = tryAddress(getAddresses(network).usdc);
|
|
68
|
+
return a ? { address: a, abi: ERC20_ABI } : null;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../../src/chain/contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface DecodedError {
|
|
2
|
+
code: string;
|
|
3
|
+
hint?: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Decode a revert from a viem error. Walks the error chain looking for
|
|
7
|
+
* a ContractFunctionRevertedError and pulls the selector from its
|
|
8
|
+
* structured `data` (or `signature`). Returns the known code if we have
|
|
9
|
+
* one for it, else returns UNKNOWN_REVERT_<selector> so agents can still
|
|
10
|
+
* key off the raw selector.
|
|
11
|
+
*/
|
|
12
|
+
export declare function decodeRevert(err: unknown): DecodedError;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/chain/errors.ts"],"names":[],"mappings":"AAaA,UAAU,YAAY;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAuBD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,CAoCvD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps Reppo's custom error selectors to stable string codes the CLI emits
|
|
3
|
+
* to stderr. The string codes are the public contract — agent skill
|
|
4
|
+
* recipes match on them.
|
|
5
|
+
*
|
|
6
|
+
* Selectors are extracted via viem's typed error walker (BaseError.walk
|
|
7
|
+
* + ContractFunctionRevertedError) — NOT a regex over the message string.
|
|
8
|
+
* A regex would misread the first 4-byte chunk of any contract address
|
|
9
|
+
* embedded in viem's formatted message (e.g. "Contract Call: address: 0xcfF…")
|
|
10
|
+
* as the custom-error selector and return a bogus UNKNOWN_REVERT code.
|
|
11
|
+
*/
|
|
12
|
+
import { BaseError, ContractFunctionRevertedError } from 'viem';
|
|
13
|
+
const SELECTORS = {
|
|
14
|
+
'0xcabeb655': {
|
|
15
|
+
code: 'INSUFFICIENT_VOTING_POWER',
|
|
16
|
+
hint: 'Lock REPPO into veReppo first: `reppo lock <amount> --duration <seconds>` (see `reppo lock --help` for the network-specific minimum).',
|
|
17
|
+
},
|
|
18
|
+
'0x5bdedc41': {
|
|
19
|
+
code: 'PUBLISHER_LACKS_SUBNET_ACCESS',
|
|
20
|
+
hint: 'Grant subnet access to the publisher: `reppo grant-access --subnet <id>`.',
|
|
21
|
+
},
|
|
22
|
+
// Voter-vs-publisher revert observed but not yet name-matched. Keep
|
|
23
|
+
// the raw selector here so the hint still helps even without the name.
|
|
24
|
+
'0x11e43eec': {
|
|
25
|
+
code: 'VOTE_REJECTED_PRECONDITION',
|
|
26
|
+
hint: 'Vote was rejected by an unidentified precondition. Common causes: voter is the pod publisher (publishers cannot vote on their own pods), or the voting window has closed for that epoch.',
|
|
27
|
+
},
|
|
28
|
+
'0xfb8f41b2': {
|
|
29
|
+
code: 'INSUFFICIENT_ALLOWANCE',
|
|
30
|
+
hint: 'Approve the spender first. Most write commands handle this automatically once implemented; for the alpha you may need to send approve() manually.',
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Decode a revert from a viem error. Walks the error chain looking for
|
|
35
|
+
* a ContractFunctionRevertedError and pulls the selector from its
|
|
36
|
+
* structured `data` (or `signature`). Returns the known code if we have
|
|
37
|
+
* one for it, else returns UNKNOWN_REVERT_<selector> so agents can still
|
|
38
|
+
* key off the raw selector.
|
|
39
|
+
*/
|
|
40
|
+
export function decodeRevert(err) {
|
|
41
|
+
const fallback = (msg) => ({
|
|
42
|
+
code: 'REVERT',
|
|
43
|
+
hint: msg.split('\n')[0] ?? msg,
|
|
44
|
+
});
|
|
45
|
+
if (!(err instanceof BaseError)) {
|
|
46
|
+
return fallback(err instanceof Error ? err.message : String(err));
|
|
47
|
+
}
|
|
48
|
+
const reverted = err.walk((e) => e instanceof ContractFunctionRevertedError);
|
|
49
|
+
if (!reverted)
|
|
50
|
+
return fallback(err.shortMessage ?? err.message);
|
|
51
|
+
// viem populates `data.errorName` for known errors and `signature` for
|
|
52
|
+
// unknown selectors. We always want the 4-byte selector itself so the
|
|
53
|
+
// SELECTORS map is the single source of truth.
|
|
54
|
+
const data = reverted.data;
|
|
55
|
+
const sig = reverted.signature;
|
|
56
|
+
const raw = reverted.raw;
|
|
57
|
+
const selector = (sig ?? raw?.slice(0, 10) ?? '').toLowerCase();
|
|
58
|
+
if (!selector) {
|
|
59
|
+
return {
|
|
60
|
+
code: data?.errorName ? `REVERT_${data.errorName.toUpperCase()}` : 'REVERT',
|
|
61
|
+
hint: reverted.shortMessage,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
const known = SELECTORS[selector];
|
|
65
|
+
if (known)
|
|
66
|
+
return known;
|
|
67
|
+
return {
|
|
68
|
+
code: data?.errorName ? `REVERT_${data.errorName.toUpperCase()}` : `UNKNOWN_REVERT_${selector}`,
|
|
69
|
+
hint: reverted.shortMessage,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/chain/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,SAAS,EAAE,6BAA6B,EAAE,MAAM,MAAM,CAAC;AAOhE,MAAM,SAAS,GAAiC;IAC9C,YAAY,EAAE;QACZ,IAAI,EAAE,2BAA2B;QACjC,IAAI,EAAE,uIAAuI;KAC9I;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,+BAA+B;QACrC,IAAI,EAAE,2EAA2E;KAClF;IACD,oEAAoE;IACpE,uEAAuE;IACvE,YAAY,EAAE;QACZ,IAAI,EAAE,4BAA4B;QAClC,IAAI,EAAE,0LAA0L;KACjM;IACD,YAAY,EAAE;QACZ,IAAI,EAAE,wBAAwB;QAC9B,IAAI,EAAE,mJAAmJ;KAC1J;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAY;IACvC,MAAM,QAAQ,GAAG,CAAC,GAAW,EAAgB,EAAE,CAAC,CAAC;QAC/C,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG;KAChC,CAAC,CAAC;IAEH,IAAI,CAAC,CAAC,GAAG,YAAY,SAAS,CAAC,EAAE,CAAC;QAChC,OAAO,QAAQ,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;IACpE,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,YAAY,6BAA6B,CAEnE,CAAC;IACT,IAAI,CAAC,QAAQ;QAAE,OAAO,QAAQ,CAAC,GAAG,CAAC,YAAY,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IAEhE,uEAAuE;IACvE,sEAAsE;IACtE,+CAA+C;IAC/C,MAAM,IAAI,GAAI,QAAoF,CAAC,IAAI,CAAC;IACxG,MAAM,GAAG,GAAI,QAAqD,CAAC,SAAS,CAAC;IAC7E,MAAM,GAAG,GAAI,QAA+C,CAAC,GAAG,CAAC;IACjE,MAAM,QAAQ,GAAG,CAAC,GAAG,IAAI,GAAG,EAAE,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC;IAEhE,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO;YACL,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ;YAC3E,IAAI,EAAE,QAAQ,CAAC,YAAY;SAC5B,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;IAClC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO;QACL,IAAI,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,CAAC,kBAAkB,QAAQ,EAAE;QAC/F,IAAI,EAAE,QAAQ,CAAC,YAAY;KAC5B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared base class for all CLI commands. Wires up:
|
|
3
|
+
* - --network flag (overrides REPPO_NETWORK env)
|
|
4
|
+
* - --json flag (sets output mode)
|
|
5
|
+
* - --rpc-url flag (override RPC)
|
|
6
|
+
* - structured error catch
|
|
7
|
+
*
|
|
8
|
+
* Subclasses implement run() and call this.exit() on success.
|
|
9
|
+
*/
|
|
10
|
+
import { Command } from 'clipanion';
|
|
11
|
+
import { type Config } from '../config/load.js';
|
|
12
|
+
export declare abstract class BaseCommand extends Command {
|
|
13
|
+
network: string | undefined;
|
|
14
|
+
json: boolean;
|
|
15
|
+
rpcUrl: string | undefined;
|
|
16
|
+
protected loadConfig(): Config;
|
|
17
|
+
protected handleError(err: unknown): never;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=_base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_base.d.ts","sourceRoot":"","sources":["../../src/commands/_base.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAE5C,OAAO,EAAc,KAAK,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG5D,8BAAsB,WAAY,SAAQ,OAAO;IAC/C,OAAO,qBAAoE;IAC3E,IAAI,UAA2E;IAC/E,MAAM,qBAAmE;IAEzE,SAAS,CAAC,UAAU,IAAI,MAAM;IAgB9B,SAAS,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,KAAK;CAQ3C"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared base class for all CLI commands. Wires up:
|
|
3
|
+
* - --network flag (overrides REPPO_NETWORK env)
|
|
4
|
+
* - --json flag (sets output mode)
|
|
5
|
+
* - --rpc-url flag (override RPC)
|
|
6
|
+
* - structured error catch
|
|
7
|
+
*
|
|
8
|
+
* Subclasses implement run() and call this.exit() on success.
|
|
9
|
+
*/
|
|
10
|
+
import { Command, Option } from 'clipanion';
|
|
11
|
+
import { setOutputMode, fail, cliError } from '../output/format.js';
|
|
12
|
+
import { loadConfig } from '../config/load.js';
|
|
13
|
+
export class BaseCommand extends Command {
|
|
14
|
+
network = Option.String('--network', { description: 'mainnet | testnet' });
|
|
15
|
+
json = Option.Boolean('--json', false, { description: 'Emit JSON to stdout' });
|
|
16
|
+
rpcUrl = Option.String('--rpc-url', { description: 'Override RPC URL' });
|
|
17
|
+
loadConfig() {
|
|
18
|
+
setOutputMode(this.json ? 'json' : 'human');
|
|
19
|
+
const overrides = {};
|
|
20
|
+
if (this.network === 'mainnet' || this.network === 'testnet') {
|
|
21
|
+
overrides.network = this.network;
|
|
22
|
+
}
|
|
23
|
+
else if (this.network) {
|
|
24
|
+
throw cliError('INVALID_NETWORK', `--network must be "mainnet" or "testnet", got "${this.network}"`);
|
|
25
|
+
}
|
|
26
|
+
const cfg = loadConfig(overrides);
|
|
27
|
+
if (this.rpcUrl)
|
|
28
|
+
cfg.rpcUrl = this.rpcUrl;
|
|
29
|
+
return cfg;
|
|
30
|
+
}
|
|
31
|
+
handleError(err) {
|
|
32
|
+
const e = err;
|
|
33
|
+
fail({
|
|
34
|
+
code: e.code ?? 'INTERNAL_ERROR',
|
|
35
|
+
message: e.message ?? String(err),
|
|
36
|
+
...(e.hint ? { hint: e.hint } : {}),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=_base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_base.js","sourceRoot":"","sources":["../../src/commands/_base.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,UAAU,EAAe,MAAM,mBAAmB,CAAC;AAG5D,MAAM,OAAgB,WAAY,SAAQ,OAAO;IAC/C,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC3E,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC,CAAC;IAC/E,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,kBAAkB,EAAE,CAAC,CAAC;IAE/D,UAAU;QAClB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC5C,MAAM,SAAS,GAA0B,EAAE,CAAC;QAC5C,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAC7D,SAAS,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;QACnC,CAAC;aAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,MAAM,QAAQ,CACZ,iBAAiB,EACjB,kDAAkD,IAAI,CAAC,OAAO,GAAG,CAClE,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;QAClC,IAAI,IAAI,CAAC,MAAM;YAAE,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1C,OAAO,GAAG,CAAC;IACb,CAAC;IAES,WAAW,CAAC,GAAY;QAChC,MAAM,CAAC,GAAG,GAAyD,CAAC;QACpE,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,gBAAgB;YAChC,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,GAAG,CAAC;YACjC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACpC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { BaseCommand } from './_base.js';
|
|
2
|
+
export declare class AuthCommand extends BaseCommand {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
static usage: import("clipanion").Usage;
|
|
5
|
+
force: boolean;
|
|
6
|
+
execute(): Promise<number>;
|
|
7
|
+
private emitSession;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAqBA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAOzC,qBAAa,WAAY,SAAQ,WAAW;IAC1C,OAAgB,KAAK,aAAc;IAEnC,OAAgB,KAAK,4BAUlB;IAEH,KAAK,UAAoG;IAEnG,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;IAqChC,OAAO,CAAC,WAAW;CA4BpB"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `reppo auth` — sign in to the Reppo platform API (api.reppo.xyz).
|
|
3
|
+
*
|
|
4
|
+
* The platform API uses two-step EIP-191 wallet auth:
|
|
5
|
+
* 1. POST /auth/nonce { walletAddress } → { nonce, message }
|
|
6
|
+
* 2. POST /auth/verify { walletAddress, signature, nonce } → { token, ... }
|
|
7
|
+
*
|
|
8
|
+
* The returned token is a 24h Bearer credential. Cached in
|
|
9
|
+
* ~/.reppo/cli-state.json under sessions[`${network}:reppo-platform`].
|
|
10
|
+
* Subsequent commands that hit api.reppo.xyz (e.g. `query emissions-due`)
|
|
11
|
+
* read this cache and refresh on expiry.
|
|
12
|
+
*
|
|
13
|
+
* `reppo auth` is idempotent — if a valid cached token exists for the
|
|
14
|
+
* caller's wallet, it returns the existing session without re-signing.
|
|
15
|
+
* Pass `--force` to mint a fresh token regardless.
|
|
16
|
+
*
|
|
17
|
+
* NB: this command does NOT touch reppo.ai/api/v1/agents/* (a separate
|
|
18
|
+
* service with persistent tokens issued by `register-agent`).
|
|
19
|
+
*/
|
|
20
|
+
import { Option } from 'clipanion';
|
|
21
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
22
|
+
import { BaseCommand } from './_base.js';
|
|
23
|
+
import { cliError, emit } from '../output/format.js';
|
|
24
|
+
import { getOrRefreshSession, signInWithEthereum } from '../api/platform.js';
|
|
25
|
+
import { getSession, saveSession } from '../state/db.js';
|
|
26
|
+
const SESSION_KEY = 'reppo-platform';
|
|
27
|
+
export class AuthCommand extends BaseCommand {
|
|
28
|
+
static paths = [['auth']];
|
|
29
|
+
static usage = BaseCommand.Usage({
|
|
30
|
+
description: 'Sign in to the Reppo platform API (api.reppo.xyz). Caches a 24h session token.',
|
|
31
|
+
examples: [
|
|
32
|
+
['Sign in (no-op if cached token is still valid)',
|
|
33
|
+
'reppo auth'],
|
|
34
|
+
['Force a fresh sign-in even if cached token is valid',
|
|
35
|
+
'reppo auth --force'],
|
|
36
|
+
['JSON output (capture token expiry programmatically)',
|
|
37
|
+
'reppo auth --json'],
|
|
38
|
+
],
|
|
39
|
+
});
|
|
40
|
+
force = Option.Boolean('--force', false, { description: 'Re-sign even if a valid cached token exists' });
|
|
41
|
+
async execute() {
|
|
42
|
+
try {
|
|
43
|
+
const cfg = this.loadConfig();
|
|
44
|
+
const pk = cfg.privateKey;
|
|
45
|
+
if (!pk) {
|
|
46
|
+
throw cliError('MISSING_PRIVATE_KEY', 'No signing key available.', 'Set REPPO_PRIVATE_KEY in env. The platform API requires a wallet signature to sign in.');
|
|
47
|
+
}
|
|
48
|
+
if (this.force) {
|
|
49
|
+
// Bypass cache: sign fresh, save fresh, emit.
|
|
50
|
+
const account = privateKeyToAccount(pk);
|
|
51
|
+
if (!cfg.apiUrl) {
|
|
52
|
+
throw cliError('PLATFORM_API_NOT_CONFIGURED', 'No platform API URL configured for this network.', 'Mainnet defaults to https://api.reppo.xyz. On testnet, set REPPO_API_URL to your platform API endpoint.');
|
|
53
|
+
}
|
|
54
|
+
const fresh = await signInWithEthereum(cfg.apiUrl, account);
|
|
55
|
+
await saveSession(cfg.network, SESSION_KEY, fresh);
|
|
56
|
+
return this.emitSession(fresh, /*refreshed=*/ true);
|
|
57
|
+
}
|
|
58
|
+
// Default: get-or-refresh — uses cached token when valid.
|
|
59
|
+
const before = await getSession(cfg.network, SESSION_KEY);
|
|
60
|
+
const session = await getOrRefreshSession(cfg.network, cfg.apiUrl, pk);
|
|
61
|
+
const refreshed = !before || before.accessToken !== session.accessToken;
|
|
62
|
+
return this.emitSession(session, refreshed);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
this.handleError(err);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
emitSession(session, refreshed) {
|
|
69
|
+
const expiresAtMs = session.expiresAt ?? 0;
|
|
70
|
+
const expiresAtIso = expiresAtMs ? new Date(expiresAtMs).toISOString() : null;
|
|
71
|
+
const remainingSec = expiresAtMs ? Math.max(0, Math.floor((expiresAtMs - Date.now()) / 1000)) : null;
|
|
72
|
+
emit({
|
|
73
|
+
walletAddress: session.walletAddress,
|
|
74
|
+
expiresAt: expiresAtIso,
|
|
75
|
+
remainingSeconds: remainingSec,
|
|
76
|
+
refreshed,
|
|
77
|
+
// accessToken intentionally omitted from the canonical output —
|
|
78
|
+
// it lives in ~/.reppo/cli-state.json and is read by subsequent
|
|
79
|
+
// commands. Emitting it here would be a foot-gun (logs, screen
|
|
80
|
+
// shares). Pass --json + parse cli-state.json directly if you
|
|
81
|
+
// need the raw token.
|
|
82
|
+
}, [
|
|
83
|
+
refreshed ? `✓ Signed in (fresh token)` : `✓ Signed in (cached token still valid)`,
|
|
84
|
+
` wallet: ${session.walletAddress}`,
|
|
85
|
+
expiresAtIso ? ` expiresAt: ${expiresAtIso} (${remainingSec}s remaining)` : ` expiresAt: (unknown)`,
|
|
86
|
+
``,
|
|
87
|
+
` Token cached in ~/.reppo/cli-state.json. Subsequent commands hitting`,
|
|
88
|
+
` api.reppo.xyz (e.g. \`reppo query emissions-due\`) will use it automatically.`,
|
|
89
|
+
]);
|
|
90
|
+
return 0;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseCommand } from './_base.js';
|
|
2
|
+
export declare class ClaimEmissionsCommand extends BaseCommand {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
static usage: import("clipanion").Usage;
|
|
5
|
+
pod: string;
|
|
6
|
+
epoch: string;
|
|
7
|
+
idempotencyKey: string | undefined;
|
|
8
|
+
dryRun: boolean;
|
|
9
|
+
execute(): Promise<number>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=claim-emissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claim-emissions.d.ts","sourceRoot":"","sources":["../../src/commands/claim-emissions.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AASzC,qBAAa,qBAAsB,SAAQ,WAAW;IACpD,OAAgB,KAAK,aAAyB;IAE9C,OAAgB,KAAK,4BAUlB;IAEH,GAAG,SAA8C;IACjD,KAAK,SAAgD;IACrD,cAAc,qBAAsC;IACpD,MAAM,UAAsC;IAEtC,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC;CA2KjC"}
|