nullpath-mcp 1.2.0 → 1.3.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.
@@ -0,0 +1,254 @@
1
+ "use strict";
2
+ /**
3
+ * Payment Integration for nullpath MCP Client
4
+ *
5
+ * Handles x402 payment flow:
6
+ * 1. Parse 402 Payment Required responses
7
+ * 2. Sign EIP-3009 TransferWithAuthorization
8
+ * 3. Encode payment header for retry
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.InvalidPrivateKeyError = exports.WalletNotConfiguredError = exports.isWalletConfigured = exports.PaymentSigningError = exports.PaymentRequiredError = void 0;
12
+ exports.parsePaymentRequired = parsePaymentRequired;
13
+ exports.signPayment = signPayment;
14
+ exports.encodePaymentHeader = encodePaymentHeader;
15
+ exports.fetchWithPayment = fetchWithPayment;
16
+ exports.formatUsdcAmount = formatUsdcAmount;
17
+ const eip3009_js_1 = require("./eip3009.js");
18
+ const wallet_js_1 = require("./wallet.js");
19
+ /** Expected network for payments (Base mainnet) */
20
+ const EXPECTED_NETWORK = 8453;
21
+ /**
22
+ * Error thrown when payment is required but cannot be made
23
+ */
24
+ class PaymentRequiredError extends Error {
25
+ requirements;
26
+ constructor(message, requirements) {
27
+ super(message);
28
+ this.requirements = requirements;
29
+ this.name = 'PaymentRequiredError';
30
+ }
31
+ }
32
+ exports.PaymentRequiredError = PaymentRequiredError;
33
+ /**
34
+ * Error thrown when payment signing fails
35
+ */
36
+ class PaymentSigningError extends Error {
37
+ cause;
38
+ constructor(message, cause) {
39
+ super(message);
40
+ this.cause = cause;
41
+ this.name = 'PaymentSigningError';
42
+ }
43
+ }
44
+ exports.PaymentSigningError = PaymentSigningError;
45
+ /**
46
+ * Parse 402 Payment Required response headers
47
+ *
48
+ * Extracts payment requirements from X-PAYMENT-REQUIRED header.
49
+ * The header contains base64-encoded JSON with payment details.
50
+ *
51
+ * @param response - Fetch Response object
52
+ * @returns PaymentRequirements or null if not a 402 response
53
+ */
54
+ function parsePaymentRequired(response) {
55
+ if (response.status !== 402) {
56
+ return null;
57
+ }
58
+ const header = response.headers.get('X-PAYMENT-REQUIRED');
59
+ if (!header) {
60
+ // Try legacy header name
61
+ const legacyHeader = response.headers.get('X-Payment-Required');
62
+ if (!legacyHeader) {
63
+ throw new PaymentRequiredError('Payment required but X-PAYMENT-REQUIRED header missing');
64
+ }
65
+ return parsePaymentHeader(legacyHeader);
66
+ }
67
+ return parsePaymentHeader(header);
68
+ }
69
+ /**
70
+ * Parse the payment header value
71
+ */
72
+ function parsePaymentHeader(header) {
73
+ try {
74
+ // Decode base64
75
+ const decoded = Buffer.from(header, 'base64').toString('utf-8');
76
+ const data = JSON.parse(decoded);
77
+ // Extract and validate required fields
78
+ const recipient = data.recipient || data.payee;
79
+ const amount = data.amount || data.maxAmountRequired;
80
+ const asset = data.asset || data.usdcAddress;
81
+ const network = data.network || data.chainId || 8453;
82
+ // Default validity window: now to 5 minutes from now
83
+ const now = Math.floor(Date.now() / 1000);
84
+ const validAfter = BigInt(data.validAfter || 0);
85
+ const validBefore = BigInt(data.validBefore || now + 300);
86
+ // Ensure authorization window is still valid
87
+ if (validBefore <= BigInt(now)) {
88
+ throw new Error(`Payment authorization expired: validBefore ${validBefore} is in the past`);
89
+ }
90
+ if (!recipient || !amount) {
91
+ throw new Error('Missing recipient or amount');
92
+ }
93
+ return {
94
+ recipient: recipient,
95
+ amount: BigInt(amount),
96
+ asset: (asset || eip3009_js_1.USDC_ADDRESS_BASE),
97
+ network: Number(network),
98
+ validAfter,
99
+ validBefore,
100
+ };
101
+ }
102
+ catch (error) {
103
+ throw new PaymentRequiredError(`Failed to parse payment requirements: ${error instanceof Error ? error.message : 'unknown error'}`);
104
+ }
105
+ }
106
+ /**
107
+ * Sign a payment using EIP-3009 TransferWithAuthorization
108
+ *
109
+ * @param wallet - NullpathWallet instance
110
+ * @param requirements - Payment requirements from 402 response
111
+ * @returns Signed authorization
112
+ */
113
+ async function signPayment(wallet, requirements) {
114
+ // Validate that the requested payment matches our signing configuration
115
+ const requestedNetwork = requirements.network;
116
+ const requestedAsset = requirements.asset?.toLowerCase();
117
+ const expectedAsset = eip3009_js_1.USDC_ADDRESS_BASE.toLowerCase();
118
+ if (requestedNetwork !== EXPECTED_NETWORK || requestedAsset !== expectedAsset) {
119
+ throw new PaymentRequiredError(`Payment requirements mismatch: requested network ${requestedNetwork} and asset ${requirements.asset} ` +
120
+ `do not match supported Base mainnet USDC (network ${EXPECTED_NETWORK}, asset ${eip3009_js_1.USDC_ADDRESS_BASE}).`);
121
+ }
122
+ try {
123
+ const params = {
124
+ from: wallet.address,
125
+ to: requirements.recipient,
126
+ value: requirements.amount,
127
+ validAfter: requirements.validAfter,
128
+ validBefore: requirements.validBefore,
129
+ nonce: (0, eip3009_js_1.generateNonce)(),
130
+ };
131
+ return await (0, eip3009_js_1.signTransferAuthorization)(wallet.client, params);
132
+ }
133
+ catch (error) {
134
+ throw new PaymentSigningError(`Failed to sign payment: ${error instanceof Error ? error.message : 'unknown error'}`, error instanceof Error ? error : undefined);
135
+ }
136
+ }
137
+ /**
138
+ * Encode signed authorization as X-PAYMENT header value
139
+ *
140
+ * @param signed - Signed transfer authorization
141
+ * @returns Base64-encoded JSON string for X-PAYMENT header
142
+ */
143
+ function encodePaymentHeader(signed) {
144
+ const payload = {
145
+ signature: signed.signature,
146
+ from: signed.from,
147
+ to: signed.to,
148
+ value: signed.value.toString(),
149
+ validAfter: signed.validAfter.toString(),
150
+ validBefore: signed.validBefore.toString(),
151
+ nonce: signed.nonce,
152
+ };
153
+ return Buffer.from(JSON.stringify(payload)).toString('base64');
154
+ }
155
+ /**
156
+ * Build headers for fetch, properly handling Headers instances
157
+ */
158
+ function buildHeaders(base, extra) {
159
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
160
+ const headers = new Headers(base);
161
+ if (extra) {
162
+ for (const [key, value] of Object.entries(extra)) {
163
+ headers.set(key, value);
164
+ }
165
+ }
166
+ return headers;
167
+ }
168
+ /**
169
+ * Execute a fetch request with automatic x402 payment handling
170
+ *
171
+ * If the server returns 402 Payment Required:
172
+ * 1. Parse payment requirements
173
+ * 2. Sign EIP-3009 authorization
174
+ * 3. Retry with X-PAYMENT header
175
+ *
176
+ * @param url - Request URL
177
+ * @param options - Fetch options
178
+ * @returns Fetch Response
179
+ * @throws WalletNotConfiguredError if 402 and no wallet
180
+ * @throws PaymentSigningError if signing fails
181
+ */
182
+ async function fetchWithPayment(url, options = {}) {
183
+ // Build headers properly (handles both plain objects and Headers instances)
184
+ const initialHeaders = buildHeaders(options.headers, {
185
+ 'Content-Type': 'application/json',
186
+ });
187
+ // Make initial request
188
+ const response = await fetch(url, {
189
+ ...options,
190
+ headers: initialHeaders,
191
+ });
192
+ // Check for 402 Payment Required
193
+ if (response.status !== 402) {
194
+ return response;
195
+ }
196
+ // Payment required - check if wallet is configured
197
+ if (!(0, wallet_js_1.isWalletConfigured)()) {
198
+ throw new wallet_js_1.WalletNotConfiguredError();
199
+ }
200
+ // Parse payment requirements
201
+ const requirements = parsePaymentRequired(response);
202
+ if (!requirements) {
203
+ throw new PaymentRequiredError('Payment required but could not parse requirements');
204
+ }
205
+ // Create wallet and sign payment
206
+ let wallet;
207
+ try {
208
+ wallet = (0, wallet_js_1.createWallet)();
209
+ }
210
+ catch (error) {
211
+ if (error instanceof wallet_js_1.InvalidPrivateKeyError) {
212
+ throw new PaymentSigningError(`Invalid wallet configuration: ${error.message}`, error);
213
+ }
214
+ throw error;
215
+ }
216
+ const signed = await signPayment(wallet, requirements);
217
+ const paymentHeader = encodePaymentHeader(signed);
218
+ // Build retry headers with payment
219
+ const retryHeaders = buildHeaders(options.headers, {
220
+ 'Content-Type': 'application/json',
221
+ 'X-PAYMENT': paymentHeader,
222
+ });
223
+ // Retry with payment header
224
+ const retryResponse = await fetch(url, {
225
+ ...options,
226
+ headers: retryHeaders,
227
+ });
228
+ // If still 402, payment was rejected
229
+ if (retryResponse.status === 402) {
230
+ const errorBody = await retryResponse.text().catch(() => '');
231
+ throw new PaymentRequiredError(`Payment was rejected by the server: ${errorBody || 'no details'}`, requirements);
232
+ }
233
+ // Handle other errors on retry
234
+ if (!retryResponse.ok) {
235
+ const errorBody = await retryResponse.text().catch(() => '');
236
+ throw new Error(`Payment submitted but request failed (${retryResponse.status}): ${errorBody}`);
237
+ }
238
+ return retryResponse;
239
+ }
240
+ /**
241
+ * Format amount in human-readable USDC (using bigint arithmetic to avoid precision loss)
242
+ */
243
+ function formatUsdcAmount(atomic) {
244
+ const whole = atomic / 1000000n;
245
+ const fraction = atomic % 1000000n;
246
+ const fractionStr = fraction.toString().padStart(6, '0');
247
+ return `$${whole.toString()}.${fractionStr} USDC`;
248
+ }
249
+ // Re-export wallet utilities for convenience
250
+ var wallet_js_2 = require("./wallet.js");
251
+ Object.defineProperty(exports, "isWalletConfigured", { enumerable: true, get: function () { return wallet_js_2.isWalletConfigured; } });
252
+ Object.defineProperty(exports, "WalletNotConfiguredError", { enumerable: true, get: function () { return wallet_js_2.WalletNotConfiguredError; } });
253
+ Object.defineProperty(exports, "InvalidPrivateKeyError", { enumerable: true, get: function () { return wallet_js_2.InvalidPrivateKeyError; } });
254
+ //# sourceMappingURL=payment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.js","sourceRoot":"","sources":["../../src/lib/payment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Wallet Client Setup for nullpath MCP Client
3
+ *
4
+ * Creates a viem wallet client from the NULLPATH_WALLET_KEY
5
+ * environment variable for signing EIP-3009 payments.
6
+ */
7
+ import { type WalletClient, type Account } from 'viem';
8
+ /**
9
+ * Environment variable name for the wallet private key
10
+ */
11
+ export declare const WALLET_KEY_ENV = "NULLPATH_WALLET_KEY";
12
+ /**
13
+ * Wallet configuration
14
+ */
15
+ export interface WalletConfig {
16
+ /** Private key (with or without 0x prefix) */
17
+ privateKey?: string;
18
+ /** RPC URL for Base (optional, uses default public RPC) */
19
+ rpcUrl?: string;
20
+ }
21
+ /**
22
+ * Wallet client with account information
23
+ */
24
+ export interface NullpathWallet {
25
+ /** viem wallet client for signing */
26
+ client: WalletClient;
27
+ /** Account derived from private key */
28
+ account: Account;
29
+ /** Wallet address */
30
+ address: `0x${string}`;
31
+ }
32
+ /**
33
+ * Error thrown when wallet is not configured
34
+ */
35
+ export declare class WalletNotConfiguredError extends Error {
36
+ constructor();
37
+ }
38
+ /**
39
+ * Error thrown when private key is invalid
40
+ */
41
+ export declare class InvalidPrivateKeyError extends Error {
42
+ constructor(reason: string);
43
+ }
44
+ /**
45
+ * Create a wallet client from configuration or environment
46
+ *
47
+ * @param config - Optional wallet configuration. If not provided,
48
+ * reads from NULLPATH_WALLET_KEY environment variable.
49
+ * @returns NullpathWallet with client, account, and address
50
+ * @throws WalletNotConfiguredError if no private key available
51
+ * @throws InvalidPrivateKeyError if private key format is invalid
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * // From environment variable
56
+ * const wallet = createWallet();
57
+ *
58
+ * // From explicit config
59
+ * const wallet = createWallet({ privateKey: '0x...' });
60
+ *
61
+ * // Use for signing
62
+ * const signed = await signTransferAuthorization(wallet.client, params);
63
+ * ```
64
+ */
65
+ export declare function createWallet(config?: WalletConfig): NullpathWallet;
66
+ /**
67
+ * Check if wallet is configured (without creating it)
68
+ *
69
+ * @returns true if NULLPATH_WALLET_KEY is set
70
+ */
71
+ export declare function isWalletConfigured(): boolean;
72
+ /**
73
+ * Get wallet address without full client setup
74
+ *
75
+ * Useful for checking the configured address without
76
+ * creating a full wallet client.
77
+ *
78
+ * @returns Wallet address or null if not configured
79
+ */
80
+ export declare function getWalletAddress(): `0x${string}` | null;
81
+ //# sourceMappingURL=wallet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.d.ts","sourceRoot":"","sources":["../../src/lib/wallet.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA4B,KAAK,YAAY,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAIjF;;GAEG;AACH,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,qCAAqC;IACrC,MAAM,EAAE,YAAY,CAAC;IACrB,uCAAuC;IACvC,OAAO,EAAE,OAAO,CAAC;IACjB,qBAAqB;IACrB,OAAO,EAAE,KAAK,MAAM,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,qBAAa,wBAAyB,SAAQ,KAAK;;CAOlD;AAED;;GAEG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,MAAM,EAAE,MAAM;CAI3B;AA4BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,cAAc,CA0BlE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAE5C;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,IAAI,KAAK,MAAM,EAAE,GAAG,IAAI,CAWvD"}
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ /**
3
+ * Wallet Client Setup for nullpath MCP Client
4
+ *
5
+ * Creates a viem wallet client from the NULLPATH_WALLET_KEY
6
+ * environment variable for signing EIP-3009 payments.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.InvalidPrivateKeyError = exports.WalletNotConfiguredError = exports.WALLET_KEY_ENV = void 0;
10
+ exports.createWallet = createWallet;
11
+ exports.isWalletConfigured = isWalletConfigured;
12
+ exports.getWalletAddress = getWalletAddress;
13
+ const viem_1 = require("viem");
14
+ const accounts_1 = require("viem/accounts");
15
+ const chains_1 = require("viem/chains");
16
+ /**
17
+ * Environment variable name for the wallet private key
18
+ */
19
+ exports.WALLET_KEY_ENV = 'NULLPATH_WALLET_KEY';
20
+ /**
21
+ * Error thrown when wallet is not configured
22
+ */
23
+ class WalletNotConfiguredError extends Error {
24
+ constructor() {
25
+ super(`Wallet not configured. Set ${exports.WALLET_KEY_ENV} environment variable with your private key.`);
26
+ this.name = 'WalletNotConfiguredError';
27
+ }
28
+ }
29
+ exports.WalletNotConfiguredError = WalletNotConfiguredError;
30
+ /**
31
+ * Error thrown when private key is invalid
32
+ */
33
+ class InvalidPrivateKeyError extends Error {
34
+ constructor(reason) {
35
+ super(`Invalid private key: ${reason}`);
36
+ this.name = 'InvalidPrivateKeyError';
37
+ }
38
+ }
39
+ exports.InvalidPrivateKeyError = InvalidPrivateKeyError;
40
+ /**
41
+ * Normalize private key to proper format
42
+ *
43
+ * Accepts keys with or without 0x prefix
44
+ */
45
+ function normalizePrivateKey(key) {
46
+ const trimmed = key.trim();
47
+ // Add 0x prefix if missing
48
+ const prefixed = trimmed.startsWith('0x') ? trimmed : `0x${trimmed}`;
49
+ // Validate length (0x + 64 hex chars = 66 chars)
50
+ if (prefixed.length !== 66) {
51
+ throw new InvalidPrivateKeyError(`Expected 64 hex characters, got ${prefixed.length - 2}`);
52
+ }
53
+ // Validate hex format
54
+ if (!/^0x[0-9a-fA-F]{64}$/.test(prefixed)) {
55
+ throw new InvalidPrivateKeyError('Must contain only hexadecimal characters');
56
+ }
57
+ return prefixed;
58
+ }
59
+ /**
60
+ * Create a wallet client from configuration or environment
61
+ *
62
+ * @param config - Optional wallet configuration. If not provided,
63
+ * reads from NULLPATH_WALLET_KEY environment variable.
64
+ * @returns NullpathWallet with client, account, and address
65
+ * @throws WalletNotConfiguredError if no private key available
66
+ * @throws InvalidPrivateKeyError if private key format is invalid
67
+ *
68
+ * @example
69
+ * ```ts
70
+ * // From environment variable
71
+ * const wallet = createWallet();
72
+ *
73
+ * // From explicit config
74
+ * const wallet = createWallet({ privateKey: '0x...' });
75
+ *
76
+ * // Use for signing
77
+ * const signed = await signTransferAuthorization(wallet.client, params);
78
+ * ```
79
+ */
80
+ function createWallet(config) {
81
+ // Get private key from config or environment
82
+ const rawKey = config?.privateKey ?? process.env[exports.WALLET_KEY_ENV];
83
+ if (!rawKey) {
84
+ throw new WalletNotConfiguredError();
85
+ }
86
+ // Normalize and validate
87
+ const privateKey = normalizePrivateKey(rawKey);
88
+ // Create account from private key
89
+ const account = (0, accounts_1.privateKeyToAccount)(privateKey);
90
+ // Create wallet client for Base mainnet
91
+ const client = (0, viem_1.createWalletClient)({
92
+ account,
93
+ chain: chains_1.base,
94
+ transport: (0, viem_1.http)(config?.rpcUrl),
95
+ });
96
+ return {
97
+ client,
98
+ account,
99
+ address: account.address,
100
+ };
101
+ }
102
+ /**
103
+ * Check if wallet is configured (without creating it)
104
+ *
105
+ * @returns true if NULLPATH_WALLET_KEY is set
106
+ */
107
+ function isWalletConfigured() {
108
+ return !!process.env[exports.WALLET_KEY_ENV];
109
+ }
110
+ /**
111
+ * Get wallet address without full client setup
112
+ *
113
+ * Useful for checking the configured address without
114
+ * creating a full wallet client.
115
+ *
116
+ * @returns Wallet address or null if not configured
117
+ */
118
+ function getWalletAddress() {
119
+ const rawKey = process.env[exports.WALLET_KEY_ENV];
120
+ if (!rawKey)
121
+ return null;
122
+ try {
123
+ const privateKey = normalizePrivateKey(rawKey);
124
+ const account = (0, accounts_1.privateKeyToAccount)(privateKey);
125
+ return account.address;
126
+ }
127
+ catch {
128
+ return null;
129
+ }
130
+ }
131
+ //# sourceMappingURL=wallet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wallet.js","sourceRoot":"","sources":["../../src/lib/wallet.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAsGH,oCA0BC;AAOD,gDAEC;AAUD,4CAWC;AA5JD,+BAAiF;AACjF,4CAAoD;AACpD,wCAAmC;AAEnC;;GAEG;AACU,QAAA,cAAc,GAAG,qBAAqB,CAAC;AAwBpD;;GAEG;AACH,MAAa,wBAAyB,SAAQ,KAAK;IACjD;QACE,KAAK,CACH,8BAA8B,sBAAc,8CAA8C,CAC3F,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAPD,4DAOC;AAED;;GAEG;AACH,MAAa,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,MAAc;QACxB,KAAK,CAAC,wBAAwB,MAAM,EAAE,CAAC,CAAC;QACxC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AALD,wDAKC;AAED;;;;GAIG;AACH,SAAS,mBAAmB,CAAC,GAAW;IACtC,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IAE3B,2BAA2B;IAC3B,MAAM,QAAQ,GAAG,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,EAAE,CAAC;IAErE,iDAAiD;IACjD,IAAI,QAAQ,CAAC,MAAM,KAAK,EAAE,EAAE,CAAC;QAC3B,MAAM,IAAI,sBAAsB,CAC9B,mCAAmC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CACzD,CAAC;IACJ,CAAC;IAED,sBAAsB;IACtB,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,sBAAsB,CAAC,0CAA0C,CAAC,CAAC;IAC/E,CAAC;IAED,OAAO,QAAyB,CAAC;AACnC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,SAAgB,YAAY,CAAC,MAAqB;IAChD,6CAA6C;IAC7C,MAAM,MAAM,GAAG,MAAM,EAAE,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,sBAAc,CAAC,CAAC;IAEjE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,wBAAwB,EAAE,CAAC;IACvC,CAAC;IAED,yBAAyB;IACzB,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAE/C,kCAAkC;IAClC,MAAM,OAAO,GAAG,IAAA,8BAAmB,EAAC,UAAU,CAAC,CAAC;IAEhD,wCAAwC;IACxC,MAAM,MAAM,GAAG,IAAA,yBAAkB,EAAC;QAChC,OAAO;QACP,KAAK,EAAE,aAAI;QACX,SAAS,EAAE,IAAA,WAAI,EAAC,MAAM,EAAE,MAAM,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO;QACL,MAAM;QACN,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,OAAO;KACzB,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,SAAgB,kBAAkB;IAChC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,sBAAc,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,SAAgB,gBAAgB;IAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAc,CAAC,CAAC;IAC3C,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,IAAA,8BAAmB,EAAC,UAAU,CAAC,CAAC;QAChD,OAAO,OAAO,CAAC,OAAO,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}