@daski/pay 0.3.0 → 0.4.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 (102) hide show
  1. package/README.md +18 -11
  2. package/dist/bin/daski.js +26 -11
  3. package/dist/bin/daski.js.map +1 -1
  4. package/dist/chain/reader.d.ts +92 -0
  5. package/dist/chain/reader.d.ts.map +1 -0
  6. package/dist/chain/reader.js +130 -0
  7. package/dist/chain/reader.js.map +1 -0
  8. package/dist/commands/approval.js +2 -2
  9. package/dist/commands/approval.js.map +1 -1
  10. package/dist/commands/buy.d.ts +0 -1
  11. package/dist/commands/buy.d.ts.map +1 -1
  12. package/dist/commands/buy.js +15 -22
  13. package/dist/commands/buy.js.map +1 -1
  14. package/dist/commands/confirmation.d.ts +322 -4
  15. package/dist/commands/confirmation.d.ts.map +1 -1
  16. package/dist/commands/confirmation.js +771 -60
  17. package/dist/commands/confirmation.js.map +1 -1
  18. package/dist/commands/doctor.d.ts +20 -0
  19. package/dist/commands/doctor.d.ts.map +1 -1
  20. package/dist/commands/doctor.js +204 -59
  21. package/dist/commands/doctor.js.map +1 -1
  22. package/dist/commands/order.d.ts +37 -6
  23. package/dist/commands/order.d.ts.map +1 -1
  24. package/dist/commands/order.js +181 -103
  25. package/dist/commands/order.js.map +1 -1
  26. package/dist/commands/signPayment.d.ts +2 -2
  27. package/dist/commands/signPayment.d.ts.map +1 -1
  28. package/dist/commands/signPayment.js +10 -5
  29. package/dist/commands/signPayment.js.map +1 -1
  30. package/dist/commands/wallet.d.ts +3 -0
  31. package/dist/commands/wallet.d.ts.map +1 -1
  32. package/dist/commands/wallet.js +72 -16
  33. package/dist/commands/wallet.js.map +1 -1
  34. package/dist/config.d.ts +10 -2
  35. package/dist/config.d.ts.map +1 -1
  36. package/dist/config.js +41 -1
  37. package/dist/config.js.map +1 -1
  38. package/dist/context.d.ts +28 -3
  39. package/dist/context.d.ts.map +1 -1
  40. package/dist/context.js +72 -3
  41. package/dist/context.js.map +1 -1
  42. package/dist/gateway/client.d.ts +20 -17
  43. package/dist/gateway/client.d.ts.map +1 -1
  44. package/dist/gateway/client.js +62 -43
  45. package/dist/gateway/client.js.map +1 -1
  46. package/dist/gateway/lifecycle.d.ts +4 -1
  47. package/dist/gateway/lifecycle.d.ts.map +1 -1
  48. package/dist/gateway/lifecycle.js +10 -5
  49. package/dist/gateway/lifecycle.js.map +1 -1
  50. package/dist/gateway/metadata.d.ts +66 -0
  51. package/dist/gateway/metadata.d.ts.map +1 -0
  52. package/dist/gateway/metadata.js +152 -0
  53. package/dist/gateway/metadata.js.map +1 -0
  54. package/dist/gateway/purchase.d.ts +51 -67
  55. package/dist/gateway/purchase.d.ts.map +1 -1
  56. package/dist/gateway/purchase.js +153 -125
  57. package/dist/gateway/purchase.js.map +1 -1
  58. package/dist/host.d.ts +41 -0
  59. package/dist/host.d.ts.map +1 -0
  60. package/dist/host.js +112 -0
  61. package/dist/host.js.map +1 -0
  62. package/dist/index.d.ts +12 -6
  63. package/dist/index.d.ts.map +1 -1
  64. package/dist/index.js +10 -4
  65. package/dist/index.js.map +1 -1
  66. package/dist/signers/circleAgent.d.ts +37 -0
  67. package/dist/signers/circleAgent.d.ts.map +1 -0
  68. package/dist/signers/circleAgent.js +244 -0
  69. package/dist/signers/circleAgent.js.map +1 -0
  70. package/dist/signers/contract.d.ts +34 -0
  71. package/dist/signers/contract.d.ts.map +1 -0
  72. package/dist/signers/contract.js +47 -0
  73. package/dist/signers/contract.js.map +1 -0
  74. package/dist/signers/index.d.ts +16 -7
  75. package/dist/signers/index.d.ts.map +1 -1
  76. package/dist/signers/index.js +7 -3
  77. package/dist/signers/index.js.map +1 -1
  78. package/dist/signers/local.d.ts +5 -1
  79. package/dist/signers/local.d.ts.map +1 -1
  80. package/dist/signers/local.js +16 -3
  81. package/dist/signers/local.js.map +1 -1
  82. package/dist/signers/selfTest.d.ts +32 -12
  83. package/dist/signers/selfTest.d.ts.map +1 -1
  84. package/dist/signers/selfTest.js +85 -12
  85. package/dist/signers/selfTest.js.map +1 -1
  86. package/dist/signers/signature.d.ts +10 -0
  87. package/dist/signers/signature.d.ts.map +1 -0
  88. package/dist/signers/signature.js +11 -0
  89. package/dist/signers/signature.js.map +1 -0
  90. package/dist/store/keystore.d.ts +48 -6
  91. package/dist/store/keystore.d.ts.map +1 -1
  92. package/dist/store/keystore.js +414 -110
  93. package/dist/store/keystore.js.map +1 -1
  94. package/dist/store/lock.d.ts +59 -0
  95. package/dist/store/lock.d.ts.map +1 -0
  96. package/dist/store/lock.js +269 -0
  97. package/dist/store/lock.js.map +1 -0
  98. package/dist/store/orders.d.ts +49 -9
  99. package/dist/store/orders.d.ts.map +1 -1
  100. package/dist/store/orders.js +173 -37
  101. package/dist/store/orders.js.map +1 -1
  102. package/package.json +2 -2
@@ -1,26 +1,57 @@
1
1
  /**
2
2
  * §5 — key storage.
3
3
  *
4
- * Order of preference: the OS keychain, then an scrypt+AES-GCM file guarded by
5
- * a passphrase, then — for sandbox development only — an environment variable.
6
- * Sandbox and mainnet never share a keychain entry or a file slot, so a
7
- * profile mix-up cannot reach a mainnet key.
4
+ * A local key is written only to a store whose persistence is known by
5
+ * construction: the macOS keychain or Windows Credential Manager (backend
6
+ * `keychain`), or the scrypt+AES-GCM file guarded by a passphrase (backend
7
+ * `file`). On Linux the keyring wrapper is never loaded: without a Secret
8
+ * Service it silently fell back to the kernel session keyring and a key was
9
+ * lost with the session, so `keychain` is refused there and the file backend
10
+ * is named instead. For sandbox development only, `DASKI_PAYER_PRIVATE_KEY`
11
+ * supplies a key from the environment.
12
+ *
13
+ * The file store distinguishes a missing file (an empty store) from one it
14
+ * cannot read, parse, or trust (`DASKI_KEYSTORE_UNREADABLE`), and it refuses
15
+ * to create or use a key on the latter. Every update holds an exclusive lock
16
+ * file, writes a temporary file beside the target with owner-only mode,
17
+ * flushes it, atomically renames it over the target, flushes the directory,
18
+ * then reads the file back and decrypts the new entry to the expected address
19
+ * before reporting success.
8
20
  *
9
- * Nothing in this file logs, prints, or returns key material except to the
10
- * single caller that is about to construct a signer.
21
+ * Sandbox and mainnet never share a keychain entry or a file slot, so a
22
+ * profile mix-up cannot reach a mainnet key. Nothing in this file logs,
23
+ * prints, or returns key material except to the single caller that is about
24
+ * to construct a signer.
11
25
  */
12
- import { createCipheriv, createDecipheriv, randomBytes, scrypt as scryptCallback } from "node:crypto";
13
- import { chmodSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
- import { dirname } from "node:path";
26
+ import { createCipheriv, createDecipheriv, randomBytes, scrypt as scryptCallback, } from "node:crypto";
27
+ import { closeSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, rmSync, statSync, writeSync, } from "node:fs";
28
+ import { tmpdir } from "node:os";
29
+ import { dirname, join } from "node:path";
15
30
  import { promisify } from "node:util";
31
+ import { privateKeyToAccount } from "viem/accounts";
32
+ import { getAddress } from "viem";
16
33
  import { CliError } from "../cli/errors.js";
17
- import { readPassphrase } from "../cli/prompt.js";
34
+ import { isInteractive, readPassphrase } from "../cli/prompt.js";
35
+ import { HOSTED_BACKENDS, } from "../host.js";
18
36
  import { keystorePath } from "../paths.js";
37
+ import { withFileLock } from "./lock.js";
19
38
  const scrypt = promisify(scryptCallback);
20
39
  const SERVICE = "io.daski.pay";
21
40
  const DOC = "https://github.com/daski-io/buyer/blob/main/docs/keys.md";
22
41
  /** Interactive-grade scrypt parameters. */
23
42
  const SCRYPT = { N: 1 << 17, r: 8, p: 1 };
43
+ /**
44
+ * The largest parameters an entry may ask for on decryption: twice the
45
+ * interactive cost. scrypt needs 128·N·r bytes, and Node's default 32 MiB
46
+ * ceiling is below even the interactive cost, so the ceiling is derived from
47
+ * the parameters instead of trusted to a default; a file that asks for more
48
+ * is malformed, not a reason to allocate gigabytes.
49
+ */
50
+ const SCRYPT_MAX = { N: 1 << 18, r: 8, p: 2 };
51
+ const scryptMemory = (N, r) => 2 * 128 * N * r;
52
+ const MIN_PASSPHRASE_LENGTH = 8;
53
+ /** How long a store update waits for another live process's lock before giving up. */
54
+ const LOCK_WAIT_MS = 30_000;
24
55
  /** Keychain and file entries are namespaced by profile, never shared. */
25
56
  function accountFor(profile) {
26
57
  return `payer:${profile}`;
@@ -35,8 +66,8 @@ function environmentKey(profile) {
35
66
  code: "DASKI_ENV_KEY_REFUSED_OFF_SANDBOX",
36
67
  message: `DASKI_PAYER_PRIVATE_KEY is set, but the active profile is "${profile}". ` +
37
68
  "The environment-variable signer is sandbox-only.",
38
- remediation: `Unset DASKI_PAYER_PRIVATE_KEY, and store the ${profile} key in the OS ` +
39
- `keychain instead: run \`daski wallet create --profile ${profile}\`. See ${DOC}`,
69
+ remediation: `Unset DASKI_PAYER_PRIVATE_KEY, and store the ${profile} key in a durable ` +
70
+ `backend instead: run \`daski wallet create --profile ${profile}\`. See ${DOC}`,
40
71
  });
41
72
  }
42
73
  if (!/^0x[0-9a-fA-F]{64}$/.test(raw)) {
@@ -48,43 +79,170 @@ function environmentKey(profile) {
48
79
  }
49
80
  return raw;
50
81
  }
82
+ const ENVIRONMENT_LOCATION = {
83
+ source: "environment",
84
+ description: "DASKI_PAYER_PRIVATE_KEY (developer/sandbox only)",
85
+ durability: "environment",
86
+ };
87
+ function keychainLocation(profile) {
88
+ return {
89
+ source: "keychain",
90
+ description: `OS keychain (${SERVICE}/${accountFor(profile)})`,
91
+ durability: "persistent",
92
+ };
93
+ }
94
+ function fileLocation() {
95
+ return {
96
+ source: "encrypted-file",
97
+ description: `${keystorePath()} (scrypt + AES-256-GCM)`,
98
+ durability: "encrypted-file",
99
+ };
100
+ }
101
+ export function keychainUnsupportedOnLinux(profile) {
102
+ return new CliError({
103
+ code: "DASKI_KEYCHAIN_UNSUPPORTED_ON_LINUX",
104
+ message: "The OS keychain backend is not used on Linux: without a Secret Service the keyring " +
105
+ "wrapper falls back to the kernel session keyring, which does not survive the session.",
106
+ remediation: `Use the encrypted file backend: DASKI_KEY_BACKEND=file daski wallet create --profile ${profile}. ` +
107
+ `Without a terminal, also set DASKI_KEYSTORE_PASSPHRASE_FILE. See ${DOC}`,
108
+ });
109
+ }
51
110
  /**
52
- * Loads `@napi-rs/keyring` if the platform has it. It is an optional
53
- * dependency with prebuilt binaries and no install scripts, so its absence is
54
- * normal rather than exceptional — we fall through to the file keystore.
111
+ * Loads `@napi-rs/keyring` on the platforms whose native stores are persistent
112
+ * by construction. On Linux this function never reaches the import.
55
113
  */
56
- async function keyring(profile) {
57
- if (process.env.DASKI_DISABLE_KEYCHAIN === "1")
58
- return undefined;
114
+ async function keyring(profile, host) {
115
+ if (host.platform === "linux")
116
+ throw keychainUnsupportedOnLinux(profile);
117
+ let Entry;
59
118
  try {
60
119
  const module = await import("@napi-rs/keyring");
61
- const Entry = module.Entry;
62
- return new Entry(SERVICE, accountFor(profile));
120
+ Entry = module.Entry;
63
121
  }
64
122
  catch {
65
- return undefined;
123
+ throw new CliError({
124
+ code: "DASKI_KEYCHAIN_UNAVAILABLE",
125
+ message: "The OS keychain backend could not be loaded on this machine.",
126
+ remediation: `Reinstall @daski/pay so its optional @napi-rs/keyring binary is present, or use ` +
127
+ `the encrypted file backend with DASKI_KEY_BACKEND=file. See ${DOC}`,
128
+ });
66
129
  }
130
+ return new Entry(SERVICE, accountFor(profile));
131
+ }
132
+ // -- file backend ----------------------------------------------------------------
133
+ function keystoreUnreadable(path, reason) {
134
+ return new CliError({
135
+ code: "DASKI_KEYSTORE_UNREADABLE",
136
+ message: `The keystore ${path} exists but cannot be used: ${reason}.`,
137
+ remediation: "An unreadable or malformed keystore is never treated as empty, because creating a " +
138
+ "key over it could hide the one already there. Restore the file from a backup or fix " +
139
+ `its permissions, then re-run. See ${DOC}`,
140
+ });
67
141
  }
68
- function readKeystoreFile() {
142
+ function isEncryptedEntry(value) {
143
+ if (!value || typeof value !== "object" || Array.isArray(value))
144
+ return false;
145
+ const entry = value;
146
+ const { N, r, p } = entry;
147
+ return entry.kdf === "scrypt" &&
148
+ typeof N === "number" && Number.isSafeInteger(N) && N >= 1 << 14 && N <= SCRYPT_MAX.N && (N & (N - 1)) === 0 &&
149
+ typeof r === "number" && Number.isSafeInteger(r) && r >= 1 && r <= SCRYPT_MAX.r &&
150
+ typeof p === "number" && Number.isSafeInteger(p) && p >= 1 && p <= SCRYPT_MAX.p &&
151
+ [entry.salt, entry.iv, entry.tag, entry.ciphertext].every((s) => typeof s === "string" && s.length > 0);
152
+ }
153
+ /**
154
+ * Reads the store. A missing file is an empty store; anything else that stops
155
+ * the file being read, parsed, or trusted is `DASKI_KEYSTORE_UNREADABLE`.
156
+ */
157
+ function readKeystoreFile(path = keystorePath()) {
158
+ let raw;
69
159
  try {
70
- const parsed = JSON.parse(readFileSync(keystorePath(), "utf8"));
71
- if (parsed.version !== 1 || typeof parsed.entries !== "object")
72
- throw new Error("shape");
73
- return parsed;
160
+ raw = readFileSync(path, "utf8");
74
161
  }
75
- catch {
76
- return { version: 1, entries: {} };
162
+ catch (error) {
163
+ if (error.code === "ENOENT")
164
+ return { version: 1, entries: {} };
165
+ throw keystoreUnreadable(path, error.message);
166
+ }
167
+ let parsed;
168
+ try {
169
+ parsed = JSON.parse(raw);
170
+ }
171
+ catch (error) {
172
+ throw keystoreUnreadable(path, `not valid JSON (${error.message})`);
173
+ }
174
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
175
+ throw keystoreUnreadable(path, "the document is not an object");
176
+ }
177
+ const file = parsed;
178
+ if (file.version !== 1 || !file.entries || typeof file.entries !== "object" || Array.isArray(file.entries)) {
179
+ throw keystoreUnreadable(path, "unexpected document shape");
180
+ }
181
+ for (const [account, entry] of Object.entries(file.entries)) {
182
+ if (!isEncryptedEntry(entry))
183
+ throw keystoreUnreadable(path, `entry "${account}" is malformed`);
77
184
  }
185
+ return file;
78
186
  }
79
- function writeKeystoreFile(file) {
80
- const path = keystorePath();
81
- mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
82
- writeFileSync(path, `${JSON.stringify(file, null, 2)}\n`, { mode: 0o600 });
83
- chmodSync(path, 0o600);
187
+ function fsyncDirectory(directory) {
188
+ // Windows cannot open a directory handle for fsync; the rename is still atomic there.
189
+ if (process.platform === "win32")
190
+ return;
191
+ const fd = openSync(directory, "r");
192
+ try {
193
+ fsyncSync(fd);
194
+ }
195
+ finally {
196
+ closeSync(fd);
197
+ }
198
+ }
199
+ /**
200
+ * Replaces the store atomically: an owner-only temporary file beside the
201
+ * target, flushed, renamed over the target, then the directory flushed. A
202
+ * crash at any point leaves either the previous file or the new one, never a
203
+ * truncated mixture.
204
+ */
205
+ function replaceKeystoreFile(path, file) {
206
+ const directory = dirname(path);
207
+ mkdirSync(directory, { recursive: true, mode: 0o700 });
208
+ const temporary = `${path}.${process.pid}.${randomBytes(4).toString("hex")}.tmp`;
209
+ const fd = openSync(temporary, "wx", 0o600);
210
+ try {
211
+ writeSync(fd, `${JSON.stringify(file, null, 2)}\n`);
212
+ fsyncSync(fd);
213
+ }
214
+ finally {
215
+ closeSync(fd);
216
+ }
217
+ try {
218
+ renameSync(temporary, path);
219
+ }
220
+ catch (error) {
221
+ rmSync(temporary, { force: true });
222
+ throw error;
223
+ }
224
+ fsyncDirectory(directory);
225
+ }
226
+ /** Serializes store updates across processes with an exclusive lock file. */
227
+ function withKeystoreLock(path, run) {
228
+ const lock = `${path}.lock`;
229
+ return withFileLock(lock, {
230
+ waitMs: LOCK_WAIT_MS,
231
+ locked: (reason) => new CliError({
232
+ code: "DASKI_KEYSTORE_LOCKED",
233
+ message: reason === "orphaned"
234
+ ? `A daski process died while recovering the keystore lock ${lock}.`
235
+ : `Another process holds the keystore lock ${lock}.`,
236
+ remediation: reason === "orphaned"
237
+ ? `If no daski process is running, remove ${lock} and ${lock}.reclaim, then re-run. See ${DOC}`
238
+ : "Wait for the other daski command to finish, then re-run. If no daski process " +
239
+ `is running, remove the stale lock file. See ${DOC}`,
240
+ }),
241
+ }, run);
84
242
  }
85
243
  async function encrypt(privateKey, passphrase) {
86
244
  const salt = randomBytes(32);
87
- const key = await scrypt(passphrase, salt, 32, SCRYPT);
245
+ const key = await scrypt(passphrase, salt, 32, { ...SCRYPT, maxmem: scryptMemory(SCRYPT.N, SCRYPT.r) });
88
246
  const iv = randomBytes(12);
89
247
  const cipher = createCipheriv("aes-256-gcm", key, iv);
90
248
  const ciphertext = Buffer.concat([
@@ -102,7 +260,7 @@ async function encrypt(privateKey, passphrase) {
102
260
  }
103
261
  async function decrypt(entry, passphrase) {
104
262
  const key = await scrypt(passphrase, Buffer.from(entry.salt, "base64"), 32, {
105
- N: entry.N, r: entry.r, p: entry.p,
263
+ N: entry.N, r: entry.r, p: entry.p, maxmem: scryptMemory(entry.N, entry.r),
106
264
  });
107
265
  const decipher = createDecipheriv("aes-256-gcm", key, Buffer.from(entry.iv, "base64"));
108
266
  decipher.setAuthTag(Buffer.from(entry.tag, "base64"));
@@ -123,104 +281,250 @@ async function decrypt(entry, passphrase) {
123
281
  });
124
282
  }
125
283
  }
284
+ // -- passphrase ------------------------------------------------------------------
285
+ function passphraseFileInvalid(path, reason, remediation) {
286
+ return new CliError({
287
+ code: "DASKI_PASSPHRASE_FILE_INVALID",
288
+ message: `DASKI_KEYSTORE_PASSPHRASE_FILE (${path}) cannot be used: ${reason}.`,
289
+ remediation: `${remediation} See ${DOC}`,
290
+ });
291
+ }
292
+ /**
293
+ * Reads the passphrase from the file `DASKI_KEYSTORE_PASSPHRASE_FILE` names.
294
+ * The file must be a regular file with owner-only permissions; a passphrase
295
+ * never travels on a command line.
296
+ */
297
+ export function readPassphraseFile(path, platform) {
298
+ let stat;
299
+ try {
300
+ stat = statSync(path);
301
+ }
302
+ catch (error) {
303
+ throw passphraseFileInvalid(path, error.message, "Point it at a regular file containing only the passphrase.");
304
+ }
305
+ if (!stat.isFile()) {
306
+ throw passphraseFileInvalid(path, "it is not a regular file", "Point it at a regular file containing only the passphrase.");
307
+ }
308
+ // Windows permissions are ACLs that Node cannot express as a mode.
309
+ if (platform !== "win32" && (stat.mode & 0o077) !== 0) {
310
+ throw passphraseFileInvalid(path, "it is readable or writable by other users", `Run: chmod 600 ${path}`);
311
+ }
312
+ let content;
313
+ try {
314
+ content = readFileSync(path, "utf8");
315
+ }
316
+ catch (error) {
317
+ throw passphraseFileInvalid(path, error.message, "Fix the file's permissions.");
318
+ }
319
+ const passphrase = content.replace(/\r?\n$/, "");
320
+ if (passphrase.length === 0) {
321
+ throw passphraseFileInvalid(path, "it is empty", "Write the passphrase into the file.");
322
+ }
323
+ return passphrase;
324
+ }
325
+ function passphraseTooShort() {
326
+ return new CliError({
327
+ code: "DASKI_PASSPHRASE_TOO_SHORT",
328
+ message: `The keystore passphrase must be at least ${MIN_PASSPHRASE_LENGTH} characters.`,
329
+ remediation: "Re-run and choose a longer passphrase.",
330
+ });
331
+ }
332
+ /**
333
+ * The passphrase for the file store: from `DASKI_KEYSTORE_PASSPHRASE_FILE`
334
+ * when set, otherwise from the terminal. With neither, the command refuses.
335
+ */
336
+ export async function keystorePassphrase(host, purpose, profile) {
337
+ if (host.passphraseFile) {
338
+ const passphrase = readPassphraseFile(host.passphraseFile, host.platform);
339
+ if (purpose === "create" && passphrase.length < MIN_PASSPHRASE_LENGTH)
340
+ throw passphraseTooShort();
341
+ return passphrase;
342
+ }
343
+ if (!isInteractive()) {
344
+ throw new CliError({
345
+ code: "DASKI_PASSPHRASE_REQUIRES_TTY",
346
+ message: "The encrypted keystore needs a passphrase, and this session has no terminal.",
347
+ remediation: "Run the command from an interactive terminal, or set DASKI_KEYSTORE_PASSPHRASE_FILE " +
348
+ "to a regular file (mode 600) containing the passphrase. The passphrase is never " +
349
+ `taken from a flag. See ${DOC}`,
350
+ });
351
+ }
352
+ if (purpose === "unlock")
353
+ return readPassphrase(`Passphrase for the ${profile} keystore: `);
354
+ const passphrase = await readPassphrase(`Choose a passphrase for ${keystorePath()}: `);
355
+ if (passphrase.length < MIN_PASSPHRASE_LENGTH)
356
+ throw passphraseTooShort();
357
+ const again = await readPassphrase("Confirm passphrase: ");
358
+ if (again !== passphrase) {
359
+ throw new CliError({
360
+ code: "DASKI_PASSPHRASE_MISMATCH",
361
+ message: "The passphrases did not match.",
362
+ remediation: "Re-run and enter the same passphrase twice.",
363
+ });
364
+ }
365
+ return passphrase;
366
+ }
367
+ // -- the store API -----------------------------------------------------------------
368
+ /** The refusal for a host whose backend holds no local key. */
369
+ export function localKeyRefusedOnHost(profile, backend) {
370
+ const named = backend === "none" ? "no local key store (DASKI_KEY_BACKEND=none)" : `the hosted ${backend} wallet`;
371
+ return new CliError({
372
+ code: "DASKI_LOCAL_KEY_REFUSED_ON_HOST",
373
+ message: `This host selects ${named}, so no local key is created or read for "${profile}".`,
374
+ remediation: backend === "none"
375
+ ? "Set DASKI_KEY_BACKEND=file (or keychain on macOS and Windows) to keep a local key, " +
376
+ `or configure a hosted signer. See ${DOC}`
377
+ : `Set the profile signer to ${backend} and run daski doctor --json --signer ${backend}. ` +
378
+ `To keep a local key instead, set DASKI_KEY_BACKEND=file. See ${DOC}`,
379
+ });
380
+ }
126
381
  /** Where a key for this profile lives, without loading it. */
127
- export async function locateKey(profile) {
128
- if (process.env.DASKI_PAYER_PRIVATE_KEY) {
129
- return {
130
- source: "environment",
131
- description: "DASKI_PAYER_PRIVATE_KEY (developer/sandbox only)",
132
- };
133
- }
134
- const entry = await keyring(profile);
135
- if (entry) {
382
+ export async function locateKey(profile, store) {
383
+ if (process.env.DASKI_PAYER_PRIVATE_KEY)
384
+ return ENVIRONMENT_LOCATION;
385
+ if (HOSTED_BACKENDS.has(store.backend))
386
+ return undefined;
387
+ if (store.backend === "keychain") {
388
+ const entry = await keyring(profile, store.host);
136
389
  try {
137
- if (entry.getPassword()) {
138
- return { source: "keychain", description: `OS keychain (${SERVICE}/${accountFor(profile)})` };
139
- }
390
+ return entry.getPassword() ? keychainLocation(profile) : undefined;
140
391
  }
141
392
  catch {
142
- // An unavailable keychain is not an error here; fall through to the file.
393
+ return undefined;
143
394
  }
144
395
  }
145
- if (readKeystoreFile().entries[accountFor(profile)]) {
146
- return { source: "encrypted-file", description: `${keystorePath()} (scrypt + AES-256-GCM)` };
147
- }
148
- return undefined;
396
+ return readKeystoreFile().entries[accountFor(profile)] ? fileLocation() : undefined;
149
397
  }
150
398
  /** Loads the private key for a profile, prompting for a passphrase if needed. */
151
- export async function loadKey(profile) {
399
+ export async function loadKey(profile, store) {
152
400
  const fromEnvironment = environmentKey(profile);
153
401
  if (fromEnvironment)
154
402
  return fromEnvironment;
155
- const entry = await keyring(profile);
156
- if (entry) {
157
- try {
158
- const stored = entry.getPassword();
159
- if (stored) {
160
- if (!/^0x[0-9a-fA-F]{64}$/.test(stored)) {
161
- throw new CliError({
162
- code: "DASKI_KEYCHAIN_ENTRY_MALFORMED",
163
- message: `The keychain entry for "${profile}" is not a valid private key.`,
164
- remediation: `Delete it and re-run \`daski wallet create --profile ${profile}\`. See ${DOC}`,
165
- });
166
- }
167
- return stored;
168
- }
169
- }
170
- catch (error) {
171
- if (error instanceof CliError)
172
- throw error;
403
+ if (HOSTED_BACKENDS.has(store.backend))
404
+ throw localKeyRefusedOnHost(profile, store.backend);
405
+ if (store.backend === "keychain") {
406
+ const entry = await keyring(profile, store.host);
407
+ const stored = entry.getPassword();
408
+ if (!stored)
409
+ throw noKey(profile);
410
+ if (!/^0x[0-9a-fA-F]{64}$/.test(stored)) {
411
+ throw new CliError({
412
+ code: "DASKI_KEYCHAIN_ENTRY_MALFORMED",
413
+ message: `The keychain entry for "${profile}" is not a valid private key.`,
414
+ remediation: `Delete it and re-run \`daski wallet create --profile ${profile}\`. See ${DOC}`,
415
+ });
173
416
  }
417
+ return stored;
174
418
  }
175
419
  const stored = readKeystoreFile().entries[accountFor(profile)];
176
- if (!stored) {
177
- throw new CliError({
178
- code: "DASKI_NO_KEY_FOR_PROFILE",
179
- message: `No signing key is configured for the "${profile}" profile.`,
180
- remediation: `Run: daski wallet create --profile ${profile}`,
181
- });
182
- }
183
- const passphrase = await readPassphrase(`Passphrase for the ${profile} keystore: `);
420
+ if (!stored)
421
+ throw noKey(profile);
422
+ const passphrase = await keystorePassphrase(store.host, "unlock", profile);
184
423
  return decrypt(stored, passphrase);
185
424
  }
425
+ function noKey(profile) {
426
+ return new CliError({
427
+ code: "DASKI_NO_KEY_FOR_PROFILE",
428
+ message: `No signing key is configured for the "${profile}" profile.`,
429
+ remediation: `Run: daski wallet create --profile ${profile}`,
430
+ });
431
+ }
432
+ /**
433
+ * Serializes a profile's native keychain setup. The entry is per OS user, not
434
+ * per DASKI_HOME, so the lock lives outside DASKI_HOME and names the entry:
435
+ * two setups for the same profile, from any directories, take turns, and the
436
+ * second finds the first's key instead of overwriting it after a check that
437
+ * saw nothing.
438
+ */
439
+ function withKeychainLock(profile, directory, run) {
440
+ const name = `keychain-${SERVICE}-${accountFor(profile)}`.replace(/[^A-Za-z0-9._-]/g, "_");
441
+ const lock = join(directory ?? join(tmpdir(), "daski-locks"), `${name}.lock`);
442
+ return withFileLock(lock, {
443
+ waitMs: LOCK_WAIT_MS,
444
+ locked: (reason) => new CliError({
445
+ code: "DASKI_KEYSTORE_LOCKED",
446
+ message: reason === "orphaned"
447
+ ? `A daski process died while recovering the keychain lock ${lock}.`
448
+ : `Another process is setting up the keychain entry for "${profile}".`,
449
+ remediation: reason === "orphaned"
450
+ ? `If no daski process is running, remove ${lock} and ${lock}.reclaim, then re-run. See ${DOC}`
451
+ : "Wait for the other daski command to finish, then re-run. If no daski process " +
452
+ `is running, remove the stale lock file. See ${DOC}`,
453
+ }),
454
+ }, run);
455
+ }
186
456
  /**
187
457
  * Stores a key for a profile. Returns where it landed so the caller can tell
188
- * the operator — the caller prints the location, never the key.
458
+ * the operator — the caller prints the location, never the key. The store is
459
+ * re-read under the lock, so two creations for the same profile serialize to
460
+ * one key: the second finds the first and refuses.
189
461
  */
190
- export async function storeKey(profile, privateKey) {
191
- const entry = await keyring(profile);
192
- if (entry) {
193
- try {
462
+ export async function storeKey(profile, privateKey, store, hooks = {}) {
463
+ if (HOSTED_BACKENDS.has(store.backend))
464
+ throw localKeyRefusedOnHost(profile, store.backend);
465
+ const expected = privateKeyToAccount(privateKey).address;
466
+ if (store.backend === "keychain") {
467
+ const entry = hooks.keyring ? hooks.keyring(profile) : await keyring(profile, store.host);
468
+ // Check, write and read-back are one critical section: a read-back alone
469
+ // cannot tell that another setup will overwrite the entry afterwards.
470
+ return withKeychainLock(profile, hooks.lockDirectory, async () => {
471
+ if (entry.getPassword())
472
+ throw keyAlreadyExists(profile);
473
+ await hooks.beforeKeychainWrite?.();
194
474
  entry.setPassword(privateKey);
195
- return { source: "keychain", description: `OS keychain (${SERVICE}/${accountFor(profile)})` };
196
- }
197
- catch {
198
- // No usable keychain (headless Linux without libsecret, for example).
199
- }
200
- }
201
- const passphrase = await readPassphrase(`No OS keychain is available. Choose a passphrase for ${keystorePath()}: `);
202
- if (passphrase.length < 8) {
203
- throw new CliError({
204
- code: "DASKI_PASSPHRASE_TOO_SHORT",
205
- message: "The keystore passphrase must be at least 8 characters.",
206
- remediation: "Re-run and choose a longer passphrase.",
207
- });
208
- }
209
- const again = await readPassphrase("Confirm passphrase: ");
210
- if (again !== passphrase) {
211
- throw new CliError({
212
- code: "DASKI_PASSPHRASE_MISMATCH",
213
- message: "The passphrases did not match.",
214
- remediation: "Re-run and enter the same passphrase twice.",
475
+ const readBack = entry.getPassword();
476
+ if (readBack !== privateKey)
477
+ throw readBackMismatch(profile);
478
+ return keychainLocation(profile);
215
479
  });
216
480
  }
217
- const file = readKeystoreFile();
218
- file.entries[accountFor(profile)] = await encrypt(privateKey, passphrase);
219
- writeKeystoreFile(file);
220
- return { source: "encrypted-file", description: `${keystorePath()} (scrypt + AES-256-GCM)` };
481
+ const path = keystorePath();
482
+ // The passphrase is obtained before the lock so a prompt never holds it.
483
+ if (readKeystoreFile(path).entries[accountFor(profile)])
484
+ throw keyAlreadyExists(profile);
485
+ const passphrase = await keystorePassphrase(store.host, "create", profile);
486
+ const encrypted = await encrypt(privateKey, passphrase);
487
+ return withKeystoreLock(path, async () => {
488
+ const file = readKeystoreFile(path);
489
+ if (file.entries[accountFor(profile)])
490
+ throw keyAlreadyExists(profile);
491
+ file.entries[accountFor(profile)] = encrypted;
492
+ replaceKeystoreFile(path, file);
493
+ hooks.afterWrite?.();
494
+ // Success is claimed only after the bytes on disk decrypt to this key.
495
+ const written = readKeystoreFile(path).entries[accountFor(profile)];
496
+ let recovered;
497
+ if (written) {
498
+ try {
499
+ recovered = getAddress(privateKeyToAccount(await decrypt(written, passphrase)).address);
500
+ }
501
+ catch {
502
+ recovered = undefined;
503
+ }
504
+ }
505
+ if (recovered !== expected)
506
+ throw readBackMismatch(profile);
507
+ return fileLocation();
508
+ });
509
+ }
510
+ function keyAlreadyExists(profile) {
511
+ return new CliError({
512
+ code: "DASKI_KEY_ALREADY_EXISTS",
513
+ message: `A signing key already exists for the "${profile}" profile.`,
514
+ remediation: `Use the existing signer with daski wallet address --profile ${profile}.`,
515
+ });
516
+ }
517
+ function readBackMismatch(profile) {
518
+ return new CliError({
519
+ code: "DASKI_KEYSTORE_READBACK_MISMATCH",
520
+ message: `The key written for "${profile}" did not read back as the key that was generated, ` +
521
+ "so the store cannot be trusted to hold it.",
522
+ remediation: "Do not fund this address. Check the disk and the state directory, then re-run " +
523
+ `daski wallet create --profile ${profile}. See ${DOC}`,
524
+ });
221
525
  }
222
526
  /** True when a key already exists for this profile. */
223
- export async function hasKey(profile) {
224
- return (await locateKey(profile)) !== undefined;
527
+ export async function hasKey(profile, store) {
528
+ return (await locateKey(profile, store)) !== undefined;
225
529
  }
226
530
  //# sourceMappingURL=keystore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../../src/store/keystore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"keystore.js","sourceRoot":"","sources":["../../src/store/keystore.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EACL,cAAc,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,IAAI,cAAc,GACxE,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EACrF,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACpD,OAAO,EAAE,UAAU,EAA0B,MAAM,MAAM,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EACL,eAAe,GAChB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,MAAM,MAAM,GAAG,SAAS,CAAC,cAAc,CAGnB,CAAC;AAErB,MAAM,OAAO,GAAG,cAAc,CAAC;AAC/B,MAAM,GAAG,GAAG,0DAA0D,CAAC;AAEvE,2CAA2C;AAC3C,MAAM,MAAM,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAW,CAAC;AACnD;;;;;;GAMG;AACH,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAW,CAAC;AACvD,MAAM,YAAY,GAAG,CAAC,CAAS,EAAE,CAAS,EAAU,EAAE,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;AACvE,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAChC,sFAAsF;AACtF,MAAM,YAAY,GAAG,MAAM,CAAC;AAkC5B,yEAAyE;AACzE,SAAS,UAAU,CAAC,OAAe;IACjC,OAAO,SAAS,OAAO,EAAE,CAAC;AAC5B,CAAC;AAED,kEAAkE;AAClE,SAAS,cAAc,CAAC,OAAe;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC;IAChD,IAAI,CAAC,GAAG;QAAE,OAAO,SAAS,CAAC;IAC3B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,mCAAmC;YACzC,OAAO,EACL,8DAA8D,OAAO,KAAK;gBAC1E,kDAAkD;YACpD,WAAW,EACT,gDAAgD,OAAO,oBAAoB;gBAC3E,wDAAwD,OAAO,WAAW,GAAG,EAAE;SAClF,CAAC,CAAC;IACL,CAAC;IACD,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QACrC,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,yBAAyB;YAC/B,OAAO,EAAE,+DAA+D;YACxE,WAAW,EAAE,qCAAqC,GAAG,EAAE;SACxD,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAU,CAAC;AACpB,CAAC;AAED,MAAM,oBAAoB,GAAgB;IACxC,MAAM,EAAE,aAAa;IACrB,WAAW,EAAE,kDAAkD;IAC/D,UAAU,EAAE,aAAa;CAC1B,CAAC;AAEF,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO;QACL,MAAM,EAAE,UAAU;QAClB,WAAW,EAAE,gBAAgB,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,GAAG;QAC9D,UAAU,EAAE,YAAY;KACzB,CAAC;AACJ,CAAC;AAED,SAAS,YAAY;IACnB,OAAO;QACL,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,GAAG,YAAY,EAAE,yBAAyB;QACvD,UAAU,EAAE,gBAAgB;KAC7B,CAAC;AACJ,CAAC;AAUD,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACxD,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,qCAAqC;QAC3C,OAAO,EACL,qFAAqF;YACrF,uFAAuF;QACzF,WAAW,EACT,wFAAwF,OAAO,IAAI;YACnG,oEAAoE,GAAG,EAAE;KAC5E,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,IAAqB;IAC3D,IAAI,IAAI,CAAC,QAAQ,KAAK,OAAO;QAAE,MAAM,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACzE,IAAI,KAA6D,CAAC;IAClE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAC;QAChD,KAAK,GAAI,MAA4E,CAAC,KAAK,CAAC;IAC9F,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,4BAA4B;YAClC,OAAO,EAAE,8DAA8D;YACvE,WAAW,EACT,kFAAkF;gBAClF,+DAA+D,GAAG,EAAE;SACvE,CAAC,CAAC;IACL,CAAC;IACD,OAAO,IAAI,KAAK,CAAC,OAAO,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,mFAAmF;AAEnF,SAAS,kBAAkB,CAAC,IAAY,EAAE,MAAc;IACtD,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,2BAA2B;QACjC,OAAO,EAAE,gBAAgB,IAAI,+BAA+B,MAAM,GAAG;QACrE,WAAW,EACT,oFAAoF;YACpF,sFAAsF;YACtF,qCAAqC,GAAG,EAAE;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,KAAc;IACtC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9E,MAAM,KAAK,GAAG,KAAgC,CAAC;IAC/C,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;IAC1B,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;QAC3B,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;QAC5G,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;QAC/E,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,CAAC;QAC/E,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC5G,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,IAAI,GAAG,YAAY,EAAE;IAC7C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;QAC3F,MAAM,kBAAkB,CAAC,IAAI,EAAG,KAAe,CAAC,OAAO,CAAC,CAAC;IAC3D,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,kBAAkB,CAAC,IAAI,EAAE,mBAAoB,KAAe,CAAC,OAAO,GAAG,CAAC,CAAC;IACjF,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnE,MAAM,kBAAkB,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,IAAI,GAAG,MAAkD,CAAC;IAChE,IAAI,IAAI,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3G,MAAM,kBAAkB,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IAC9D,CAAC;IACD,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAkC,CAAC,EAAE,CAAC;QACvF,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;YAAE,MAAM,kBAAkB,CAAC,IAAI,EAAE,UAAU,OAAO,gBAAgB,CAAC,CAAC;IAClG,CAAC;IACD,OAAO,IAAoB,CAAC;AAC9B,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB;IACvC,sFAAsF;IACtF,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO;IACzC,MAAM,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,mBAAmB,CAAC,IAAY,EAAE,IAAkB;IAC3D,MAAM,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC;IACjF,MAAM,EAAE,GAAG,QAAQ,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;IAC5C,IAAI,CAAC;QACH,SAAS,CAAC,EAAE,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;QACpD,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;YAAS,CAAC;QACT,SAAS,CAAC,EAAE,CAAC,CAAC;IAChB,CAAC;IACD,IAAI,CAAC;QACH,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IAC9B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACnC,MAAM,KAAK,CAAC;IACd,CAAC;IACD,cAAc,CAAC,SAAS,CAAC,CAAC;AAC5B,CAAC;AAED,6EAA6E;AAC7E,SAAS,gBAAgB,CAAI,IAAY,EAAE,GAAqB;IAC9D,MAAM,IAAI,GAAG,GAAG,IAAI,OAAO,CAAC;IAC5B,OAAO,YAAY,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;YAC/B,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,MAAM,KAAK,UAAU;gBAC5B,CAAC,CAAC,2DAA2D,IAAI,GAAG;gBACpE,CAAC,CAAC,2CAA2C,IAAI,GAAG;YACtD,WAAW,EAAE,MAAM,KAAK,UAAU;gBAChC,CAAC,CAAC,0CAA0C,IAAI,QAAQ,IAAI,8BAA8B,GAAG,EAAE;gBAC/F,CAAC,CAAC,+EAA+E;oBAC/E,+CAA+C,GAAG,EAAE;SACzD,CAAC;KACH,EAAE,GAAG,CAAC,CAAC;AACV,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,UAAe,EAAE,UAAkB;IACxD,MAAM,IAAI,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC7B,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACxG,MAAM,EAAE,GAAG,WAAW,CAAC,EAAE,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,CAAC;QAC/B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;QACtD,MAAM,CAAC,KAAK,EAAE;KACf,CAAC,CAAC;IACH,OAAO;QACL,GAAG,EAAE,QAAQ;QACb,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC7B,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QACzB,GAAG,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAC3C,UAAU,EAAE,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC;KAC1C,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,OAAO,CAAC,KAAqB,EAAE,UAAkB;IAC9D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,EAAE;QAC1E,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;KAC3E,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,gBAAgB,CAAC,aAAa,EAAE,GAAG,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvF,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtD,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC;YAC9B,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;YACxD,QAAQ,CAAC,KAAK,EAAE;SACjB,CAAC,CAAC;QACH,OAAO,KAAK,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAS,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACP,qEAAqE;QACrE,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,+BAA+B;YACrC,OAAO,EAAE,2DAA2D;YACpE,WAAW,EACT,uEAAuE;gBACvE,4DAA4D,GAAG,EAAE;SACpE,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAED,mFAAmF;AAEnF,SAAS,qBAAqB,CAAC,IAAY,EAAE,MAAc,EAAE,WAAmB;IAC9E,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,+BAA+B;QACrC,OAAO,EAAE,mCAAmC,IAAI,qBAAqB,MAAM,GAAG;QAC9E,WAAW,EAAE,GAAG,WAAW,QAAQ,GAAG,EAAE;KACzC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAC,IAAY,EAAE,QAAyB;IACxE,IAAI,IAAI,CAAC;IACT,IAAI,CAAC;QACH,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,IAAI,EAAG,KAAe,CAAC,OAAO,EACxD,4DAA4D,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC;QACnB,MAAM,qBAAqB,CAAC,IAAI,EAAE,0BAA0B,EAC1D,4DAA4D,CAAC,CAAC;IAClE,CAAC;IACD,mEAAmE;IACnE,IAAI,QAAQ,KAAK,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,MAAM,qBAAqB,CAAC,IAAI,EAAE,2CAA2C,EAC3E,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAC9B,CAAC;IACD,IAAI,OAAe,CAAC;IACpB,IAAI,CAAC;QACH,OAAO,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,qBAAqB,CAAC,IAAI,EAAG,KAAe,CAAC,OAAO,EAAE,6BAA6B,CAAC,CAAC;IAC7F,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5B,MAAM,qBAAqB,CAAC,IAAI,EAAE,aAAa,EAAE,qCAAqC,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,SAAS,kBAAkB;IACzB,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,4BAA4B;QAClC,OAAO,EAAE,4CAA4C,qBAAqB,cAAc;QACxF,WAAW,EAAE,wCAAwC;KACtD,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAqB,EACrB,OAA4B,EAC5B,OAAe;IAEf,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;QACxB,MAAM,UAAU,GAAG,kBAAkB,CAAC,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC1E,IAAI,OAAO,KAAK,QAAQ,IAAI,UAAU,CAAC,MAAM,GAAG,qBAAqB;YAAE,MAAM,kBAAkB,EAAE,CAAC;QAClG,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QACrB,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,+BAA+B;YACrC,OAAO,EAAE,8EAA8E;YACvF,WAAW,EACT,sFAAsF;gBACtF,kFAAkF;gBAClF,0BAA0B,GAAG,EAAE;SAClC,CAAC,CAAC;IACL,CAAC;IACD,IAAI,OAAO,KAAK,QAAQ;QAAE,OAAO,cAAc,CAAC,sBAAsB,OAAO,aAAa,CAAC,CAAC;IAC5F,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,2BAA2B,YAAY,EAAE,IAAI,CAAC,CAAC;IACvF,IAAI,UAAU,CAAC,MAAM,GAAG,qBAAqB;QAAE,MAAM,kBAAkB,EAAE,CAAC;IAC1E,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,sBAAsB,CAAC,CAAC;IAC3D,IAAI,KAAK,KAAK,UAAU,EAAE,CAAC;QACzB,MAAM,IAAI,QAAQ,CAAC;YACjB,IAAI,EAAE,2BAA2B;YACjC,OAAO,EAAE,gCAAgC;YACzC,WAAW,EAAE,6CAA6C;SAC3D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,qFAAqF;AAErF,+DAA+D;AAC/D,MAAM,UAAU,qBAAqB,CAAC,OAAe,EAAE,OAAmB;IACxE,MAAM,KAAK,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,6CAA6C,CAAC,CAAC,CAAC,cAAc,OAAO,SAAS,CAAC;IAClH,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,iCAAiC;QACvC,OAAO,EAAE,qBAAqB,KAAK,6CAA6C,OAAO,IAAI;QAC3F,WAAW,EACT,OAAO,KAAK,MAAM;YAChB,CAAC,CAAC,qFAAqF;gBACrF,qCAAqC,GAAG,EAAE;YAC5C,CAAC,CAAC,6BAA6B,OAAO,yCAAyC,OAAO,IAAI;gBACxF,gEAAgE,GAAG,EAAE;KAC5E,CAAC,CAAC;AACL,CAAC;AAED,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAe,EAAE,KAAwB;IACvE,IAAI,OAAO,CAAC,GAAG,CAAC,uBAAuB;QAAE,OAAO,oBAAoB,CAAC;IACrE,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IACzD,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC;YACH,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACrE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,gBAAgB,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;AACtF,CAAC;AAED,iFAAiF;AACjF,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,OAAe,EAAE,KAAwB;IACrE,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;IAChD,IAAI,eAAe;QAAE,OAAO,eAAe,CAAC;IAE5C,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,MAAM,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAE5F,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;QACnC,IAAI,CAAC,MAAM;YAAE,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;QAClC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACxC,MAAM,IAAI,QAAQ,CAAC;gBACjB,IAAI,EAAE,gCAAgC;gBACtC,OAAO,EAAE,2BAA2B,OAAO,+BAA+B;gBAC1E,WAAW,EAAE,wDAAwD,OAAO,WAAW,GAAG,EAAE;aAC7F,CAAC,CAAC;QACL,CAAC;QACD,OAAO,MAAa,CAAC;IACvB,CAAC;IAED,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM;QAAE,MAAM,KAAK,CAAC,OAAO,CAAC,CAAC;IAClC,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,OAAO,OAAO,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACrC,CAAC;AAED,SAAS,KAAK,CAAC,OAAe;IAC5B,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,yCAAyC,OAAO,YAAY;QACrE,WAAW,EAAE,sCAAsC,OAAO,EAAE;KAC7D,CAAC,CAAC;AACL,CAAC;AAcD;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAI,OAAe,EAAE,SAA6B,EAAE,GAAqB;IAChG,MAAM,IAAI,GAAG,YAAY,OAAO,IAAI,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,MAAM,EAAE,EAAE,aAAa,CAAC,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IAC9E,OAAO,YAAY,CAAC,IAAI,EAAE;QACxB,MAAM,EAAE,YAAY;QACpB,MAAM,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,QAAQ,CAAC;YAC/B,IAAI,EAAE,uBAAuB;YAC7B,OAAO,EAAE,MAAM,KAAK,UAAU;gBAC5B,CAAC,CAAC,2DAA2D,IAAI,GAAG;gBACpE,CAAC,CAAC,yDAAyD,OAAO,IAAI;YACxE,WAAW,EAAE,MAAM,KAAK,UAAU;gBAChC,CAAC,CAAC,0CAA0C,IAAI,QAAQ,IAAI,8BAA8B,GAAG,EAAE;gBAC/F,CAAC,CAAC,+EAA+E;oBAC/E,+CAA+C,GAAG,EAAE;SACzD,CAAC;KACH,EAAE,GAAG,CAAC,CAAC;AACV,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC5B,OAAe,EACf,UAAe,EACf,KAAwB,EACxB,QAAuB,EAAE;IAEzB,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,MAAM,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,mBAAmB,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;IAEzD,IAAI,KAAK,CAAC,OAAO,KAAK,UAAU,EAAE,CAAC;QACjC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1F,yEAAyE;QACzE,sEAAsE;QACtE,OAAO,gBAAgB,CAAC,OAAO,EAAE,KAAK,CAAC,aAAa,EAAE,KAAK,IAAI,EAAE;YAC/D,IAAI,KAAK,CAAC,WAAW,EAAE;gBAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACzD,MAAM,KAAK,CAAC,mBAAmB,EAAE,EAAE,CAAC;YACpC,KAAK,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;YACrC,IAAI,QAAQ,KAAK,UAAU;gBAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;YAC7D,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACL,CAAC;IAED,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,yEAAyE;IACzE,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;QAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;IACzF,MAAM,UAAU,GAAG,MAAM,kBAAkB,CAAC,KAAK,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACxD,OAAO,gBAAgB,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QACvC,MAAM,IAAI,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;YAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC;QAC9C,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAChC,KAAK,CAAC,UAAU,EAAE,EAAE,CAAC;QACrB,uEAAuE;QACvE,MAAM,OAAO,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;QACpE,IAAI,SAA8B,CAAC;QACnC,IAAI,OAAO,EAAE,CAAC;YACZ,IAAI,CAAC;gBACH,SAAS,GAAG,UAAU,CAAC,mBAAmB,CAAC,MAAM,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAC1F,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS,GAAG,SAAS,CAAC;YACxB,CAAC;QACH,CAAC;QACD,IAAI,SAAS,KAAK,QAAQ;YAAE,MAAM,gBAAgB,CAAC,OAAO,CAAC,CAAC;QAC5D,OAAO,YAAY,EAAE,CAAC;IACxB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,0BAA0B;QAChC,OAAO,EAAE,yCAAyC,OAAO,YAAY;QACrE,WAAW,EAAE,+DAA+D,OAAO,GAAG;KACvF,CAAC,CAAC;AACL,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAe;IACvC,OAAO,IAAI,QAAQ,CAAC;QAClB,IAAI,EAAE,kCAAkC;QACxC,OAAO,EACL,wBAAwB,OAAO,qDAAqD;YACpF,4CAA4C;QAC9C,WAAW,EACT,gFAAgF;YAChF,iCAAiC,OAAO,SAAS,GAAG,EAAE;KACzD,CAAC,CAAC;AACL,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,OAAe,EAAE,KAAwB;IACpE,OAAO,CAAC,MAAM,SAAS,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC;AACzD,CAAC"}