@solana/keychain-gcp-kms 0.0.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.
package/README.md ADDED
@@ -0,0 +1,103 @@
1
+ # @solana/keychain-gcp-kms
2
+
3
+ Google Cloud KMS-based signer for Solana transactions using EdDSA (Ed25519) signing.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @solana/keychain-gcp-kms
9
+ ```
10
+
11
+ ## Prerequisites
12
+
13
+ 1. A Google Cloud KMS key with:
14
+ - **Algorithm**: `EC_SIGN_ED25519`
15
+ - **Purpose**: `ASYMMETRIC_SIGN`
16
+
17
+ 2. Google Cloud credentials configured (see [Google Cloud Credentials](#google-cloud-credentials) below)
18
+
19
+ ## Google Cloud Credentials
20
+
21
+ The signer uses the **Application Default Credentials (ADC)** to authenticate. You don't need to pass credentials explicitly when running in a Google Cloud environment (Compute Engine, GKE, Cloud Run, etc.).
22
+
23
+ ### IAM Permissions
24
+
25
+ For this signer:
26
+
27
+ - Signing operations require `cloudkms.cryptoKeyVersions.useToSign`
28
+ - Availability checks (`isAvailable()`) require `cloudkms.cryptoKeyVersions.viewPublicKey`
29
+
30
+ ### Local Development
31
+
32
+ For local development, you can:
33
+
34
+ 1. **Use the gcloud CLI**:
35
+ ```bash
36
+ gcloud auth application-default login
37
+ ```
38
+
39
+ 2. **Use a Service Account Key**:
40
+ ```bash
41
+ export GOOGLE_APPLICATION_CREDENTIALS="/path/to/your/service-account-file.json"
42
+ ```
43
+
44
+ ## Creating a Google Cloud KMS Key
45
+
46
+ Use the `gcloud` CLI to create a key suitable for Solana signing:
47
+
48
+ ```bash
49
+ # Create a KeyRing
50
+ gcloud kms keyrings create "my-keyring" --location "us-east1"
51
+
52
+ # Create a CryptoKey
53
+ gcloud kms keys create "my-key" \
54
+ --location "us-east1" \
55
+ --keyring "my-keyring" \
56
+ --purpose "asymmetric-signing" \
57
+ --default-algorithm "ec-sign-ed25519"
58
+ ```
59
+
60
+ ## Usage
61
+
62
+ ### Basic Example
63
+
64
+ ```typescript
65
+ import { GcpKmsSigner } from '@solana/keychain-gcp-kms';
66
+
67
+ const signer = new GcpKmsSigner({
68
+ keyName: 'projects/my-project/locations/us-east1/keyRings/my-ring/cryptoKeys/my-key/cryptoKeyVersions/1',
69
+ publicKey: 'YourSolanaPublicKeyBase58',
70
+ });
71
+
72
+ // Sign a message
73
+ const message = { content: new Uint8Array([1, 2, 3, 4]) };
74
+ const signatures = await signer.signMessages([message]);
75
+
76
+ // Sign a transaction
77
+ const signatures = await signer.signTransactions([transaction]);
78
+ ```
79
+
80
+ ## API Reference
81
+
82
+ ### `GcpKmsSigner`
83
+
84
+ #### Constructor
85
+
86
+ ```typescript
87
+ new GcpKmsSigner(config: GcpKmsSignerConfig)
88
+ ```
89
+
90
+ **Config Options:**
91
+ - `keyName` (required): Full resource name of the GCP KMS crypto key version
92
+ - `publicKey` (required): Solana public key (base58-encoded)
93
+ - `requestDelayMs` (optional): Delay in ms between concurrent signing requests to avoid rate limits (default: 0)
94
+
95
+ #### Properties
96
+
97
+ - `address`: The Solana address (public key) for this signer
98
+
99
+ #### Methods
100
+
101
+ - `signMessages(messages)`: Sign multiple messages
102
+ - `signTransactions(transactions)`: Sign multiple transactions
103
+ - `isAvailable()`: Check if the signer is available by retrieving the public key and verifying `EC_SIGN_ED25519`
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gcp-kms-signer.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-kms-signer.integration.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/gcp-kms-signer.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,49 @@
1
+ import { appendTransactionMessageInstructions, createSolanaRpc, createTransactionMessage, pipe, setTransactionMessageFeePayerSigner, setTransactionMessageLifetimeUsingBlockhash, signTransactionMessageWithSigners, } from '@solana/kit';
2
+ import { getAddMemoInstruction } from '@solana-program/memo';
3
+ import { config } from 'dotenv';
4
+ import { describe, expect, it } from 'vitest';
5
+ import { GcpKmsSigner } from '../gcp-kms-signer.js';
6
+ config();
7
+ const REQUIRED_ENV_VARS = ['GCP_KMS_KEY_NAME', 'GCP_KMS_SIGNER_PUBKEY'];
8
+ function hasRequiredEnvVars() {
9
+ return REQUIRED_ENV_VARS.every(v => process.env[v]);
10
+ }
11
+ function createGcpKmsSigner() {
12
+ return new GcpKmsSigner({
13
+ keyName: process.env.GCP_KMS_KEY_NAME,
14
+ publicKey: process.env.GCP_KMS_SIGNER_PUBKEY,
15
+ });
16
+ }
17
+ describe('GcpKmsSigner Integration', () => {
18
+ it.skipIf(!hasRequiredEnvVars())('signs transactions with GCP KMS', async () => {
19
+ const signer = createGcpKmsSigner();
20
+ const rpcUrl = process.env.SOLANA_RPC_URL ?? 'https://api.devnet.solana.com';
21
+ // Get real blockhash from devnet
22
+ const rpc = createSolanaRpc(rpcUrl);
23
+ const { value: { blockhash, lastValidBlockHeight }, } = await rpc.getLatestBlockhash().send();
24
+ // Create memo transaction (doesn't need funds)
25
+ const transaction = pipe(createTransactionMessage({ version: 0 }), tx => setTransactionMessageFeePayerSigner(signer, tx), tx => appendTransactionMessageInstructions([getAddMemoInstruction({ memo: 'GCP KMS test' })], tx), tx => setTransactionMessageLifetimeUsingBlockhash({ blockhash, lastValidBlockHeight }, tx));
26
+ // Sign via GCP KMS
27
+ const signed = await signTransactionMessageWithSigners(transaction);
28
+ // Verify signature returned
29
+ expect(signed.signatures[signer.address]).toBeDefined();
30
+ expect(signed.signatures[signer.address]?.length).toBe(64);
31
+ }, 60000); // 1 minute timeout
32
+ it.skipIf(!hasRequiredEnvVars())('signs messages', async () => {
33
+ const signer = createGcpKmsSigner();
34
+ const message = {
35
+ content: new Uint8Array([1, 2, 3, 4, 5]),
36
+ signatures: {},
37
+ };
38
+ const result = await signer.signMessages([message]);
39
+ expect(result).toHaveLength(1);
40
+ expect(result[0]?.[signer.address]).toBeDefined();
41
+ expect(result[0]?.[signer.address]?.length).toBe(64);
42
+ });
43
+ it.skipIf(!hasRequiredEnvVars())('checks availability', async () => {
44
+ const signer = createGcpKmsSigner();
45
+ const available = await signer.isAvailable();
46
+ expect(available).toBe(true);
47
+ });
48
+ });
49
+ //# sourceMappingURL=gcp-kms-signer.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-kms-signer.integration.test.js","sourceRoot":"","sources":["../../src/__tests__/gcp-kms-signer.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=gcp-kms-signer.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-kms-signer.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/gcp-kms-signer.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,286 @@
1
+ import { address } from '@solana/addresses';
2
+ import { beforeEach, describe, expect, it, vi } from 'vitest';
3
+ import { assertIsSolanaSigner } from '@solana/keychain-core';
4
+ import { GcpKmsSigner } from '../gcp-kms-signer.js';
5
+ // Mock GCP KMS SDK
6
+ const mockAsymmetricSign = vi.fn();
7
+ const mockGetPublicKey = vi.fn();
8
+ vi.mock('@google-cloud/kms', () => {
9
+ return {
10
+ v1: {
11
+ KeyManagementServiceClient: class {
12
+ constructor() {
13
+ this.asymmetricSign = mockAsymmetricSign;
14
+ this.getPublicKey = mockGetPublicKey;
15
+ }
16
+ },
17
+ },
18
+ };
19
+ });
20
+ describe('GcpKmsSigner', () => {
21
+ const TEST_KEY_NAME = 'projects/test-project/locations/us-east1/keyRings/test-ring/cryptoKeys/test-key/cryptoKeyVersions/1';
22
+ const TEST_PUBLIC_KEY = address('11111111111111111111111111111111');
23
+ beforeEach(() => {
24
+ vi.clearAllMocks();
25
+ });
26
+ describe('constructor', () => {
27
+ it('creates a GcpKmsSigner with valid config', () => {
28
+ const config = {
29
+ keyName: TEST_KEY_NAME,
30
+ publicKey: TEST_PUBLIC_KEY,
31
+ };
32
+ const signer = new GcpKmsSigner(config);
33
+ expect(signer.address).toBe(TEST_PUBLIC_KEY);
34
+ assertIsSolanaSigner(signer);
35
+ expect(signer.signMessages).toBeDefined();
36
+ expect(signer.signTransactions).toBeDefined();
37
+ expect(signer.isAvailable).toBeDefined();
38
+ });
39
+ it('should throw error for missing keyName', () => {
40
+ expect(() => {
41
+ new GcpKmsSigner({
42
+ keyName: '',
43
+ publicKey: TEST_PUBLIC_KEY,
44
+ });
45
+ }).toThrow('Missing required keyName field');
46
+ });
47
+ it('should throw error for missing publicKey', () => {
48
+ expect(() => {
49
+ new GcpKmsSigner({
50
+ keyName: TEST_KEY_NAME,
51
+ publicKey: '',
52
+ });
53
+ }).toThrow('Missing required publicKey field');
54
+ });
55
+ it('should throw error for invalid public key', () => {
56
+ expect(() => {
57
+ new GcpKmsSigner({
58
+ keyName: TEST_KEY_NAME,
59
+ publicKey: 'invalid-key',
60
+ });
61
+ }).toThrow('Invalid Solana public key format');
62
+ });
63
+ it('should validate requestDelayMs', () => {
64
+ expect(() => {
65
+ new GcpKmsSigner({
66
+ keyName: TEST_KEY_NAME,
67
+ publicKey: TEST_PUBLIC_KEY,
68
+ requestDelayMs: -1,
69
+ });
70
+ }).toThrow('requestDelayMs must not be negative');
71
+ });
72
+ it('should warn for high requestDelayMs', () => {
73
+ const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => { });
74
+ new GcpKmsSigner({
75
+ keyName: TEST_KEY_NAME,
76
+ publicKey: TEST_PUBLIC_KEY,
77
+ requestDelayMs: 5000,
78
+ });
79
+ expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('requestDelayMs is greater than 3000ms'));
80
+ warnSpy.mockRestore();
81
+ });
82
+ });
83
+ describe('signMessages', () => {
84
+ it('should sign a message successfully', async () => {
85
+ mockAsymmetricSign.mockResolvedValue([
86
+ {
87
+ signature: new Uint8Array(64).fill(0x42),
88
+ },
89
+ ]);
90
+ const signer = new GcpKmsSigner({
91
+ keyName: TEST_KEY_NAME,
92
+ publicKey: TEST_PUBLIC_KEY,
93
+ });
94
+ const message = {
95
+ content: new Uint8Array([1, 2, 3, 4]),
96
+ signatures: {},
97
+ };
98
+ const result = await signer.signMessages([message]);
99
+ expect(result).toHaveLength(1);
100
+ expect(result[0]?.[signer.address]).toBeDefined();
101
+ expect(mockAsymmetricSign).toHaveBeenCalledTimes(1);
102
+ expect(mockAsymmetricSign).toHaveBeenCalledWith({
103
+ data: message.content,
104
+ name: TEST_KEY_NAME,
105
+ });
106
+ });
107
+ it('should handle multiple messages with delay', async () => {
108
+ mockAsymmetricSign.mockResolvedValue([
109
+ {
110
+ signature: new Uint8Array(64).fill(0x42),
111
+ },
112
+ ]);
113
+ const signer = new GcpKmsSigner({
114
+ keyName: TEST_KEY_NAME,
115
+ publicKey: TEST_PUBLIC_KEY,
116
+ requestDelayMs: 10,
117
+ });
118
+ const messages = [
119
+ { content: new Uint8Array([1]), signatures: {} },
120
+ { content: new Uint8Array([2]), signatures: {} },
121
+ { content: new Uint8Array([3]), signatures: {} },
122
+ ];
123
+ const startTime = Date.now();
124
+ const result = await signer.signMessages(messages);
125
+ const endTime = Date.now();
126
+ expect(result).toHaveLength(3);
127
+ expect(mockAsymmetricSign).toHaveBeenCalledTimes(3);
128
+ // Should have some delay (at least 15ms for 2 delays of 10ms each)
129
+ expect(endTime - startTime).toBeGreaterThanOrEqual(15);
130
+ });
131
+ it('should throw error on invalid signature length', async () => {
132
+ mockAsymmetricSign.mockResolvedValue([
133
+ {
134
+ signature: new Uint8Array(32), // Wrong length
135
+ },
136
+ ]);
137
+ const signer = new GcpKmsSigner({
138
+ keyName: TEST_KEY_NAME,
139
+ publicKey: TEST_PUBLIC_KEY,
140
+ });
141
+ const message = { content: new Uint8Array([1, 2, 3, 4]), signatures: {} };
142
+ await expect(signer.signMessages([message])).rejects.toThrow('Invalid signature length');
143
+ });
144
+ it('should throw error on missing signature', async () => {
145
+ mockAsymmetricSign.mockResolvedValue([{}]);
146
+ const signer = new GcpKmsSigner({
147
+ keyName: TEST_KEY_NAME,
148
+ publicKey: TEST_PUBLIC_KEY,
149
+ });
150
+ const message = { content: new Uint8Array([1, 2, 3, 4]), signatures: {} };
151
+ await expect(signer.signMessages([message])).rejects.toThrow('No signature in GCP KMS response');
152
+ });
153
+ it('should handle GCP KMS API errors', async () => {
154
+ const apiError = new Error('GCP Error');
155
+ apiError.code = 403;
156
+ mockAsymmetricSign.mockRejectedValue(apiError);
157
+ const signer = new GcpKmsSigner({
158
+ keyName: TEST_KEY_NAME,
159
+ publicKey: TEST_PUBLIC_KEY,
160
+ });
161
+ const message = { content: new Uint8Array([1, 2, 3, 4]), signatures: {} };
162
+ await expect(signer.signMessages([message])).rejects.toThrow('GCP KMS Sign operation failed: GCP Error');
163
+ });
164
+ });
165
+ describe('signTransactions', () => {
166
+ it('should sign a transaction successfully', async () => {
167
+ mockAsymmetricSign.mockResolvedValue([
168
+ {
169
+ signature: new Uint8Array(64).fill(0x42),
170
+ },
171
+ ]);
172
+ const signer = new GcpKmsSigner({
173
+ keyName: TEST_KEY_NAME,
174
+ publicKey: TEST_PUBLIC_KEY,
175
+ });
176
+ const transaction = {
177
+ messageBytes: new Uint8Array([1, 2, 3, 4]),
178
+ signatures: {},
179
+ };
180
+ const result = await signer.signTransactions([transaction]);
181
+ expect(result).toHaveLength(1);
182
+ expect(result[0]).toHaveProperty(signer.address);
183
+ expect(mockAsymmetricSign).toHaveBeenCalledTimes(1);
184
+ });
185
+ it('should sign multiple transactions successfully', async () => {
186
+ mockAsymmetricSign.mockResolvedValue([
187
+ {
188
+ signature: new Uint8Array(64).fill(0x42),
189
+ },
190
+ ]);
191
+ const signer = new GcpKmsSigner({
192
+ keyName: TEST_KEY_NAME,
193
+ publicKey: TEST_PUBLIC_KEY,
194
+ });
195
+ const transactions = [
196
+ { messageBytes: new Uint8Array([1]), signatures: {} },
197
+ { messageBytes: new Uint8Array([2]), signatures: {} },
198
+ ];
199
+ const result = await signer.signTransactions(transactions);
200
+ expect(result).toHaveLength(2);
201
+ expect(mockAsymmetricSign).toHaveBeenCalledTimes(2);
202
+ });
203
+ it('should throw error on invalid signature length', async () => {
204
+ mockAsymmetricSign.mockResolvedValue([
205
+ {
206
+ signature: new Uint8Array(32),
207
+ },
208
+ ]);
209
+ const signer = new GcpKmsSigner({
210
+ keyName: TEST_KEY_NAME,
211
+ publicKey: TEST_PUBLIC_KEY,
212
+ });
213
+ const transaction = { messageBytes: new Uint8Array([1, 2, 3, 4]), signatures: {} };
214
+ await expect(signer.signTransactions([transaction])).rejects.toThrow('Invalid signature length');
215
+ });
216
+ it('should throw error on missing signature', async () => {
217
+ mockAsymmetricSign.mockResolvedValue([{}]);
218
+ const signer = new GcpKmsSigner({
219
+ keyName: TEST_KEY_NAME,
220
+ publicKey: TEST_PUBLIC_KEY,
221
+ });
222
+ const transaction = { messageBytes: new Uint8Array([1, 2, 3, 4]), signatures: {} };
223
+ await expect(signer.signTransactions([transaction])).rejects.toThrow('No signature in GCP KMS response');
224
+ });
225
+ it('should handle GCP KMS API errors', async () => {
226
+ const apiError = new Error('GCP Error');
227
+ apiError.code = 403;
228
+ mockAsymmetricSign.mockRejectedValue(apiError);
229
+ const signer = new GcpKmsSigner({
230
+ keyName: TEST_KEY_NAME,
231
+ publicKey: TEST_PUBLIC_KEY,
232
+ });
233
+ const transaction = { messageBytes: new Uint8Array([1, 2, 3, 4]), signatures: {} };
234
+ await expect(signer.signTransactions([transaction])).rejects.toThrow('GCP KMS Sign operation failed: GCP Error');
235
+ });
236
+ });
237
+ describe('isAvailable', () => {
238
+ it('should return true for valid Ed25519 key', async () => {
239
+ mockGetPublicKey.mockResolvedValue([
240
+ {
241
+ name: TEST_KEY_NAME,
242
+ algorithm: 'EC_SIGN_ED25519',
243
+ },
244
+ ]);
245
+ const signer = new GcpKmsSigner({
246
+ keyName: TEST_KEY_NAME,
247
+ publicKey: TEST_PUBLIC_KEY,
248
+ });
249
+ const available = await signer.isAvailable();
250
+ expect(available).toBe(true);
251
+ });
252
+ it('should return false for wrong algorithm', async () => {
253
+ mockGetPublicKey.mockResolvedValue([
254
+ {
255
+ name: TEST_KEY_NAME,
256
+ algorithm: 'RSA_SIGN_PKCS1_2048_SHA256',
257
+ },
258
+ ]);
259
+ const signer = new GcpKmsSigner({
260
+ keyName: TEST_KEY_NAME,
261
+ publicKey: TEST_PUBLIC_KEY,
262
+ });
263
+ const available = await signer.isAvailable();
264
+ expect(available).toBe(false);
265
+ });
266
+ it('should return false for missing public key response', async () => {
267
+ mockGetPublicKey.mockResolvedValue([undefined]);
268
+ const signer = new GcpKmsSigner({
269
+ keyName: TEST_KEY_NAME,
270
+ publicKey: TEST_PUBLIC_KEY,
271
+ });
272
+ const available = await signer.isAvailable();
273
+ expect(available).toBe(false);
274
+ });
275
+ it('should return false on error', async () => {
276
+ mockGetPublicKey.mockRejectedValue(new Error('GCP error'));
277
+ const signer = new GcpKmsSigner({
278
+ keyName: TEST_KEY_NAME,
279
+ publicKey: TEST_PUBLIC_KEY,
280
+ });
281
+ const available = await signer.isAvailable();
282
+ expect(available).toBe(false);
283
+ });
284
+ });
285
+ });
286
+ //# sourceMappingURL=gcp-kms-signer.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-kms-signer.test.js","sourceRoot":"","sources":["../../src/__tests__/gcp-kms-signer.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { Address } from '@solana/addresses';
2
+ import { SolanaSigner } from '@solana/keychain-core';
3
+ import { SignableMessage, SignatureDictionary } from '@solana/signers';
4
+ import { Transaction, TransactionWithinSizeLimit, TransactionWithLifetime } from '@solana/transactions';
5
+ import type { GcpKmsSignerConfig } from './types.js';
6
+ /**
7
+ * Google Cloud KMS-based signer using EdDSA (Ed25519) signing
8
+ *
9
+ * The GCP KMS key must be created with:
10
+ * - Algorithm: EC_SIGN_ED25519
11
+ * - Purpose: ASYMMETRIC_SIGN
12
+ *
13
+ * Example gcloud CLI command to create a key:
14
+ * ```bash
15
+ * gcloud kms keys create my-key \
16
+ * --keyring=my-keyring \
17
+ * --location=us-east1 \
18
+ * --purpose=asymmetric-signing \
19
+ * --default-algorithm=ec-sign-ed25519
20
+ * ```
21
+ */
22
+ export declare class GcpKmsSigner<TAddress extends string = string> implements SolanaSigner<TAddress> {
23
+ readonly address: Address<TAddress>;
24
+ private readonly keyName;
25
+ private readonly client;
26
+ private readonly requestDelayMs;
27
+ constructor(config: GcpKmsSignerConfig);
28
+ /**
29
+ * Validate request delay ms
30
+ */
31
+ private validateRequestDelayMs;
32
+ /**
33
+ * Add delay between concurrent requests
34
+ */
35
+ private delay;
36
+ /**
37
+ * Sign message bytes using GCP KMS EdDSA signing
38
+ */
39
+ private signBytes;
40
+ /**
41
+ * Sign multiple messages using GCP KMS
42
+ */
43
+ signMessages(messages: readonly SignableMessage[]): Promise<readonly SignatureDictionary[]>;
44
+ /**
45
+ * Sign multiple transactions using GCP KMS
46
+ */
47
+ signTransactions(transactions: readonly (Transaction & TransactionWithinSizeLimit & TransactionWithLifetime)[]): Promise<readonly SignatureDictionary[]>;
48
+ /**
49
+ * Check if GCP KMS is available and the key is accessible
50
+ */
51
+ isAvailable(): Promise<boolean>;
52
+ }
53
+ //# sourceMappingURL=gcp-kms-signer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp-kms-signer.d.ts","sourceRoot":"","sources":["../src/gcp-kms-signer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAmB,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAA8C,YAAY,EAAoB,MAAM,uBAAuB,CAAC;AAEnH,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AACvE,OAAO,EAAE,WAAW,EAAE,0BAA0B,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAExG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,YAAY,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,CAAE,YAAW,YAAY,CAAC,QAAQ,CAAC;IACzF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgC;IACvD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;gBAE5B,MAAM,EAAE,kBAAkB;IA6BtC;;OAEG;IACH,OAAO,CAAC,sBAAsB;IAa9B;;OAEG;YACW,KAAK;IAMnB;;OAEG;YACW,SAAS;IA4CvB;;OAEG;IACG,YAAY,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,GAAG,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC;IAiBjG;;OAEG;IACG,gBAAgB,CAClB,YAAY,EAAE,SAAS,CAAC,WAAW,GAAG,0BAA0B,GAAG,uBAAuB,CAAC,EAAE,GAC9F,OAAO,CAAC,SAAS,mBAAmB,EAAE,CAAC;IAc1C;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;CAgBxC"}