@reppo/cli 0.12.0 → 0.12.2

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.
@@ -23,11 +23,14 @@ export interface EnsureAllowanceResult {
23
23
  /** The approve tx hash, present only when `approved` is true. */
24
24
  approveTx?: `0x${string}`;
25
25
  }
26
+ /** Injectable sleeper so tests don't wait wall-clock time during the visibility poll. */
27
+ type Sleeper = (ms: number) => Promise<void>;
26
28
  /**
27
29
  * Ensure the caller has approved `spender` for at least `needed` of `token`.
28
30
  * Sends an unlimited approve() + waits for the receipt when short; no-op otherwise.
29
31
  * Pass `knownAllowance` to reuse an allowance the caller already read (avoids a
30
32
  * second RPC round-trip).
31
33
  */
32
- export declare function ensureAllowance(clients: Clients, token: Address, spender: Address, needed: bigint, knownAllowance?: bigint): Promise<EnsureAllowanceResult>;
34
+ export declare function ensureAllowance(clients: Clients, token: Address, spender: Address, needed: bigint, knownAllowance?: bigint, sleepFn?: Sleeper): Promise<EnsureAllowanceResult>;
35
+ export {};
33
36
  //# sourceMappingURL=allowance.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"allowance.d.ts","sourceRoot":"","sources":["../../src/chain/allowance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAM5C,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,SAAS,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,qBAAqB,CAAC,CA6BhC"}
1
+ {"version":3,"file":"allowance.d.ts","sourceRoot":"","sources":["../../src/chain/allowance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAM5C,MAAM,WAAW,qBAAqB;IACpC,kFAAkF;IAClF,QAAQ,EAAE,OAAO,CAAC;IAClB,iEAAiE;IACjE,SAAS,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CAC3B;AAOD,yFAAyF;AACzF,KAAK,OAAO,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAG7C;;;;;GAKG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM,EACd,cAAc,CAAC,EAAE,MAAM,EACvB,OAAO,GAAE,OAAmB,GAC3B,OAAO,CAAC,qBAAqB,CAAC,CA8ChC"}
@@ -20,13 +20,18 @@ import { nextNonce } from './clients.js';
20
20
  import { erc20 } from './contracts.js';
21
21
  import { decodeRevert } from './errors.js';
22
22
  import { cliError } from '../output/format.js';
23
+ /** Post-approve visibility poll bounds: 10 × 500ms ≈ 5s worst case — far beyond
24
+ * observed replica lag, negligible next to the approve's own receipt wait. */
25
+ const ALLOWANCE_VISIBILITY_POLLS = 10;
26
+ const ALLOWANCE_VISIBILITY_DELAY_MS = 500;
27
+ const realSleep = (ms) => new Promise((r) => setTimeout(r, ms));
23
28
  /**
24
29
  * Ensure the caller has approved `spender` for at least `needed` of `token`.
25
30
  * Sends an unlimited approve() + waits for the receipt when short; no-op otherwise.
26
31
  * Pass `knownAllowance` to reuse an allowance the caller already read (avoids a
27
32
  * second RPC round-trip).
28
33
  */
29
- export async function ensureAllowance(clients, token, spender, needed, knownAllowance) {
34
+ export async function ensureAllowance(clients, token, spender, needed, knownAllowance, sleepFn = realSleep) {
30
35
  const t = erc20(token);
31
36
  const allowance = knownAllowance ?? (await clients.publicClient.readContract({
32
37
  address: t.address, abi: t.abi, functionName: 'allowance',
@@ -53,6 +58,23 @@ export async function ensureAllowance(clients, token, spender, needed, knownAllo
53
58
  if (receipt.status === 'reverted') {
54
59
  throw cliError('APPROVE_REVERTED', `auto-approve tx reverted: ${approveTx}`, 'The approve() transaction reverted on-chain. Check the token contract and that the wallet holds gas.');
55
60
  }
61
+ // Receipt ≠ read-path visibility on load-balanced RPCs: the receipt confirms on ONE
62
+ // replica, but the caller's spend is simulated by whichever replica answers next — if
63
+ // that one hasn't applied the approve yet, the spend reverts InsufficientAllowance
64
+ // (0x13be252b) despite a successful approve (issue #55; observed live on
65
+ // grant-access --token primary). Poll the allowance through the same read path the
66
+ // spend will use until it reflects the approval, bounded. On timeout, fall through
67
+ // rather than fail: the spend may still succeed, and its own revert is more
68
+ // actionable than a synthetic error here.
69
+ for (let i = 0; i < ALLOWANCE_VISIBILITY_POLLS; i++) {
70
+ const visible = await clients.publicClient.readContract({
71
+ address: t.address, abi: t.abi, functionName: 'allowance',
72
+ args: [clients.account.address, spender],
73
+ });
74
+ if (visible >= needed)
75
+ break;
76
+ await sleepFn(ALLOWANCE_VISIBILITY_DELAY_MS);
77
+ }
56
78
  return { approved: true, approveTx };
57
79
  }
58
80
  //# sourceMappingURL=allowance.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"allowance.js","sourceRoot":"","sources":["../../src/chain/allowance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAgB,MAAM,MAAM,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAS/C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAgB,EAChB,KAAc,EACd,OAAgB,EAChB,MAAc,EACd,cAAuB;IAEvB,MAAM,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACvB,MAAM,SAAS,GAAG,cAAc,IAAI,CAAC,MAAM,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC;QAC3E,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW;QACzD,IAAI,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC;KACzC,CAAC,CAAC,CAAC;IACJ,IAAI,SAAS,IAAI,MAAM;QAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;IAEpD,IAAI,SAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC7E,SAAS,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC;YACnD,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,YAAY,EAAE,SAAS;YACvD,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC;YAC3B,KAAK,EAAE,OAAO,CAAC,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,KAAK;SACnE,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;QAChC,MAAM,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,kCAAkC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACjF,CAAC;IAED,8EAA8E;IAC9E,8EAA8E;IAC9E,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,CAAC,yBAAyB,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAC5G,IAAI,OAAO,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;QAClC,MAAM,QAAQ,CAAC,kBAAkB,EAAE,6BAA6B,SAAS,EAAE,EACzE,sGAAsG,CAAC,CAAC;IAC5G,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACvC,CAAC"}
1
+ {"version":3,"file":"allowance.js","sourceRoot":"","sources":["../../src/chain/allowance.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reppo/cli",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "Command-line interface for Reppo — mint pods, vote, lock REPPO, manage datanets. Built for AI agents.",
5
5
  "license": "MIT",
6
6
  "author": "Reppo Labs",