tenjin-cli 0.1.0-alpha.0 → 0.1.0-alpha.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.
Files changed (138) hide show
  1. package/NOTICE.md +33 -0
  2. package/README.md +198 -18
  3. package/dist/{_esm-ZH2J4QEH.js → _esm-C5CRWCYU.js} +2 -2
  4. package/dist/_esm-FEASBWRP.js +881 -0
  5. package/dist/buy-U35DQ6XM.js +1598 -0
  6. package/dist/buy-U35DQ6XM.js.map +1 -0
  7. package/dist/candidate-RLYCQMF5.js +127 -0
  8. package/dist/candidate-RLYCQMF5.js.map +1 -0
  9. package/dist/{ccip-FXWZDDF5.js → ccip-NQXCEK2U.js} +6 -5
  10. package/dist/ccip-XR5NE5QK.js +19 -0
  11. package/dist/chunk-27ONARHV.js +171 -0
  12. package/dist/chunk-27ONARHV.js.map +1 -0
  13. package/dist/chunk-2I4QTOLB.js +11 -0
  14. package/dist/chunk-2I4QTOLB.js.map +1 -0
  15. package/dist/chunk-3OV7E5G5.js +18 -0
  16. package/dist/chunk-3OV7E5G5.js.map +1 -0
  17. package/dist/chunk-5CLSD5YN.js +209 -0
  18. package/dist/chunk-5CLSD5YN.js.map +1 -0
  19. package/dist/chunk-7KUW4MJD.js +59 -0
  20. package/dist/chunk-7KUW4MJD.js.map +1 -0
  21. package/dist/{doctor-MVLZRVPU.js → chunk-7PHSZKQS.js} +88 -93
  22. package/dist/chunk-7PHSZKQS.js.map +1 -0
  23. package/dist/chunk-CYOF7ROH.js +70 -0
  24. package/dist/chunk-CYOF7ROH.js.map +1 -0
  25. package/dist/chunk-HIVZG55D.js +204 -0
  26. package/dist/chunk-HIVZG55D.js.map +1 -0
  27. package/dist/chunk-HSDCI7OV.js +7806 -0
  28. package/dist/chunk-HSDCI7OV.js.map +1 -0
  29. package/dist/{chunk-LTTRND4A.js → chunk-IYLHQMT5.js} +85 -9
  30. package/dist/chunk-IYLHQMT5.js.map +1 -0
  31. package/dist/chunk-JPHG2JW3.js +96 -0
  32. package/dist/chunk-JPHG2JW3.js.map +1 -0
  33. package/dist/{chunk-ZPZFPVDN.js → chunk-MUBUQVC3.js} +1 -1
  34. package/dist/chunk-MUBUQVC3.js.map +1 -0
  35. package/dist/chunk-N62ROTMC.js +79 -0
  36. package/dist/chunk-N62ROTMC.js.map +1 -0
  37. package/dist/{chunk-SXQQ2ZSR.js → chunk-NCE5NSN6.js} +186 -18
  38. package/dist/chunk-NCE5NSN6.js.map +1 -0
  39. package/dist/{chunk-FIYZLITH.js → chunk-OYMYCW7J.js} +23 -4
  40. package/dist/{chunk-FIYZLITH.js.map → chunk-OYMYCW7J.js.map} +1 -1
  41. package/dist/chunk-QNP7H47L.js +152 -0
  42. package/dist/chunk-QNP7H47L.js.map +1 -0
  43. package/dist/{chunk-TX5T3LKJ.js → chunk-QVX5MWJZ.js} +21 -17
  44. package/dist/{chunk-TX5T3LKJ.js.map → chunk-QVX5MWJZ.js.map} +1 -1
  45. package/dist/{chunk-CPUZRZ2A.js → chunk-RBJPAZFI.js} +25 -170
  46. package/dist/chunk-RBJPAZFI.js.map +1 -0
  47. package/dist/chunk-RRN3YTK7.js +6199 -0
  48. package/dist/chunk-RRN3YTK7.js.map +1 -0
  49. package/dist/chunk-RY4XKNV3.js +140 -0
  50. package/dist/chunk-RY4XKNV3.js.map +1 -0
  51. package/dist/chunk-S3IGX57D.js +14682 -0
  52. package/dist/chunk-S3IGX57D.js.map +1 -0
  53. package/dist/{config-XVXZ3V2Q.js → chunk-TFGSOPWR.js} +117 -62
  54. package/dist/chunk-TFGSOPWR.js.map +1 -0
  55. package/dist/chunk-TLCMMYLY.js +126 -0
  56. package/dist/chunk-TLCMMYLY.js.map +1 -0
  57. package/dist/{chunk-PAAL45FJ.js → chunk-UGX7YPX2.js} +3446 -448
  58. package/dist/chunk-UGX7YPX2.js.map +1 -0
  59. package/dist/chunk-UO22YNY4.js +69 -0
  60. package/dist/chunk-UO22YNY4.js.map +1 -0
  61. package/dist/chunk-UPIEAMGH.js +160 -0
  62. package/dist/chunk-UPIEAMGH.js.map +1 -0
  63. package/dist/chunk-XJIW7USF.js +217 -0
  64. package/dist/chunk-XJIW7USF.js.map +1 -0
  65. package/dist/{chunk-F5DZJLU3.js → chunk-YALGASEU.js} +2065 -1258
  66. package/dist/chunk-YALGASEU.js.map +1 -0
  67. package/dist/chunk-YBMMV4Y4.js +51 -0
  68. package/dist/chunk-YBMMV4Y4.js.map +1 -0
  69. package/dist/chunk-YIYQ2ZNT.js +286 -0
  70. package/dist/chunk-YIYQ2ZNT.js.map +1 -0
  71. package/dist/{chunk-376LHMK2.js → chunk-YN5SHIXQ.js} +36 -10
  72. package/dist/chunk-YN5SHIXQ.js.map +1 -0
  73. package/dist/chunk-Z52RA3NC.js +137 -0
  74. package/dist/chunk-Z52RA3NC.js.map +1 -0
  75. package/dist/chunk-Z6MFJV5Z.js +1330 -0
  76. package/dist/chunk-Z6MFJV5Z.js.map +1 -0
  77. package/dist/chunk-ZABPQJ3M.js +83 -0
  78. package/dist/chunk-ZABPQJ3M.js.map +1 -0
  79. package/dist/{chunk-WOHCAMDQ.js → chunk-ZMHYXMO6.js} +1887 -1029
  80. package/dist/chunk-ZMHYXMO6.js.map +1 -0
  81. package/dist/{chunk-3IMLRUZE.js → chunk-ZXTAQYNA.js} +6 -2
  82. package/dist/{cli-LMHGCZ5S.js → cli-4NNBEQYH.js} +175 -179
  83. package/dist/cli-4NNBEQYH.js.map +1 -0
  84. package/dist/config-2VSXWWHK.js +21 -0
  85. package/dist/doctor-JJPNIBYH.js +20 -0
  86. package/dist/doctor-JJPNIBYH.js.map +1 -0
  87. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js +18 -0
  88. package/dist/ethersCompat-Df4a6QIZ-3YZIAXDK.js.map +1 -0
  89. package/dist/index.js +1 -1
  90. package/dist/inspect-JGYJWFDP.js +96 -0
  91. package/dist/inspect-JGYJWFDP.js.map +1 -0
  92. package/dist/install-ZQRMSRGW.js +378 -0
  93. package/dist/install-ZQRMSRGW.js.map +1 -0
  94. package/dist/lookup-WYVTOMVY.js +113 -0
  95. package/dist/lookup-WYVTOMVY.js.map +1 -0
  96. package/dist/{mine.wasm-GQECMSGN.js → mine.wasm-6PIT3DK6.js} +2 -2
  97. package/dist/outcome-HKKT6QIA.js +66 -0
  98. package/dist/outcome-HKKT6QIA.js.map +1 -0
  99. package/dist/publish-D76B3MBK.js +1480 -0
  100. package/dist/publish-D76B3MBK.js.map +1 -0
  101. package/dist/{secp256k1-35YNNB6F.js → secp256k1-N3ZHU7LB.js} +5 -4
  102. package/dist/secp256k1-N3ZHU7LB.js.map +1 -0
  103. package/dist/usdc-JIAJW4SV.js +22 -0
  104. package/dist/usdc-JIAJW4SV.js.map +1 -0
  105. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js +14 -0
  106. package/dist/viemAdapter-By13KInL-ZZE6UV4Y.js.map +1 -0
  107. package/dist/wallet-6QKS6UHW.js +179 -0
  108. package/dist/wallet-6QKS6UHW.js.map +1 -0
  109. package/dist/wallet-PA54CRBL.js +30 -0
  110. package/dist/wallet-PA54CRBL.js.map +1 -0
  111. package/package.json +20 -15
  112. package/skills/tenjin/SKILL.md +199 -0
  113. package/skills/tenjin-publish/SKILL.md +96 -0
  114. package/skills/tenjin-search/SKILL.md +122 -0
  115. package/dist/chunk-376LHMK2.js.map +0 -1
  116. package/dist/chunk-CPUZRZ2A.js.map +0 -1
  117. package/dist/chunk-F5DZJLU3.js.map +0 -1
  118. package/dist/chunk-LTTRND4A.js.map +0 -1
  119. package/dist/chunk-PAAL45FJ.js.map +0 -1
  120. package/dist/chunk-QHIEYBLV.js +0 -320
  121. package/dist/chunk-QHIEYBLV.js.map +0 -1
  122. package/dist/chunk-SXQQ2ZSR.js.map +0 -1
  123. package/dist/chunk-WOHCAMDQ.js.map +0 -1
  124. package/dist/chunk-ZPZFPVDN.js.map +0 -1
  125. package/dist/cli-LMHGCZ5S.js.map +0 -1
  126. package/dist/config-XVXZ3V2Q.js.map +0 -1
  127. package/dist/doctor-MVLZRVPU.js.map +0 -1
  128. package/dist/usdc-OQUOFF6R.js +0 -18
  129. package/dist/wallet-NRKWLKHX.js +0 -153
  130. package/dist/wallet-NRKWLKHX.js.map +0 -1
  131. package/dist/wallet-QUWK2PA4.js +0 -22
  132. /package/dist/{_esm-ZH2J4QEH.js.map → _esm-C5CRWCYU.js.map} +0 -0
  133. /package/dist/{ccip-FXWZDDF5.js.map → _esm-FEASBWRP.js.map} +0 -0
  134. /package/dist/{chunk-3IMLRUZE.js.map → ccip-NQXCEK2U.js.map} +0 -0
  135. /package/dist/{secp256k1-35YNNB6F.js.map → ccip-XR5NE5QK.js.map} +0 -0
  136. /package/dist/{usdc-OQUOFF6R.js.map → chunk-ZXTAQYNA.js.map} +0 -0
  137. /package/dist/{wallet-QUWK2PA4.js.map → config-2VSXWWHK.js.map} +0 -0
  138. /package/dist/{mine.wasm-GQECMSGN.js.map → mine.wasm-6PIT3DK6.js.map} +0 -0
@@ -0,0 +1,69 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+
3
+ // src/lib/policy.ts
4
+ function normCreator(value) {
5
+ return value.trim().toLowerCase();
6
+ }
7
+ function evaluateSpendPolicy(policy, req) {
8
+ if (req.maxPriceAtomic !== void 0 && req.amountAtomic > req.maxPriceAtomic) {
9
+ return {
10
+ decision: "deny",
11
+ reason: "price_cap_exceeded",
12
+ message: `Price ${req.amountAtomic} exceeds the --max-price cap ${req.maxPriceAtomic}.`
13
+ };
14
+ }
15
+ if (policy.allowlistCreators.length > 0) {
16
+ const allowed = policy.allowlistCreators.map(normCreator);
17
+ if (!allowed.includes(normCreator(req.creator))) {
18
+ return {
19
+ decision: "deny",
20
+ reason: "not_allowlisted",
21
+ message: `Creator "${req.creator}" is not in allowlistCreators.`
22
+ };
23
+ }
24
+ }
25
+ if (policy.sessionBudgetAtomic > 0n) {
26
+ const projected = req.sessionSpentAtomic + req.amountAtomic;
27
+ if (projected > policy.sessionBudgetAtomic) {
28
+ return {
29
+ decision: "deny",
30
+ reason: "session_budget_exceeded",
31
+ message: `This spend would bring the session total to ${projected}, over sessionBudget ${policy.sessionBudgetAtomic}.`
32
+ };
33
+ }
34
+ }
35
+ if (req.amountAtomic > policy.maxAutoSpendAtomic) {
36
+ return {
37
+ decision: "confirm",
38
+ reason: "above_auto_spend",
39
+ message: `Price ${req.amountAtomic} is above maxAutoSpend ${policy.maxAutoSpendAtomic}; confirmation required.`
40
+ };
41
+ }
42
+ if (policy.confirm.mode === "always") {
43
+ return {
44
+ decision: "confirm",
45
+ reason: "confirm_always",
46
+ message: 'confirm policy is "always"; confirmation required.'
47
+ };
48
+ }
49
+ if (req.amountAtomic > policy.confirm.thresholdAtomic) {
50
+ return {
51
+ decision: "confirm",
52
+ reason: "above_confirm_threshold",
53
+ message: `Price ${req.amountAtomic} is above the confirm threshold ${policy.confirm.thresholdAtomic}; confirmation required.`
54
+ };
55
+ }
56
+ return { decision: "allow", reason: "within_policy", message: "within spend policy" };
57
+ }
58
+ function parseConfirmPolicy(stored) {
59
+ if (stored === "always") return { mode: "always" };
60
+ const m = /^above:(\d+)$/.exec(stored);
61
+ if (m && m[1] !== void 0) return { mode: "above", thresholdAtomic: BigInt(m[1]) };
62
+ return { mode: "always" };
63
+ }
64
+
65
+ export {
66
+ evaluateSpendPolicy,
67
+ parseConfirmPolicy
68
+ };
69
+ //# sourceMappingURL=chunk-UO22YNY4.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/policy.ts"],"sourcesContent":["/**\n * Spend-policy evaluation, pure and provider-agnostic. The wallet provider layer\n * (lib/wallet/spend.ts) owns the ledger and calls this; a future hosted provider\n * (Privy, B5) reuses the same decision rules, so the knobs live in exactly one\n * place. Nothing here does IO, the caller supplies the already-spent total and\n * decides how to satisfy a `confirm` decision (a `--yes`, a TTY prompt, or a\n * non-interactive refusal).\n */\n\n/** How a `confirm` gate is configured (parsed from the stored config string). */\nexport type ConfirmPolicy = { mode: 'always' } | { mode: 'above'; thresholdAtomic: bigint };\n\nexport interface SpendPolicy {\n /** Amounts at or below this auto-approve WITHOUT a prompt (still subject to the\n * confirm gate below). Default 0 → nothing auto-approves. */\n maxAutoSpendAtomic: bigint;\n /** Rolling local ceiling on cumulative session spend. 0 = disabled (no ceiling). */\n sessionBudgetAtomic: bigint;\n /** When a human confirmation is requested. */\n confirm: ConfirmPolicy;\n /** Creators (handle or 0x-address, lowercased) auto-payment is restricted to.\n * Empty = no restriction. A non-empty list is a hard gate: a non-member is\n * denied even with `--yes`. */\n allowlistCreators: string[];\n}\n\nexport interface SpendRequest {\n amountAtomic: bigint;\n /** Creator identity from the 402 preview / candidate, handle or 0x address. */\n creator: string;\n /** The caller's `--max-price` cap, if given. A hard ceiling, never bypassable. */\n maxPriceAtomic?: bigint;\n /** Cumulative spend already recorded in this rolling session window. */\n sessionSpentAtomic: bigint;\n}\n\n/**\n * `allow`: within policy, proceed silently. `confirm`: an approval is required ,\n * the caller satisfies it with `--yes`, an interactive prompt, or refuses. `deny`:\n * a hard gate blocked it (price cap, allowlist, session budget); NOT satisfiable\n * by `--yes` or a prompt.\n */\nexport type SpendDecision = 'allow' | 'confirm' | 'deny';\n\nexport type PolicyReason =\n | 'within_policy'\n | 'price_cap_exceeded'\n | 'not_allowlisted'\n | 'session_budget_exceeded'\n | 'above_auto_spend'\n | 'confirm_always'\n | 'above_confirm_threshold';\n\nexport interface PolicyEvaluation {\n decision: SpendDecision;\n reason: PolicyReason;\n message: string;\n}\n\n/** Normalize a creator identity for allowlist comparison (case-insensitive; a\n * word-handle and a 0x address are both single tokens). */\nfunction normCreator(value: string): string {\n return value.trim().toLowerCase();\n}\n\n/**\n * Evaluate one spend against the policy. Hard gates run first (price cap →\n * allowlist → session budget); only if all pass is the confirm gate consulted. A\n * spend at or below `maxAutoSpend` that the confirm policy would not prompt for is\n * the only `allow`; everything else within the hard gates is `confirm`.\n */\nexport function evaluateSpendPolicy(policy: SpendPolicy, req: SpendRequest): PolicyEvaluation {\n if (req.maxPriceAtomic !== undefined && req.amountAtomic > req.maxPriceAtomic) {\n return {\n decision: 'deny',\n reason: 'price_cap_exceeded',\n message: `Price ${req.amountAtomic} exceeds the --max-price cap ${req.maxPriceAtomic}.`,\n };\n }\n\n if (policy.allowlistCreators.length > 0) {\n const allowed = policy.allowlistCreators.map(normCreator);\n if (!allowed.includes(normCreator(req.creator))) {\n return {\n decision: 'deny',\n reason: 'not_allowlisted',\n message: `Creator \"${req.creator}\" is not in allowlistCreators.`,\n };\n }\n }\n\n if (policy.sessionBudgetAtomic > 0n) {\n const projected = req.sessionSpentAtomic + req.amountAtomic;\n if (projected > policy.sessionBudgetAtomic) {\n return {\n decision: 'deny',\n reason: 'session_budget_exceeded',\n message: `This spend would bring the session total to ${projected}, over sessionBudget ${policy.sessionBudgetAtomic}.`,\n };\n }\n }\n\n if (req.amountAtomic > policy.maxAutoSpendAtomic) {\n return {\n decision: 'confirm',\n reason: 'above_auto_spend',\n message: `Price ${req.amountAtomic} is above maxAutoSpend ${policy.maxAutoSpendAtomic}; confirmation required.`,\n };\n }\n\n if (policy.confirm.mode === 'always') {\n return {\n decision: 'confirm',\n reason: 'confirm_always',\n message: 'confirm policy is \"always\"; confirmation required.',\n };\n }\n\n if (req.amountAtomic > policy.confirm.thresholdAtomic) {\n return {\n decision: 'confirm',\n reason: 'above_confirm_threshold',\n message: `Price ${req.amountAtomic} is above the confirm threshold ${policy.confirm.thresholdAtomic}; confirmation required.`,\n };\n }\n\n return { decision: 'allow', reason: 'within_policy', message: 'within spend policy' };\n}\n\n/** Parse the stored `confirm` config value (\"always\" | \"above:<atomic>\"). */\nexport function parseConfirmPolicy(stored: string): ConfirmPolicy {\n if (stored === 'always') return { mode: 'always' };\n const m = /^above:(\\d+)$/.exec(stored);\n if (m && m[1] !== undefined) return { mode: 'above', thresholdAtomic: BigInt(m[1]) };\n // The config schema already constrains this; a malformed value here is a bug,\n // so fail closed to the safest interpretation rather than throwing mid-buy.\n return { mode: 'always' };\n}\n"],"mappings":";;;AA6DA,SAAS,YAAY,OAAuB;AAC1C,SAAO,MAAM,KAAK,EAAE,YAAY;AAClC;AAQO,SAAS,oBAAoB,QAAqB,KAAqC;AAC5F,MAAI,IAAI,mBAAmB,UAAa,IAAI,eAAe,IAAI,gBAAgB;AAC7E,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,SAAS,IAAI,YAAY,gCAAgC,IAAI,cAAc;AAAA,IACtF;AAAA,EACF;AAEA,MAAI,OAAO,kBAAkB,SAAS,GAAG;AACvC,UAAM,UAAU,OAAO,kBAAkB,IAAI,WAAW;AACxD,QAAI,CAAC,QAAQ,SAAS,YAAY,IAAI,OAAO,CAAC,GAAG;AAC/C,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,YAAY,IAAI,OAAO;AAAA,MAClC;AAAA,IACF;AAAA,EACF;AAEA,MAAI,OAAO,sBAAsB,IAAI;AACnC,UAAM,YAAY,IAAI,qBAAqB,IAAI;AAC/C,QAAI,YAAY,OAAO,qBAAqB;AAC1C,aAAO;AAAA,QACL,UAAU;AAAA,QACV,QAAQ;AAAA,QACR,SAAS,+CAA+C,SAAS,wBAAwB,OAAO,mBAAmB;AAAA,MACrH;AAAA,IACF;AAAA,EACF;AAEA,MAAI,IAAI,eAAe,OAAO,oBAAoB;AAChD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,SAAS,IAAI,YAAY,0BAA0B,OAAO,kBAAkB;AAAA,IACvF;AAAA,EACF;AAEA,MAAI,OAAO,QAAQ,SAAS,UAAU;AACpC,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS;AAAA,IACX;AAAA,EACF;AAEA,MAAI,IAAI,eAAe,OAAO,QAAQ,iBAAiB;AACrD,WAAO;AAAA,MACL,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,SAAS,SAAS,IAAI,YAAY,mCAAmC,OAAO,QAAQ,eAAe;AAAA,IACrG;AAAA,EACF;AAEA,SAAO,EAAE,UAAU,SAAS,QAAQ,iBAAiB,SAAS,sBAAsB;AACtF;AAGO,SAAS,mBAAmB,QAA+B;AAChE,MAAI,WAAW,SAAU,QAAO,EAAE,MAAM,SAAS;AACjD,QAAM,IAAI,gBAAgB,KAAK,MAAM;AACrC,MAAI,KAAK,EAAE,CAAC,MAAM,OAAW,QAAO,EAAE,MAAM,SAAS,iBAAiB,OAAO,EAAE,CAAC,CAAC,EAAE;AAGnF,SAAO,EAAE,MAAM,SAAS;AAC1B;","names":[]}
@@ -0,0 +1,160 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+ import {
3
+ PublishModeSchema,
4
+ loadRawConfig,
5
+ parseUsdToAtomic,
6
+ resolvePublishDefaultPrice,
7
+ resolvePublishMode,
8
+ resolveSettings
9
+ } from "./chunk-IYLHQMT5.js";
10
+ import {
11
+ parseConfirmPolicy
12
+ } from "./chunk-UO22YNY4.js";
13
+ import {
14
+ CliError,
15
+ external_exports
16
+ } from "./chunk-OYMYCW7J.js";
17
+
18
+ // src/lib/settings.ts
19
+ import { execFile } from "child_process";
20
+ import { readFile, stat } from "fs/promises";
21
+ import { homedir } from "os";
22
+ import { dirname, join } from "path";
23
+ async function resolveContextSettings(ctx) {
24
+ const config = await loadRawConfig(ctx.dataDir);
25
+ const s = resolveSettings({ config, flags: { baseUrl: ctx.flags.baseUrl }, env: process.env });
26
+ return {
27
+ baseUrl: s.baseUrl.value,
28
+ rpcUrl: s.rpcUrl.value,
29
+ evalCohort: s.evalCohort.value,
30
+ policy: {
31
+ maxAutoSpendAtomic: BigInt(s.maxAutoSpend.value),
32
+ sessionBudgetAtomic: BigInt(s.sessionBudget.value),
33
+ confirm: parseConfirmPolicy(s.confirm.value),
34
+ allowlistCreators: s.allowlistCreators.value
35
+ }
36
+ };
37
+ }
38
+ var PROJECT_CONFIG_FILE = ".tenjin.json";
39
+ var ProjectConfigSchema = external_exports.object({
40
+ publish: external_exports.object({
41
+ mode: PublishModeSchema.optional(),
42
+ defaultPrice: external_exports.string().optional()
43
+ }).passthrough().optional()
44
+ }).passthrough();
45
+ async function resolvePublishSettings(input, deps = {}) {
46
+ const env = input.env ?? process.env;
47
+ const config = await loadRawConfig(input.dataDir);
48
+ const project = await loadProjectConfig(input.cwd, deps);
49
+ const layer = project?.layer;
50
+ const mode = resolvePublishMode({ config, project: layer, env, flag: input.flag });
51
+ const price = resolvePublishDefaultPrice({ config, project: layer });
52
+ const warnings = mode.downgradedWarning !== void 0 ? [mode.downgradedWarning] : [];
53
+ return {
54
+ mode: mode.value,
55
+ modeSource: mode.source,
56
+ defaultPriceAtomic: price.value,
57
+ defaultPriceSource: price.source,
58
+ warnings,
59
+ ...project !== null ? { projectConfigPath: project.path } : {}
60
+ };
61
+ }
62
+ async function loadProjectConfig(cwd, deps = {}) {
63
+ const path = await findProjectConfigFile(cwd, deps);
64
+ if (path === null) return null;
65
+ let json;
66
+ try {
67
+ json = JSON.parse(await readFile(path, "utf8"));
68
+ } catch (err) {
69
+ throw new CliError("CONFIG_INVALID", `${PROJECT_CONFIG_FILE} at ${path} could not be read`, {
70
+ fix: `Fix or delete ${path} (must be a readable JSON file).`,
71
+ cause: err
72
+ });
73
+ }
74
+ const parsed = ProjectConfigSchema.safeParse(json);
75
+ if (!parsed.success) {
76
+ throw new CliError("CONFIG_INVALID", `${PROJECT_CONFIG_FILE} at ${path} is invalid`, {
77
+ fix: `Correct the reported keys in ${path}, or delete it.`,
78
+ details: parsed.error.issues
79
+ });
80
+ }
81
+ const isGitignored = deps.isGitignored ?? defaultIsGitignored;
82
+ const gitignored = await isGitignored(path);
83
+ const layer = { gitignored };
84
+ if (parsed.data.publish !== void 0) {
85
+ const { mode, defaultPrice } = parsed.data.publish;
86
+ layer.publish = {
87
+ ...mode !== void 0 ? { mode } : {},
88
+ ...defaultPrice !== void 0 ? { defaultPrice: parseProjectPrice(defaultPrice, path) } : {}
89
+ };
90
+ }
91
+ return { path, layer };
92
+ }
93
+ function parseProjectPrice(decimalUsd, path) {
94
+ try {
95
+ return parseUsdToAtomic(decimalUsd);
96
+ } catch (err) {
97
+ throw new CliError(
98
+ "CONFIG_INVALID",
99
+ `${PROJECT_CONFIG_FILE} at ${path} has an invalid publish.defaultPrice`,
100
+ { fix: 'Use a non-negative decimal USD amount like "0.10".', cause: err }
101
+ );
102
+ }
103
+ }
104
+ async function findProjectConfigFile(cwd, deps) {
105
+ const homeDir = deps.homeDir ?? homedir();
106
+ const isForeignOwned = deps.isForeignOwned ?? defaultIsForeignOwned;
107
+ const warn = deps.warn ?? ((message) => process.stderr.write(`${message}
108
+ `));
109
+ let dir = cwd;
110
+ for (; ; ) {
111
+ const candidate = join(dir, PROJECT_CONFIG_FILE);
112
+ if (await pathExists(candidate)) {
113
+ if (await isForeignOwned(candidate)) {
114
+ warn(`Ignoring ${candidate}: not owned by the current user.`);
115
+ } else {
116
+ return candidate;
117
+ }
118
+ }
119
+ if (await pathExists(join(dir, ".git"))) return null;
120
+ if (dir === homeDir) return null;
121
+ const parent = dirname(dir);
122
+ if (parent === dir) return null;
123
+ dir = parent;
124
+ }
125
+ }
126
+ async function defaultIsForeignOwned(filePath) {
127
+ const uid = process.getuid?.();
128
+ if (uid === void 0) return false;
129
+ try {
130
+ return (await stat(filePath)).uid !== uid;
131
+ } catch {
132
+ return false;
133
+ }
134
+ }
135
+ async function pathExists(path) {
136
+ try {
137
+ await stat(path);
138
+ return true;
139
+ } catch {
140
+ return false;
141
+ }
142
+ }
143
+ function defaultIsGitignored(filePath) {
144
+ return new Promise((resolve) => {
145
+ execFile(
146
+ "git",
147
+ ["check-ignore", "--quiet", "--", filePath],
148
+ { cwd: dirname(filePath) },
149
+ (err) => resolve(err === null)
150
+ );
151
+ });
152
+ }
153
+
154
+ export {
155
+ resolveContextSettings,
156
+ resolvePublishSettings,
157
+ loadProjectConfig,
158
+ pathExists
159
+ };
160
+ //# sourceMappingURL=chunk-UPIEAMGH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/settings.ts"],"sourcesContent":["import { execFile } from 'node:child_process';\nimport { readFile, stat } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { dirname, join } from 'node:path';\nimport { z } from 'zod';\nimport { CliError } from './errors';\nimport {\n PublishModeSchema,\n loadRawConfig,\n resolvePublishDefaultPrice,\n resolvePublishMode,\n resolveSettings,\n} from './config';\nimport type { Provenance, ProjectPublishLayer, PublishMode } from './config';\nimport { parseUsdToAtomic } from './money';\nimport { parseConfirmPolicy, type SpendPolicy } from './policy';\nimport type { CommandContext } from '../context';\n\n/**\n * The effective runtime settings a B2 command needs, resolved once through the\n * same precedence (flag > env > file > default) config/doctor use. Spend values\n * arrive atomic from config and are handed on as bigint for the policy layer.\n */\nexport interface ResolvedSettings {\n baseUrl: string;\n rpcUrl: string;\n policy: SpendPolicy;\n /** Lookup-only privacy opt-in; sends X-Tenjin-Eval-Cohort: 1 when true. */\n evalCohort: boolean;\n}\n\nexport async function resolveContextSettings(ctx: CommandContext): Promise<ResolvedSettings> {\n const config = await loadRawConfig(ctx.dataDir);\n const s = resolveSettings({ config, flags: { baseUrl: ctx.flags.baseUrl }, env: process.env });\n return {\n baseUrl: s.baseUrl.value,\n rpcUrl: s.rpcUrl.value,\n evalCohort: s.evalCohort.value,\n policy: {\n maxAutoSpendAtomic: BigInt(s.maxAutoSpend.value),\n sessionBudgetAtomic: BigInt(s.sessionBudget.value),\n confirm: parseConfirmPolicy(s.confirm.value),\n allowlistCreators: s.allowlistCreators.value,\n },\n };\n}\n\n// ---------------------------------------------------------------------------\n// Publish consent settings (B3, D38)\n//\n// The publish mode/price cascade extends the same precedence machinery\n// (resolvePublishMode / resolvePublishDefaultPrice in lib/config) with a\n// per-project layer that needs I/O the pure resolvers can't do: it walks up from\n// cwd for a `.tenjin.json` and asks git whether that file is committed (the\n// loosening gate on `full-auto`). It lives here beside resolveContextSettings so\n// there is one settings resolver, not a parallel one.\n// ---------------------------------------------------------------------------\n\nexport const PROJECT_CONFIG_FILE = '.tenjin.json';\n\n/**\n * The per-project override file. `publish.defaultPrice` is DECIMAL USD (\"0.10\"),\n * because a hand-edited project file is a human edge (O1) — unlike config.json,\n * which stores atomic because `config set` converts at the command edge. The\n * decimal string is converted to atomic at load via the same money util the\n * config command uses. Partial + passthrough: forward-compatible with subkeys a\n * newer CLI adds, same posture as the global config.\n */\nconst ProjectConfigSchema = z\n .object({\n publish: z\n .object({\n mode: PublishModeSchema.optional(),\n defaultPrice: z.string().optional(),\n })\n .passthrough()\n .optional(),\n })\n .passthrough();\n\nexport interface LoadedProjectConfig {\n /** Absolute path of the discovered `.tenjin.json`. */\n path: string;\n layer: ProjectPublishLayer;\n}\n\nexport interface PublishSettingsDeps {\n /** git check-ignore seam; defaults to shelling out to git (see wallet/passphrase). */\n isGitignored?: (filePath: string) => Promise<boolean>;\n /** Ownership seam; defaults to stat().uid vs process uid. Gates a planted file. */\n isForeignOwned?: (filePath: string) => Promise<boolean>;\n /** One-line stderr warning sink; defaults to process.stderr. */\n warn?: (message: string) => void;\n /** Upper bound of the walk; defaults to the user's home directory. */\n homeDir?: string;\n}\n\nexport interface ResolvedPublishSettings {\n mode: PublishMode;\n modeSource: Provenance;\n defaultPriceAtomic: string;\n defaultPriceSource: Provenance;\n /** Non-fatal notices for stderr (e.g. the full-auto downgrade). */\n warnings: string[];\n /** The `.tenjin.json` that contributed the project layer, if one was found. */\n projectConfigPath?: string;\n}\n\n/**\n * Resolve the effective publish mode + default price across every layer:\n * global config.json < project `.tenjin.json` < env (TENJIN_PUBLISH_MODE) <\n * flag (`--mode`), with the `full-auto` loosening gate applied to the project\n * layer. The seam a `publish` command (B3.2) resolves its consent through.\n */\nexport async function resolvePublishSettings(\n input: { dataDir: string; cwd: string; flag?: string; env?: NodeJS.ProcessEnv },\n deps: PublishSettingsDeps = {},\n): Promise<ResolvedPublishSettings> {\n const env = input.env ?? process.env;\n const config = await loadRawConfig(input.dataDir);\n const project = await loadProjectConfig(input.cwd, deps);\n const layer = project?.layer;\n\n const mode = resolvePublishMode({ config, project: layer, env, flag: input.flag });\n const price = resolvePublishDefaultPrice({ config, project: layer });\n const warnings = mode.downgradedWarning !== undefined ? [mode.downgradedWarning] : [];\n\n return {\n mode: mode.value,\n modeSource: mode.source,\n defaultPriceAtomic: price.value,\n defaultPriceSource: price.source,\n warnings,\n ...(project !== null ? { projectConfigPath: project.path } : {}),\n };\n}\n\n/**\n * Find the nearest `.tenjin.json` walking up from cwd toward the repo root (the\n * first directory holding a `.git`, inclusive), never crossing above $HOME, then\n * load, validate, and check whether it is gitignored. A file not owned by the\n * current user is ignored with a stderr warning (a planted config on a shared\n * host must not become the honored project layer). Null when none is found; a\n * present-but-unreadable/malformed file is CONFIG_INVALID (never silently\n * skipped).\n */\nexport async function loadProjectConfig(\n cwd: string,\n deps: PublishSettingsDeps = {},\n): Promise<LoadedProjectConfig | null> {\n const path = await findProjectConfigFile(cwd, deps);\n if (path === null) return null;\n\n let json: unknown;\n try {\n // readFile is inside the try: a raced delete (ENOENT), a directory named\n // .tenjin.json (EISDIR), or a permission error (EACCES) is a bad project file,\n // not an INTERNAL fault.\n json = JSON.parse(await readFile(path, 'utf8'));\n } catch (err) {\n throw new CliError('CONFIG_INVALID', `${PROJECT_CONFIG_FILE} at ${path} could not be read`, {\n fix: `Fix or delete ${path} (must be a readable JSON file).`,\n cause: err,\n });\n }\n const parsed = ProjectConfigSchema.safeParse(json);\n if (!parsed.success) {\n throw new CliError('CONFIG_INVALID', `${PROJECT_CONFIG_FILE} at ${path} is invalid`, {\n fix: `Correct the reported keys in ${path}, or delete it.`,\n details: parsed.error.issues,\n });\n }\n\n const isGitignored = deps.isGitignored ?? defaultIsGitignored;\n const gitignored = await isGitignored(path);\n const layer: ProjectPublishLayer = { gitignored };\n if (parsed.data.publish !== undefined) {\n const { mode, defaultPrice } = parsed.data.publish;\n layer.publish = {\n ...(mode !== undefined ? { mode } : {}),\n ...(defaultPrice !== undefined\n ? { defaultPrice: parseProjectPrice(defaultPrice, path) }\n : {}),\n };\n }\n return { path, layer };\n}\n\n/**\n * Convert a `.tenjin.json` decimal-USD price to atomic via the shared money\n * parser. parseUsdToAtomic throws USAGE on a bad amount; re-raise as\n * CONFIG_INVALID naming the file, so it reads like the file's other errors.\n */\nfunction parseProjectPrice(decimalUsd: string, path: string): string {\n try {\n return parseUsdToAtomic(decimalUsd);\n } catch (err) {\n throw new CliError(\n 'CONFIG_INVALID',\n `${PROJECT_CONFIG_FILE} at ${path} has an invalid publish.defaultPrice`,\n { fix: 'Use a non-negative decimal USD amount like \"0.10\".', cause: err },\n );\n }\n}\n\nasync function findProjectConfigFile(\n cwd: string,\n deps: PublishSettingsDeps,\n): Promise<string | null> {\n const homeDir = deps.homeDir ?? homedir();\n const isForeignOwned = deps.isForeignOwned ?? defaultIsForeignOwned;\n const warn = deps.warn ?? ((message: string) => process.stderr.write(`${message}\\n`));\n\n let dir = cwd;\n // Bounded by $HOME (a shared-host trust boundary) and the filesystem root\n // (dirname('/') === '/'), whichever comes first.\n for (;;) {\n const candidate = join(dir, PROJECT_CONFIG_FILE);\n if (await pathExists(candidate)) {\n if (await isForeignOwned(candidate)) {\n // A file owned by another user (e.g. /tmp/.tenjin.json on a shared box)\n // must never become the honored layer; skip it and keep walking.\n warn(`Ignoring ${candidate}: not owned by the current user.`);\n } else {\n return candidate;\n }\n }\n if (await pathExists(join(dir, '.git'))) return null; // repo root, no file\n if (dir === homeDir) return null; // never cross above $HOME\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n/**\n * True when the file is owned by a different uid than the process. On a platform\n * without a uid model (Windows: process.getuid is undefined) this is always\n * false — the ownership gate is a POSIX shared-host protection.\n */\nasync function defaultIsForeignOwned(filePath: string): Promise<boolean> {\n const uid = process.getuid?.();\n if (uid === undefined) return false;\n try {\n return (await stat(filePath)).uid !== uid;\n } catch {\n return false;\n }\n}\n\n/** True when a path exists (of any type). Shared with the candidate command's\n * repo-root walk so the two `.git`/file probes stay one implementation. */\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * True only on a git check-ignore exit 0 (the path is ignored). Exit 1 (tracked)\n * and any error (git absent, not a repo) resolve false: `full-auto` is honored\n * from a project file ONLY when git positively confirms it is ignored. Uses\n * execFile with an argv array (never a shell), matching wallet/passphrase.ts.\n */\nfunction defaultIsGitignored(filePath: string): Promise<boolean> {\n return new Promise((resolve) => {\n execFile(\n 'git',\n ['check-ignore', '--quiet', '--', filePath],\n { cwd: dirname(filePath) },\n (err) => resolve(err === null),\n );\n });\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,217 @@
1
+ import { createRequire as __tenjinCreateRequire } from 'node:module'; const require = __tenjinCreateRequire(import.meta.url);
2
+ import {
3
+ createPublicClient,
4
+ defineBlock,
5
+ defineChain,
6
+ defineTransaction,
7
+ defineTransactionReceipt,
8
+ formatTransaction,
9
+ http
10
+ } from "./chunk-UGX7YPX2.js";
11
+ import {
12
+ serializeTransaction,
13
+ toRlp
14
+ } from "./chunk-NCE5NSN6.js";
15
+ import {
16
+ erc20Abi
17
+ } from "./chunk-ZMHYXMO6.js";
18
+ import {
19
+ InvalidAddressError,
20
+ concatHex,
21
+ hexToBigInt,
22
+ hexToNumber,
23
+ isAddress,
24
+ toHex
25
+ } from "./chunk-YALGASEU.js";
26
+
27
+ // node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/_esm/op-stack/contracts.js
28
+ var contracts = {
29
+ gasPriceOracle: { address: "0x420000000000000000000000000000000000000F" },
30
+ l1Block: { address: "0x4200000000000000000000000000000000000015" },
31
+ l2CrossDomainMessenger: {
32
+ address: "0x4200000000000000000000000000000000000007"
33
+ },
34
+ l2Erc721Bridge: { address: "0x4200000000000000000000000000000000000014" },
35
+ l2StandardBridge: { address: "0x4200000000000000000000000000000000000010" },
36
+ l2ToL1MessagePasser: {
37
+ address: "0x4200000000000000000000000000000000000016"
38
+ }
39
+ };
40
+
41
+ // node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/_esm/op-stack/formatters.js
42
+ var formatters = {
43
+ block: /* @__PURE__ */ defineBlock({
44
+ format(args) {
45
+ const transactions = args.transactions?.map((transaction) => {
46
+ if (typeof transaction === "string")
47
+ return transaction;
48
+ const formatted = formatTransaction(transaction);
49
+ if (formatted.typeHex === "0x7e") {
50
+ formatted.isSystemTx = transaction.isSystemTx;
51
+ formatted.mint = transaction.mint ? hexToBigInt(transaction.mint) : void 0;
52
+ formatted.sourceHash = transaction.sourceHash;
53
+ formatted.type = "deposit";
54
+ }
55
+ return formatted;
56
+ });
57
+ return {
58
+ transactions,
59
+ stateRoot: args.stateRoot
60
+ };
61
+ }
62
+ }),
63
+ transaction: /* @__PURE__ */ defineTransaction({
64
+ format(args) {
65
+ const transaction = {};
66
+ if (args.type === "0x7e") {
67
+ transaction.isSystemTx = args.isSystemTx;
68
+ transaction.mint = args.mint ? hexToBigInt(args.mint) : void 0;
69
+ transaction.sourceHash = args.sourceHash;
70
+ transaction.type = "deposit";
71
+ }
72
+ return transaction;
73
+ }
74
+ }),
75
+ transactionReceipt: /* @__PURE__ */ defineTransactionReceipt({
76
+ format(args) {
77
+ return {
78
+ ...args.depositNonce ? { depositNonce: hexToBigInt(args.depositNonce) } : {},
79
+ ...args.depositReceiptVersion ? { depositReceiptVersion: hexToNumber(args.depositReceiptVersion) } : {},
80
+ l1GasPrice: args.l1GasPrice ? hexToBigInt(args.l1GasPrice) : null,
81
+ l1GasUsed: args.l1GasUsed ? hexToBigInt(args.l1GasUsed) : null,
82
+ l1Fee: args.l1Fee ? hexToBigInt(args.l1Fee) : null,
83
+ l1FeeScalar: args.l1FeeScalar ? Number(args.l1FeeScalar) : null
84
+ };
85
+ }
86
+ })
87
+ };
88
+
89
+ // node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/_esm/op-stack/serializers.js
90
+ function serializeTransaction2(transaction, signature) {
91
+ if (isDeposit(transaction))
92
+ return serializeTransactionDeposit(transaction);
93
+ return serializeTransaction(transaction, signature);
94
+ }
95
+ var serializers = {
96
+ transaction: serializeTransaction2
97
+ };
98
+ function serializeTransactionDeposit(transaction) {
99
+ assertTransactionDeposit(transaction);
100
+ const { sourceHash, data, from, gas, isSystemTx, mint, to, value } = transaction;
101
+ const serializedTransaction = [
102
+ sourceHash,
103
+ from,
104
+ to ?? "0x",
105
+ mint ? toHex(mint) : "0x",
106
+ value ? toHex(value) : "0x",
107
+ gas ? toHex(gas) : "0x",
108
+ isSystemTx ? "0x1" : "0x",
109
+ data ?? "0x"
110
+ ];
111
+ return concatHex([
112
+ "0x7e",
113
+ toRlp(serializedTransaction)
114
+ ]);
115
+ }
116
+ function isDeposit(transaction) {
117
+ if (transaction.type === "deposit")
118
+ return true;
119
+ if (typeof transaction.sourceHash !== "undefined")
120
+ return true;
121
+ return false;
122
+ }
123
+ function assertTransactionDeposit(transaction) {
124
+ const { from, to } = transaction;
125
+ if (from && !isAddress(from))
126
+ throw new InvalidAddressError({ address: from });
127
+ if (to && !isAddress(to))
128
+ throw new InvalidAddressError({ address: to });
129
+ }
130
+
131
+ // node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/_esm/op-stack/chainConfig.js
132
+ var chainConfig = {
133
+ blockTime: 2e3,
134
+ contracts,
135
+ formatters,
136
+ serializers
137
+ };
138
+
139
+ // node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/_esm/chains/definitions/base.js
140
+ var sourceId = 1;
141
+ var base = /* @__PURE__ */ defineChain({
142
+ ...chainConfig,
143
+ id: 8453,
144
+ name: "Base",
145
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
146
+ rpcUrls: {
147
+ default: {
148
+ http: ["https://mainnet.base.org"]
149
+ }
150
+ },
151
+ blockExplorers: {
152
+ default: {
153
+ name: "Basescan",
154
+ url: "https://basescan.org",
155
+ apiUrl: "https://api.basescan.org/api"
156
+ }
157
+ },
158
+ contracts: {
159
+ ...chainConfig.contracts,
160
+ disputeGameFactory: {
161
+ [sourceId]: {
162
+ address: "0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e"
163
+ }
164
+ },
165
+ l2OutputOracle: {
166
+ [sourceId]: {
167
+ address: "0x56315b90c40730925ec5485cf004d835058518A0"
168
+ }
169
+ },
170
+ multicall3: {
171
+ address: "0xca11bde05977b3631167028862be2a173976ca11",
172
+ blockCreated: 5022
173
+ },
174
+ portal: {
175
+ [sourceId]: {
176
+ address: "0x49048044D57e1C92A77f79988d21Fa8fAF74E97e",
177
+ blockCreated: 17482143
178
+ }
179
+ },
180
+ l1StandardBridge: {
181
+ [sourceId]: {
182
+ address: "0x3154Cf16ccdb4C6d922629664174b904d80F2C35",
183
+ blockCreated: 17482143
184
+ }
185
+ }
186
+ },
187
+ sourceId
188
+ });
189
+ var basePreconf = /* @__PURE__ */ defineChain({
190
+ ...base,
191
+ experimental_preconfirmationTime: 200,
192
+ rpcUrls: {
193
+ default: {
194
+ http: ["https://mainnet-preconf.base.org"]
195
+ }
196
+ }
197
+ });
198
+
199
+ // src/lib/usdc.ts
200
+ var USDC_ADDRESS = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
201
+ var USDC_DECIMALS = 6;
202
+ async function getUsdcBalance(address, rpcUrl) {
203
+ const client = createPublicClient({ chain: base, transport: http(rpcUrl) });
204
+ return client.readContract({
205
+ address: USDC_ADDRESS,
206
+ abi: erc20Abi,
207
+ functionName: "balanceOf",
208
+ args: [address]
209
+ });
210
+ }
211
+
212
+ export {
213
+ USDC_ADDRESS,
214
+ USDC_DECIMALS,
215
+ getUsdcBalance
216
+ };
217
+ //# sourceMappingURL=chunk-XJIW7USF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/op-stack/contracts.ts","../node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/op-stack/formatters.ts","../node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/op-stack/serializers.ts","../node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/op-stack/chainConfig.ts","../node_modules/.pnpm/viem@2.55.2_typescript@6.0.3_zod@4.4.3/node_modules/viem/chains/definitions/base.ts","../src/lib/usdc.ts"],"sourcesContent":["import type { Chain } from '../types/chain.js'\n\n/**\n * Predeploy contracts for OP Stack.\n * @see https://github.com/ethereum-optimism/optimism/blob/develop/specs/predeploys.md\n */\nexport const contracts = {\n gasPriceOracle: { address: '0x420000000000000000000000000000000000000F' },\n l1Block: { address: '0x4200000000000000000000000000000000000015' },\n l2CrossDomainMessenger: {\n address: '0x4200000000000000000000000000000000000007',\n },\n l2Erc721Bridge: { address: '0x4200000000000000000000000000000000000014' },\n l2StandardBridge: { address: '0x4200000000000000000000000000000000000010' },\n l2ToL1MessagePasser: {\n address: '0x4200000000000000000000000000000000000016',\n },\n} as const satisfies Chain['contracts']\n","import type { ChainFormatters } from '../types/chain.js'\nimport type { RpcTransaction } from '../types/rpc.js'\nimport { hexToBigInt, hexToNumber } from '../utils/encoding/fromHex.js'\nimport { defineBlock } from '../utils/formatters/block.js'\nimport {\n defineTransaction,\n formatTransaction,\n} from '../utils/formatters/transaction.js'\nimport { defineTransactionReceipt } from '../utils/formatters/transactionReceipt.js'\nimport type { OpStackBlock, OpStackRpcBlock } from './types/block.js'\nimport type {\n OpStackRpcTransaction,\n OpStackRpcTransactionReceipt,\n OpStackTransaction,\n OpStackTransactionReceipt,\n} from './types/transaction.js'\n\nexport const formatters = {\n block: /*#__PURE__*/ defineBlock({\n format(args: OpStackRpcBlock): OpStackBlock {\n const transactions = args.transactions?.map((transaction) => {\n if (typeof transaction === 'string') return transaction\n const formatted = formatTransaction(\n transaction as RpcTransaction,\n ) as OpStackTransaction\n if (formatted.typeHex === '0x7e') {\n formatted.isSystemTx = transaction.isSystemTx\n formatted.mint = transaction.mint\n ? hexToBigInt(transaction.mint)\n : undefined\n formatted.sourceHash = transaction.sourceHash\n formatted.type = 'deposit'\n }\n return formatted\n })\n return {\n transactions,\n stateRoot: args.stateRoot,\n } as OpStackBlock\n },\n }),\n transaction: /*#__PURE__*/ defineTransaction({\n format(args: OpStackRpcTransaction): OpStackTransaction {\n const transaction = {} as OpStackTransaction\n if (args.type === '0x7e') {\n transaction.isSystemTx = args.isSystemTx\n transaction.mint = args.mint ? hexToBigInt(args.mint) : undefined\n transaction.sourceHash = args.sourceHash\n transaction.type = 'deposit'\n }\n return transaction\n },\n }),\n transactionReceipt: /*#__PURE__*/ defineTransactionReceipt({\n format(args: OpStackRpcTransactionReceipt): OpStackTransactionReceipt {\n return {\n ...(args.depositNonce\n ? { depositNonce: hexToBigInt(args.depositNonce) }\n : {}),\n ...(args.depositReceiptVersion\n ? { depositReceiptVersion: hexToNumber(args.depositReceiptVersion) }\n : {}),\n l1GasPrice: args.l1GasPrice ? hexToBigInt(args.l1GasPrice) : null,\n l1GasUsed: args.l1GasUsed ? hexToBigInt(args.l1GasUsed) : null,\n l1Fee: args.l1Fee ? hexToBigInt(args.l1Fee) : null,\n l1FeeScalar: args.l1FeeScalar ? Number(args.l1FeeScalar) : null,\n } as OpStackTransactionReceipt\n },\n }),\n} as const satisfies ChainFormatters\n","import { InvalidAddressError } from '../errors/address.js'\nimport type { ErrorType } from '../errors/utils.js'\nimport type { ChainSerializers } from '../types/chain.js'\nimport type { Hex, Signature } from '../types/misc.js'\nimport type { TransactionSerializable } from '../types/transaction.js'\nimport type { RequiredBy } from '../types/utils.js'\nimport { isAddress } from '../utils/address/isAddress.js'\nimport { concatHex } from '../utils/data/concat.js'\nimport { toHex } from '../utils/encoding/toHex.js'\nimport { toRlp } from '../utils/encoding/toRlp.js'\nimport {\n type SerializeTransactionErrorType as SerializeTransactionErrorType_,\n serializeTransaction as serializeTransaction_,\n} from '../utils/transaction/serializeTransaction.js'\nimport type {\n OpStackTransactionSerializable,\n TransactionSerializableDeposit,\n TransactionSerializedDeposit,\n} from './types/transaction.js'\n\nexport type SerializeTransactionReturnType = ReturnType<\n typeof serializeTransaction\n>\n\nexport type SerializeTransactionErrorType =\n | SerializeTransactionErrorType_\n | ErrorType\n\nexport function serializeTransaction(\n transaction: OpStackTransactionSerializable,\n signature?: Signature,\n) {\n if (isDeposit(transaction)) return serializeTransactionDeposit(transaction)\n return serializeTransaction_(\n transaction as TransactionSerializable,\n signature,\n )\n}\n\nexport const serializers = {\n transaction: serializeTransaction,\n} as const satisfies ChainSerializers\n\n//////////////////////////////////////////////////////////////////////////////\n// Serializers\n\nexport type SerializeTransactionDepositReturnType = TransactionSerializedDeposit\n\nfunction serializeTransactionDeposit(\n transaction: TransactionSerializableDeposit,\n): SerializeTransactionDepositReturnType {\n assertTransactionDeposit(transaction)\n\n const { sourceHash, data, from, gas, isSystemTx, mint, to, value } =\n transaction\n\n const serializedTransaction: Hex[] = [\n sourceHash,\n from,\n to ?? '0x',\n mint ? toHex(mint) : '0x',\n value ? toHex(value) : '0x',\n gas ? toHex(gas) : '0x',\n isSystemTx ? '0x1' : '0x',\n data ?? '0x',\n ]\n\n return concatHex([\n '0x7e',\n toRlp(serializedTransaction),\n ]) as SerializeTransactionDepositReturnType\n}\n\nfunction isDeposit(\n transaction: OpStackTransactionSerializable,\n): transaction is RequiredBy<TransactionSerializableDeposit, 'type'> {\n if (transaction.type === 'deposit') return true\n if (typeof transaction.sourceHash !== 'undefined') return true\n return false\n}\n\nexport function assertTransactionDeposit(\n transaction: TransactionSerializableDeposit,\n) {\n const { from, to } = transaction\n if (from && !isAddress(from)) throw new InvalidAddressError({ address: from })\n if (to && !isAddress(to)) throw new InvalidAddressError({ address: to })\n}\n","import { contracts } from './contracts.js'\nimport { formatters } from './formatters.js'\nimport { serializers } from './serializers.js'\n\nexport const chainConfig = {\n blockTime: 2_000,\n contracts,\n formatters,\n serializers,\n} as const\n","import { chainConfig } from '../../op-stack/chainConfig.js'\nimport { defineChain } from '../../utils/chain/defineChain.js'\n\nconst sourceId = 1 // mainnet\n\nexport const base = /*#__PURE__*/ defineChain({\n ...chainConfig,\n id: 8453,\n name: 'Base',\n nativeCurrency: { name: 'Ether', symbol: 'ETH', decimals: 18 },\n rpcUrls: {\n default: {\n http: ['https://mainnet.base.org'],\n },\n },\n blockExplorers: {\n default: {\n name: 'Basescan',\n url: 'https://basescan.org',\n apiUrl: 'https://api.basescan.org/api',\n },\n },\n contracts: {\n ...chainConfig.contracts,\n disputeGameFactory: {\n [sourceId]: {\n address: '0x43edB88C4B80fDD2AdFF2412A7BebF9dF42cB40e',\n },\n },\n l2OutputOracle: {\n [sourceId]: {\n address: '0x56315b90c40730925ec5485cf004d835058518A0',\n },\n },\n multicall3: {\n address: '0xca11bde05977b3631167028862be2a173976ca11',\n blockCreated: 5022,\n },\n portal: {\n [sourceId]: {\n address: '0x49048044D57e1C92A77f79988d21Fa8fAF74E97e',\n blockCreated: 17482143,\n },\n },\n l1StandardBridge: {\n [sourceId]: {\n address: '0x3154Cf16ccdb4C6d922629664174b904d80F2C35',\n blockCreated: 17482143,\n },\n },\n },\n sourceId,\n})\n\nexport const basePreconf = /*#__PURE__*/ defineChain({\n ...base,\n experimental_preconfirmationTime: 200,\n rpcUrls: {\n default: {\n http: ['https://mainnet-preconf.base.org'],\n },\n },\n})\n","import { createPublicClient, erc20Abi, http, type Address } from 'viem';\nimport { base } from 'viem/chains';\n\n// Values mirror the app's lib/chain.ts Base mainnet entry (chain 8453).\nexport const USDC_ADDRESS: Address = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';\nexport const USDC_DECIMALS = 6;\n\nexport async function getUsdcBalance(address: Address, rpcUrl: string): Promise<bigint> {\n const client = createPublicClient({ chain: base, transport: http(rpcUrl) });\n return client.readContract({\n address: USDC_ADDRESS,\n abi: erc20Abi,\n functionName: 'balanceOf',\n args: [address],\n });\n}\n"],"mappings":"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","names":["serializeTransaction"]}