@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.
Files changed (107) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -0
  3. package/dist/api/platform.d.ts +39 -0
  4. package/dist/api/platform.d.ts.map +1 -0
  5. package/dist/api/platform.js +148 -0
  6. package/dist/api/platform.js.map +1 -0
  7. package/dist/bin.d.ts +3 -0
  8. package/dist/bin.d.ts.map +1 -0
  9. package/dist/bin.js +60 -0
  10. package/dist/bin.js.map +1 -0
  11. package/dist/chain/abis.d.ts +576 -0
  12. package/dist/chain/abis.d.ts.map +1 -0
  13. package/dist/chain/abis.js +66 -0
  14. package/dist/chain/abis.js.map +1 -0
  15. package/dist/chain/addresses.d.ts +27 -0
  16. package/dist/chain/addresses.d.ts.map +1 -0
  17. package/dist/chain/addresses.js +39 -0
  18. package/dist/chain/addresses.js.map +1 -0
  19. package/dist/chain/clients.d.ts +46 -0
  20. package/dist/chain/clients.d.ts.map +1 -0
  21. package/dist/chain/clients.js +48 -0
  22. package/dist/chain/clients.js.map +1 -0
  23. package/dist/chain/contracts.d.ts +28 -0
  24. package/dist/chain/contracts.d.ts.map +1 -0
  25. package/dist/chain/contracts.js +70 -0
  26. package/dist/chain/contracts.js.map +1 -0
  27. package/dist/chain/errors.d.ts +14 -0
  28. package/dist/chain/errors.d.ts.map +1 -0
  29. package/dist/chain/errors.js +72 -0
  30. package/dist/chain/errors.js.map +1 -0
  31. package/dist/commands/_base.d.ts +19 -0
  32. package/dist/commands/_base.d.ts.map +1 -0
  33. package/dist/commands/_base.js +40 -0
  34. package/dist/commands/_base.js.map +1 -0
  35. package/dist/commands/auth.d.ts +9 -0
  36. package/dist/commands/auth.d.ts.map +1 -0
  37. package/dist/commands/auth.js +93 -0
  38. package/dist/commands/auth.js.map +1 -0
  39. package/dist/commands/claim-emissions.d.ts +11 -0
  40. package/dist/commands/claim-emissions.d.ts.map +1 -0
  41. package/dist/commands/claim-emissions.js +192 -0
  42. package/dist/commands/claim-emissions.js.map +1 -0
  43. package/dist/commands/extend-lock.d.ts +11 -0
  44. package/dist/commands/extend-lock.d.ts.map +1 -0
  45. package/dist/commands/extend-lock.js +196 -0
  46. package/dist/commands/extend-lock.js.map +1 -0
  47. package/dist/commands/grant-access.d.ts +11 -0
  48. package/dist/commands/grant-access.d.ts.map +1 -0
  49. package/dist/commands/grant-access.js +191 -0
  50. package/dist/commands/grant-access.js.map +1 -0
  51. package/dist/commands/lock.d.ts +11 -0
  52. package/dist/commands/lock.d.ts.map +1 -0
  53. package/dist/commands/lock.js +192 -0
  54. package/dist/commands/lock.js.map +1 -0
  55. package/dist/commands/mint-pod.d.ts +15 -0
  56. package/dist/commands/mint-pod.d.ts.map +1 -0
  57. package/dist/commands/mint-pod.js +286 -0
  58. package/dist/commands/mint-pod.js.map +1 -0
  59. package/dist/commands/query/balance.d.ts +9 -0
  60. package/dist/commands/query/balance.d.ts.map +1 -0
  61. package/dist/commands/query/balance.js +91 -0
  62. package/dist/commands/query/balance.js.map +1 -0
  63. package/dist/commands/query/datanet.d.ts +10 -0
  64. package/dist/commands/query/datanet.d.ts.map +1 -0
  65. package/dist/commands/query/datanet.js +128 -0
  66. package/dist/commands/query/datanet.js.map +1 -0
  67. package/dist/commands/query/emissions-due.d.ts +18 -0
  68. package/dist/commands/query/emissions-due.d.ts.map +1 -0
  69. package/dist/commands/query/emissions-due.js +170 -0
  70. package/dist/commands/query/emissions-due.js.map +1 -0
  71. package/dist/commands/query/pod.d.ts +8 -0
  72. package/dist/commands/query/pod.d.ts.map +1 -0
  73. package/dist/commands/query/pod.js +88 -0
  74. package/dist/commands/query/pod.js.map +1 -0
  75. package/dist/commands/query/voting-power.d.ts +9 -0
  76. package/dist/commands/query/voting-power.d.ts.map +1 -0
  77. package/dist/commands/query/voting-power.js +82 -0
  78. package/dist/commands/query/voting-power.js.map +1 -0
  79. package/dist/commands/register-agent.d.ts +9 -0
  80. package/dist/commands/register-agent.d.ts.map +1 -0
  81. package/dist/commands/register-agent.js +115 -0
  82. package/dist/commands/register-agent.js.map +1 -0
  83. package/dist/commands/unlock.d.ts +11 -0
  84. package/dist/commands/unlock.d.ts.map +1 -0
  85. package/dist/commands/unlock.js +181 -0
  86. package/dist/commands/unlock.js.map +1 -0
  87. package/dist/commands/vote.d.ts +13 -0
  88. package/dist/commands/vote.d.ts.map +1 -0
  89. package/dist/commands/vote.js +174 -0
  90. package/dist/commands/vote.js.map +1 -0
  91. package/dist/config/load.d.ts +19 -0
  92. package/dist/config/load.d.ts.map +1 -0
  93. package/dist/config/load.js +66 -0
  94. package/dist/config/load.js.map +1 -0
  95. package/dist/output/format.d.ts +43 -0
  96. package/dist/output/format.d.ts.map +1 -0
  97. package/dist/output/format.js +58 -0
  98. package/dist/output/format.js.map +1 -0
  99. package/dist/state/db.d.ts +47 -0
  100. package/dist/state/db.d.ts.map +1 -0
  101. package/dist/state/db.js +169 -0
  102. package/dist/state/db.js.map +1 -0
  103. package/dist/state/idempotency.d.ts +66 -0
  104. package/dist/state/idempotency.d.ts.map +1 -0
  105. package/dist/state/idempotency.js +173 -0
  106. package/dist/state/idempotency.js.map +1 -0
  107. 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"}