@solana/keychain-dfns 0.0.0 → 1.0.1
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 +136 -0
- package/dist/__tests__/dfns-signer.integration.test.d.ts +2 -0
- package/dist/__tests__/dfns-signer.integration.test.d.ts.map +1 -0
- package/dist/__tests__/dfns-signer.integration.test.js +17 -0
- package/dist/__tests__/dfns-signer.integration.test.js.map +1 -0
- package/dist/__tests__/dfns-signer.test.d.ts +2 -0
- package/dist/__tests__/dfns-signer.test.d.ts.map +1 -0
- package/dist/__tests__/dfns-signer.test.js +292 -0
- package/dist/__tests__/dfns-signer.test.js.map +1 -0
- package/dist/__tests__/setup.d.ts +45 -0
- package/dist/__tests__/setup.d.ts.map +1 -0
- package/dist/__tests__/setup.js +64 -0
- package/dist/__tests__/setup.js.map +1 -0
- package/dist/auth.d.ts +7 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +237 -0
- package/dist/auth.js.map +1 -0
- package/dist/dfns-signer.d.ts +72 -0
- package/dist/dfns-signer.d.ts.map +1 -0
- package/dist/dfns-signer.js +392 -0
- package/dist/dfns-signer.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/types.d.ts +101 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +61 -8
- package/src/__tests__/dfns-signer.integration.test.ts +17 -0
- package/src/__tests__/dfns-signer.test.ts +398 -0
- package/src/__tests__/setup.ts +76 -0
- package/src/auth.ts +289 -0
- package/src/dfns-signer.ts +495 -0
- package/src/index.ts +2 -0
- package/src/types.ts +113 -0
|
@@ -0,0 +1,392 @@
|
|
|
1
|
+
import { assertIsAddress } from '@solana/addresses';
|
|
2
|
+
import { getBase16Decoder, getBase16Encoder, getBase58Decoder } from '@solana/codecs-strings';
|
|
3
|
+
import { assertSignatureValid, createSignatureDictionary, sanitizeRemoteErrorResponse, SignerErrorCode, throwSignerError, } from '@solana/keychain-core';
|
|
4
|
+
import { getTransactionEncoder, } from '@solana/transactions';
|
|
5
|
+
import { signUserAction } from './auth.js';
|
|
6
|
+
/**
|
|
7
|
+
* Create and initialize a Dfns-backed signer.
|
|
8
|
+
*
|
|
9
|
+
* @throws {SignerError} `SIGNER_CONFIG_ERROR` when required config is missing or invalid.
|
|
10
|
+
* @throws {SignerError} `SIGNER_HTTP_ERROR`, `SIGNER_REMOTE_API_ERROR`, `SIGNER_PARSING_ERROR`,
|
|
11
|
+
* or `SIGNER_INVALID_PUBLIC_KEY` when initialization fails.
|
|
12
|
+
*/
|
|
13
|
+
export async function createDfnsSigner(config) {
|
|
14
|
+
return await DfnsSigner.create(config);
|
|
15
|
+
}
|
|
16
|
+
const DEFAULT_API_BASE_URL = 'https://api.dfns.io';
|
|
17
|
+
let base16Encoder;
|
|
18
|
+
let base16Decoder;
|
|
19
|
+
let base58Decoder;
|
|
20
|
+
function hexToBytes(hex) {
|
|
21
|
+
base16Encoder || (base16Encoder = getBase16Encoder());
|
|
22
|
+
const clean = hex.startsWith('0x') ? hex.slice(2) : hex;
|
|
23
|
+
return new Uint8Array(base16Encoder.encode(clean));
|
|
24
|
+
}
|
|
25
|
+
function bytesToHex(bytes) {
|
|
26
|
+
base16Decoder || (base16Decoder = getBase16Decoder());
|
|
27
|
+
return base16Decoder.decode(bytes);
|
|
28
|
+
}
|
|
29
|
+
function bytesToBase58(bytes) {
|
|
30
|
+
base58Decoder || (base58Decoder = getBase58Decoder());
|
|
31
|
+
return base58Decoder.decode(bytes);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Dfns-based signer for Solana transactions.
|
|
35
|
+
*
|
|
36
|
+
* Uses Dfns Keys API to sign Solana transactions and messages.
|
|
37
|
+
* Requires a Dfns account with an active Ed25519 Solana wallet.
|
|
38
|
+
*
|
|
39
|
+
* Use the static `create()` factory to construct an instance — it validates
|
|
40
|
+
* the wallet status, key scheme, and curve via the Dfns API.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const signer = await DfnsSigner.create({
|
|
45
|
+
* authToken: 'your-service-account-token',
|
|
46
|
+
* credId: 'your-credential-id',
|
|
47
|
+
* privateKeyPem: '-----BEGIN PRIVATE KEY-----\n...',
|
|
48
|
+
* walletId: 'your-wallet-id',
|
|
49
|
+
* });
|
|
50
|
+
* const signed = await signTransactionMessageWithSigners(transactionMessage, [signer]);
|
|
51
|
+
* ```
|
|
52
|
+
*
|
|
53
|
+
* @deprecated Prefer `createDfnsSigner()`. Class export will be removed in a future version.
|
|
54
|
+
*/
|
|
55
|
+
export class DfnsSigner {
|
|
56
|
+
constructor(config) {
|
|
57
|
+
this.address = config.address;
|
|
58
|
+
this.authToken = config.authToken;
|
|
59
|
+
this.credId = config.credId;
|
|
60
|
+
this.privateKeyPem = config.privateKeyPem;
|
|
61
|
+
this.walletId = config.walletId;
|
|
62
|
+
this.apiBaseUrl = config.apiBaseUrl;
|
|
63
|
+
this.keyId = config.keyId;
|
|
64
|
+
this.requestDelayMs = config.requestDelayMs;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Create and initialize a DfnsSigner.
|
|
68
|
+
*
|
|
69
|
+
* Validates config fields, fetches the wallet from Dfns, and checks that
|
|
70
|
+
* the wallet is active with an EdDSA/ed25519 signing key.
|
|
71
|
+
* @deprecated Use `createDfnsSigner()` instead.
|
|
72
|
+
*/
|
|
73
|
+
static async create(config) {
|
|
74
|
+
if (!config.authToken) {
|
|
75
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
76
|
+
message: 'Missing required authToken field',
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
if (!config.credId) {
|
|
80
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
81
|
+
message: 'Missing required credId field',
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
if (!config.privateKeyPem) {
|
|
85
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
86
|
+
message: 'Missing required privateKeyPem field',
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
if (!config.walletId) {
|
|
90
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
91
|
+
message: 'Missing required walletId field',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
const apiBaseUrl = config.apiBaseUrl ?? DEFAULT_API_BASE_URL;
|
|
95
|
+
validateHttpsApiBaseUrl(apiBaseUrl);
|
|
96
|
+
const requestDelayMs = config.requestDelayMs ?? 0;
|
|
97
|
+
if (requestDelayMs < 0) {
|
|
98
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
99
|
+
message: 'requestDelayMs must not be negative',
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
if (requestDelayMs > 3000) {
|
|
103
|
+
console.warn('requestDelayMs is greater than 3000ms, this may result in blockhash expiration errors for signing messages/transactions');
|
|
104
|
+
}
|
|
105
|
+
const wallet = await fetchWallet(apiBaseUrl, config.authToken, config.walletId);
|
|
106
|
+
if (wallet.status !== 'Active') {
|
|
107
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
108
|
+
message: `Wallet is not active: ${wallet.status}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
if (wallet.signingKey.scheme !== 'EdDSA') {
|
|
112
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
113
|
+
message: `Unsupported key scheme: ${wallet.signingKey.scheme} (expected EdDSA)`,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
if (wallet.signingKey.curve !== 'ed25519') {
|
|
117
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
118
|
+
message: `Unsupported key curve: ${wallet.signingKey.curve} (expected ed25519)`,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const pubkeyBytes = hexToBytes(wallet.signingKey.publicKey);
|
|
122
|
+
const bs58Address = bytesToBase58(pubkeyBytes);
|
|
123
|
+
let address;
|
|
124
|
+
try {
|
|
125
|
+
assertIsAddress(bs58Address);
|
|
126
|
+
address = bs58Address;
|
|
127
|
+
}
|
|
128
|
+
catch (error) {
|
|
129
|
+
throwSignerError(SignerErrorCode.INVALID_PUBLIC_KEY, {
|
|
130
|
+
cause: error,
|
|
131
|
+
message: 'Invalid public key from Dfns wallet',
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return new DfnsSigner({
|
|
135
|
+
address,
|
|
136
|
+
apiBaseUrl,
|
|
137
|
+
authToken: config.authToken,
|
|
138
|
+
credId: config.credId,
|
|
139
|
+
keyId: wallet.signingKey.id,
|
|
140
|
+
privateKeyPem: config.privateKeyPem,
|
|
141
|
+
requestDelayMs,
|
|
142
|
+
walletId: config.walletId,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
async delay(index) {
|
|
146
|
+
if (this.requestDelayMs > 0 && index > 0) {
|
|
147
|
+
await new Promise(resolve => setTimeout(resolve, index * this.requestDelayMs));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Sign multiple messages using Dfns
|
|
152
|
+
*/
|
|
153
|
+
async signMessages(messages) {
|
|
154
|
+
return await Promise.all(messages.map(async (message, index) => {
|
|
155
|
+
await this.delay(index);
|
|
156
|
+
const messageBytes = message.content instanceof Uint8Array
|
|
157
|
+
? message.content
|
|
158
|
+
: new Uint8Array(Array.from(message.content));
|
|
159
|
+
const signatureBytes = await this.sendSignatureRequest({
|
|
160
|
+
kind: 'Message',
|
|
161
|
+
message: `0x${bytesToHex(messageBytes)}`,
|
|
162
|
+
});
|
|
163
|
+
await assertSignatureValid({
|
|
164
|
+
data: messageBytes,
|
|
165
|
+
signature: signatureBytes,
|
|
166
|
+
signerAddress: this.address,
|
|
167
|
+
});
|
|
168
|
+
return createSignatureDictionary({
|
|
169
|
+
signature: signatureBytes,
|
|
170
|
+
signerAddress: this.address,
|
|
171
|
+
});
|
|
172
|
+
}));
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Sign multiple transactions using Dfns
|
|
176
|
+
*/
|
|
177
|
+
async signTransactions(transactions) {
|
|
178
|
+
const txEncoder = getTransactionEncoder();
|
|
179
|
+
return await Promise.all(transactions.map(async (transaction, index) => {
|
|
180
|
+
await this.delay(index);
|
|
181
|
+
const txBytes = txEncoder.encode(transaction);
|
|
182
|
+
const signatureBytes = await this.sendSignatureRequest({
|
|
183
|
+
blockchainKind: 'Solana',
|
|
184
|
+
kind: 'Transaction',
|
|
185
|
+
transaction: `0x${bytesToHex(new Uint8Array(txBytes))}`,
|
|
186
|
+
});
|
|
187
|
+
await assertSignatureValid({
|
|
188
|
+
data: transaction.messageBytes,
|
|
189
|
+
signature: signatureBytes,
|
|
190
|
+
signerAddress: this.address,
|
|
191
|
+
});
|
|
192
|
+
return createSignatureDictionary({
|
|
193
|
+
signature: signatureBytes,
|
|
194
|
+
signerAddress: this.address,
|
|
195
|
+
});
|
|
196
|
+
}));
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Check if Dfns API is available
|
|
200
|
+
*/
|
|
201
|
+
async isAvailable() {
|
|
202
|
+
try {
|
|
203
|
+
await fetchWallet(this.apiBaseUrl, this.authToken, this.walletId);
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Send a signature request to the Dfns Keys API
|
|
212
|
+
*/
|
|
213
|
+
async sendSignatureRequest(request) {
|
|
214
|
+
const httpPath = `/keys/${this.keyId}/signatures`;
|
|
215
|
+
const requestBody = JSON.stringify(request);
|
|
216
|
+
const userAction = await signUserAction(this.apiBaseUrl, this.authToken, this.credId, this.privateKeyPem, 'POST', httpPath, requestBody);
|
|
217
|
+
const url = `${this.apiBaseUrl}${httpPath}`;
|
|
218
|
+
let response;
|
|
219
|
+
try {
|
|
220
|
+
response = await fetch(url, {
|
|
221
|
+
body: requestBody,
|
|
222
|
+
headers: {
|
|
223
|
+
Authorization: `Bearer ${this.authToken}`,
|
|
224
|
+
'Content-Type': 'application/json',
|
|
225
|
+
'x-dfns-useraction': userAction,
|
|
226
|
+
},
|
|
227
|
+
method: 'POST',
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
catch (error) {
|
|
231
|
+
throwSignerError(SignerErrorCode.HTTP_ERROR, {
|
|
232
|
+
cause: error,
|
|
233
|
+
message: 'Dfns network request failed',
|
|
234
|
+
url,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
if (!response.ok) {
|
|
238
|
+
const errorText = await response.text().catch(() => 'Failed to read error response');
|
|
239
|
+
throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
|
|
240
|
+
message: `Dfns signing API error: ${response.status}`,
|
|
241
|
+
response: sanitizeRemoteErrorResponse(errorText),
|
|
242
|
+
status: response.status,
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
let rawSigResponse;
|
|
246
|
+
try {
|
|
247
|
+
rawSigResponse = await response.json();
|
|
248
|
+
}
|
|
249
|
+
catch (error) {
|
|
250
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
251
|
+
cause: error,
|
|
252
|
+
message: 'Failed to parse Dfns signature response',
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
const sigResponse = parseSignatureResponse(rawSigResponse);
|
|
256
|
+
if (sigResponse.status === 'Failed') {
|
|
257
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
258
|
+
message: 'Dfns signing failed',
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
if (sigResponse.status !== 'Signed') {
|
|
262
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
263
|
+
message: `Unexpected signature status: ${sigResponse.status} (may require policy approval)`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
if (!sigResponse.signature) {
|
|
267
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
268
|
+
message: 'Signature components missing from response',
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
return combineSignature(sigResponse.signature.r, sigResponse.signature.s);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Fetch wallet details from Dfns
|
|
276
|
+
*/
|
|
277
|
+
async function fetchWallet(apiBaseUrl, authToken, walletId) {
|
|
278
|
+
const url = `${apiBaseUrl}/wallets/${walletId}`;
|
|
279
|
+
let response;
|
|
280
|
+
try {
|
|
281
|
+
response = await fetch(url, {
|
|
282
|
+
headers: {
|
|
283
|
+
Authorization: `Bearer ${authToken}`,
|
|
284
|
+
},
|
|
285
|
+
method: 'GET',
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
catch (error) {
|
|
289
|
+
throwSignerError(SignerErrorCode.HTTP_ERROR, {
|
|
290
|
+
cause: error,
|
|
291
|
+
message: 'Dfns network request failed',
|
|
292
|
+
url,
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
if (!response.ok) {
|
|
296
|
+
const errorText = await response.text().catch(() => 'Failed to read error response');
|
|
297
|
+
throwSignerError(SignerErrorCode.REMOTE_API_ERROR, {
|
|
298
|
+
message: `Dfns API error: ${response.status}`,
|
|
299
|
+
response: sanitizeRemoteErrorResponse(errorText),
|
|
300
|
+
status: response.status,
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
let rawWalletResponse;
|
|
304
|
+
try {
|
|
305
|
+
rawWalletResponse = await response.json();
|
|
306
|
+
}
|
|
307
|
+
catch (error) {
|
|
308
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
309
|
+
cause: error,
|
|
310
|
+
message: 'Failed to parse Dfns wallet response',
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
return parseWalletResponse(rawWalletResponse);
|
|
314
|
+
}
|
|
315
|
+
function validateHttpsApiBaseUrl(apiBaseUrl) {
|
|
316
|
+
let parsedUrl;
|
|
317
|
+
try {
|
|
318
|
+
parsedUrl = new URL(apiBaseUrl);
|
|
319
|
+
}
|
|
320
|
+
catch {
|
|
321
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
322
|
+
message: 'apiBaseUrl is not a valid URL',
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (parsedUrl.protocol !== 'https:') {
|
|
326
|
+
throwSignerError(SignerErrorCode.CONFIG_ERROR, {
|
|
327
|
+
message: 'apiBaseUrl must use HTTPS',
|
|
328
|
+
});
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function parseSignatureResponse(raw) {
|
|
332
|
+
if (!isObject(raw) || typeof raw.status !== 'string') {
|
|
333
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
334
|
+
message: 'Unexpected Dfns signature response shape',
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
if (raw.signature !== undefined) {
|
|
338
|
+
if (!isObject(raw.signature) || typeof raw.signature.r !== 'string' || typeof raw.signature.s !== 'string') {
|
|
339
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
340
|
+
message: 'Unexpected Dfns signature components shape',
|
|
341
|
+
});
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
return raw;
|
|
345
|
+
}
|
|
346
|
+
function parseWalletResponse(raw) {
|
|
347
|
+
if (!isObject(raw) || typeof raw.status !== 'string' || !isObject(raw.signingKey)) {
|
|
348
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
349
|
+
message: 'Unexpected Dfns wallet response shape',
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
if (typeof raw.signingKey.id !== 'string' ||
|
|
353
|
+
typeof raw.signingKey.scheme !== 'string' ||
|
|
354
|
+
typeof raw.signingKey.curve !== 'string' ||
|
|
355
|
+
typeof raw.signingKey.publicKey !== 'string') {
|
|
356
|
+
throwSignerError(SignerErrorCode.PARSING_ERROR, {
|
|
357
|
+
message: 'Unexpected Dfns wallet signing key shape',
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return raw;
|
|
361
|
+
}
|
|
362
|
+
function isObject(value) {
|
|
363
|
+
return typeof value === 'object' && value !== null;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Pad signature component to exactly 32 bytes.
|
|
367
|
+
* Components from Dfns may be shorter than 32 bytes and need left-padding with zeros.
|
|
368
|
+
*/
|
|
369
|
+
function padSignatureComponent(hex) {
|
|
370
|
+
const bytes = hexToBytes(hex);
|
|
371
|
+
if (bytes.length > 32) {
|
|
372
|
+
throwSignerError(SignerErrorCode.SIGNING_FAILED, {
|
|
373
|
+
message: `Invalid signature component length: ${bytes.length} (max 32)`,
|
|
374
|
+
});
|
|
375
|
+
}
|
|
376
|
+
const padded = new Uint8Array(32);
|
|
377
|
+
padded.set(bytes, 32 - bytes.length);
|
|
378
|
+
return padded;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Combine r and s hex-encoded components into a 64-byte Ed25519 signature.
|
|
382
|
+
* Each component is individually validated and left-padded to 32 bytes.
|
|
383
|
+
*/
|
|
384
|
+
function combineSignature(r, s) {
|
|
385
|
+
const rBytes = padSignatureComponent(r);
|
|
386
|
+
const sBytes = padSignatureComponent(s);
|
|
387
|
+
const combined = new Uint8Array(64);
|
|
388
|
+
combined.set(rBytes, 0);
|
|
389
|
+
combined.set(sBytes, 32);
|
|
390
|
+
return combined;
|
|
391
|
+
}
|
|
392
|
+
//# sourceMappingURL=dfns-signer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dfns-signer.js","sourceRoot":"","sources":["../src/dfns-signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAW,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC9F,OAAO,EACH,oBAAoB,EACpB,yBAAyB,EACzB,2BAA2B,EAC3B,eAAe,EAEf,gBAAgB,GACnB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACH,qBAAqB,GAIxB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAQ3C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,MAAwB;IAExB,OAAO,MAAM,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,oBAAoB,GAAG,qBAAqB,CAAC;AAEnD,IAAI,aAA8D,CAAC;AACnE,IAAI,aAA8D,CAAC;AACnE,IAAI,aAA8D,CAAC;AAEnE,SAAS,UAAU,CAAC,GAAW;IAC3B,aAAa,KAAb,aAAa,GAAK,gBAAgB,EAAE,EAAC;IACrC,MAAM,KAAK,GAAG,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;IACxD,OAAO,IAAI,UAAU,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AACvD,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB;IACjC,aAAa,KAAb,aAAa,GAAK,gBAAgB,EAAE,EAAC;IACrC,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AACD,SAAS,aAAa,CAAC,KAAiB;IACpC,aAAa,KAAb,aAAa,GAAK,gBAAgB,EAAE,EAAC;IACrC,OAAO,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,OAAO,UAAU;IAWnB,YAAoB,MASnB;QACG,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;QAClC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,CAAC;QAC1C,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;QAC1B,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;IAChD,CAAC;IAED;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,MAAM,CAAmC,MAAwB;QAC1E,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;YACpB,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,kCAAkC;aAC9C,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACjB,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,+BAA+B;aAC3C,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;YACxB,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,sCAAsC;aAClD,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;YACnB,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,iCAAiC;aAC7C,CAAC,CAAC;QACP,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,IAAI,oBAAoB,CAAC;QAC7D,uBAAuB,CAAC,UAAU,CAAC,CAAC;QACpC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC;QAElD,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;YACrB,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,qCAAqC;aACjD,CAAC,CAAC;QACP,CAAC;QACD,IAAI,cAAc,GAAG,IAAI,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CACR,yHAAyH,CAC5H,CAAC;QACN,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAEhF,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC7B,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,yBAAyB,MAAM,CAAC,MAAM,EAAE;aACpD,CAAC,CAAC;QACP,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YACvC,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,2BAA2B,MAAM,CAAC,UAAU,CAAC,MAAM,mBAAmB;aAClF,CAAC,CAAC;QACP,CAAC;QAED,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;YACxC,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;gBAC3C,OAAO,EAAE,0BAA0B,MAAM,CAAC,UAAU,CAAC,KAAK,qBAAqB;aAClF,CAAC,CAAC;QACP,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC5D,MAAM,WAAW,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAE/C,IAAI,OAA0B,CAAC;QAC/B,IAAI,CAAC;YACD,eAAe,CAAC,WAAW,CAAC,CAAC;YAC7B,OAAO,GAAG,WAAgC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,gBAAgB,CAAC,eAAe,CAAC,kBAAkB,EAAE;gBACjD,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,qCAAqC;aACjD,CAAC,CAAC;QACP,CAAC;QAED,OAAO,IAAI,UAAU,CAAW;YAC5B,OAAO;YACP,UAAU;YACV,SAAS,EAAE,MAAM,CAAC,SAAS;YAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,KAAK,EAAE,MAAM,CAAC,UAAU,CAAC,EAAE;YAC3B,aAAa,EAAE,MAAM,CAAC,aAAa;YACnC,cAAc;YACd,QAAQ,EAAE,MAAM,CAAC,QAAQ;SAC5B,CAAC,CAAC;IACP,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,KAAa;QAC7B,IAAI,IAAI,CAAC,cAAc,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC;QACnF,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAAC,QAAoC;QACnD,OAAO,MAAM,OAAO,CAAC,GAAG,CACpB,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;YAClC,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,MAAM,YAAY,GACd,OAAO,CAAC,OAAO,YAAY,UAAU;gBACjC,CAAC,CAAC,OAAO,CAAC,OAAO;gBACjB,CAAC,CAAC,IAAI,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;YACtD,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC;gBACnD,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,KAAK,UAAU,CAAC,YAAY,CAAC,EAAE;aAC3C,CAAC,CAAC;YACH,MAAM,oBAAoB,CAAC;gBACvB,IAAI,EAAE,YAAY;gBAClB,SAAS,EAAE,cAAc;gBACzB,aAAa,EAAE,IAAI,CAAC,OAAO;aAC9B,CAAC,CAAC;YACH,OAAO,yBAAyB,CAAC;gBAC7B,SAAS,EAAE,cAAc;gBACzB,aAAa,EAAE,IAAI,CAAC,OAAO;aAC9B,CAAC,CAAC;QACP,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,gBAAgB,CAClB,YAA6F;QAE7F,MAAM,SAAS,GAAG,qBAAqB,EAAE,CAAC;QAC1C,OAAO,MAAM,OAAO,CAAC,GAAG,CACpB,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE;YAC1C,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACxB,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC9C,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,oBAAoB,CAAC;gBACnD,cAAc,EAAE,QAAQ;gBACxB,IAAI,EAAE,aAAa;gBACnB,WAAW,EAAE,KAAK,UAAU,CAAC,IAAI,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE;aAC1D,CAAC,CAAC;YACH,MAAM,oBAAoB,CAAC;gBACvB,IAAI,EAAE,WAAW,CAAC,YAAY;gBAC9B,SAAS,EAAE,cAAc;gBACzB,aAAa,EAAE,IAAI,CAAC,OAAO;aAC9B,CAAC,CAAC;YACH,OAAO,yBAAyB,CAAC;gBAC7B,SAAS,EAAE,cAAc;gBACzB,aAAa,EAAE,IAAI,CAAC,OAAO;aAC9B,CAAC,CAAC;QACP,CAAC,CAAC,CACL,CAAC;IACN,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,WAAW;QACb,IAAI,CAAC;YACD,MAAM,WAAW,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;YAClE,OAAO,IAAI,CAAC;QAChB,CAAC;QAAC,MAAM,CAAC;YACL,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAAC,OAAiC;QAChE,MAAM,QAAQ,GAAG,SAAS,IAAI,CAAC,KAAK,aAAa,CAAC;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;QAE5C,MAAM,UAAU,GAAG,MAAM,cAAc,CACnC,IAAI,CAAC,UAAU,EACf,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,MAAM,EACX,IAAI,CAAC,aAAa,EAClB,MAAM,EACN,QAAQ,EACR,WAAW,CACd,CAAC;QAEF,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,UAAU,GAAG,QAAQ,EAAE,CAAC;QAC5C,IAAI,QAAkB,CAAC;QACvB,IAAI,CAAC;YACD,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBACxB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE;oBACL,aAAa,EAAE,UAAU,IAAI,CAAC,SAAS,EAAE;oBACzC,cAAc,EAAE,kBAAkB;oBAClC,mBAAmB,EAAE,UAAU;iBAClC;gBACD,MAAM,EAAE,MAAM;aACjB,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,gBAAgB,CAAC,eAAe,CAAC,UAAU,EAAE;gBACzC,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,6BAA6B;gBACtC,GAAG;aACN,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,+BAA+B,CAAC,CAAC;YACrF,gBAAgB,CAAC,eAAe,CAAC,gBAAgB,EAAE;gBAC/C,OAAO,EAAE,2BAA2B,QAAQ,CAAC,MAAM,EAAE;gBACrD,QAAQ,EAAE,2BAA2B,CAAC,SAAS,CAAC;gBAChD,MAAM,EAAE,QAAQ,CAAC,MAAM;aAC1B,CAAC,CAAC;QACP,CAAC;QAED,IAAI,cAAuB,CAAC;QAC5B,IAAI,CAAC;YACD,cAAc,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC3C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;gBAC5C,KAAK,EAAE,KAAK;gBACZ,OAAO,EAAE,yCAAyC;aACrD,CAAC,CAAC;QACP,CAAC;QAED,MAAM,WAAW,GAAG,sBAAsB,CAAC,cAAc,CAAC,CAAC;QAE3D,IAAI,WAAW,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClC,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;gBAC7C,OAAO,EAAE,qBAAqB;aACjC,CAAC,CAAC;QACP,CAAC;QAED,IAAI,WAAW,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClC,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;gBAC7C,OAAO,EAAE,gCAAgC,WAAW,CAAC,MAAM,gCAAgC;aAC9F,CAAC,CAAC;QACP,CAAC;QAED,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC;YACzB,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;gBAC7C,OAAO,EAAE,4CAA4C;aACxD,CAAC,CAAC;QACP,CAAC;QAED,OAAO,gBAAgB,CAAC,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC9E,CAAC;CACJ;AAED;;GAEG;AACH,KAAK,UAAU,WAAW,CAAC,UAAkB,EAAE,SAAiB,EAAE,QAAgB;IAC9E,MAAM,GAAG,GAAG,GAAG,UAAU,YAAY,QAAQ,EAAE,CAAC;IAChD,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACD,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YACxB,OAAO,EAAE;gBACL,aAAa,EAAE,UAAU,SAAS,EAAE;aACvC;YACD,MAAM,EAAE,KAAK;SAChB,CAAC,CAAC;IACP,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,gBAAgB,CAAC,eAAe,CAAC,UAAU,EAAE;YACzC,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,6BAA6B;YACtC,GAAG;SACN,CAAC,CAAC;IACP,CAAC;IAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,+BAA+B,CAAC,CAAC;QACrF,gBAAgB,CAAC,eAAe,CAAC,gBAAgB,EAAE;YAC/C,OAAO,EAAE,mBAAmB,QAAQ,CAAC,MAAM,EAAE;YAC7C,QAAQ,EAAE,2BAA2B,CAAC,SAAS,CAAC;YAChD,MAAM,EAAE,QAAQ,CAAC,MAAM;SAC1B,CAAC,CAAC;IACP,CAAC;IAED,IAAI,iBAA0B,CAAC;IAC/B,IAAI,CAAC;QACD,iBAAiB,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACb,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;YAC5C,KAAK,EAAE,KAAK;YACZ,OAAO,EAAE,sCAAsC;SAClD,CAAC,CAAC;IACP,CAAC;IAED,OAAO,mBAAmB,CAAC,iBAAiB,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,uBAAuB,CAAC,UAAkB;IAC/C,IAAI,SAAc,CAAC;IACnB,IAAI,CAAC;QACD,SAAS,GAAG,IAAI,GAAG,CAAC,UAAU,CAAC,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACL,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;YAC3C,OAAO,EAAE,+BAA+B;SAC3C,CAAC,CAAC;IACP,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,gBAAgB,CAAC,eAAe,CAAC,YAAY,EAAE;YAC3C,OAAO,EAAE,2BAA2B;SACvC,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED,SAAS,sBAAsB,CAAC,GAAY;IACxC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnD,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;YAC5C,OAAO,EAAE,0CAA0C;SACtD,CAAC,CAAC;IACP,CAAC;IAED,IAAI,GAAG,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,KAAK,QAAQ,EAAE,CAAC;YACzG,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;gBAC5C,OAAO,EAAE,4CAA4C;aACxD,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED,OAAO,GAA2C,CAAC;AACvD,CAAC;AAED,SAAS,mBAAmB,CAAC,GAAY;IACrC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAChF,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;YAC5C,OAAO,EAAE,uCAAuC;SACnD,CAAC,CAAC;IACP,CAAC;IAED,IACI,OAAO,GAAG,CAAC,UAAU,CAAC,EAAE,KAAK,QAAQ;QACrC,OAAO,GAAG,CAAC,UAAU,CAAC,MAAM,KAAK,QAAQ;QACzC,OAAO,GAAG,CAAC,UAAU,CAAC,KAAK,KAAK,QAAQ;QACxC,OAAO,GAAG,CAAC,UAAU,CAAC,SAAS,KAAK,QAAQ,EAC9C,CAAC;QACC,gBAAgB,CAAC,eAAe,CAAC,aAAa,EAAE;YAC5C,OAAO,EAAE,0CAA0C;SACtD,CAAC,CAAC;IACP,CAAC;IAED,OAAO,GAAmC,CAAC;AAC/C,CAAC;AAED,SAAS,QAAQ,CAAC,KAAc;IAC5B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,CAAC;AACvD,CAAC;AAED;;;GAGG;AACH,SAAS,qBAAqB,CAAC,GAAW;IACtC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAE9B,IAAI,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;QACpB,gBAAgB,CAAC,eAAe,CAAC,cAAc,EAAE;YAC7C,OAAO,EAAE,uCAAuC,KAAK,CAAC,MAAM,WAAW;SAC1E,CAAC,CAAC;IACP,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAClC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC;IACrC,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,CAAS,EAAE,CAAS;IAC1C,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,qBAAqB,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACpC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxB,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACzB,OAAO,QAA0B,CAAC;AACtC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAChE,YAAY,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration for creating a DfnsSigner
|
|
3
|
+
*/
|
|
4
|
+
export interface DfnsSignerConfig {
|
|
5
|
+
/** API base URL (default: "https://api.dfns.io") */
|
|
6
|
+
apiBaseUrl?: string;
|
|
7
|
+
/** Service account token or personal access token */
|
|
8
|
+
authToken: string;
|
|
9
|
+
/** Credential ID for user action signing */
|
|
10
|
+
credId: string;
|
|
11
|
+
/** Private key in PEM format for signing user action challenges (Ed25519, P256, or RSA) */
|
|
12
|
+
privateKeyPem: string;
|
|
13
|
+
/** Optional delay in ms between concurrent signing requests to avoid rate limits (default: 0) */
|
|
14
|
+
requestDelayMs?: number;
|
|
15
|
+
/** Dfns wallet ID */
|
|
16
|
+
walletId: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Dfns wallet response
|
|
20
|
+
*/
|
|
21
|
+
export interface GetWalletResponse {
|
|
22
|
+
id: string;
|
|
23
|
+
signingKey: {
|
|
24
|
+
curve: string;
|
|
25
|
+
id: string;
|
|
26
|
+
publicKey: string;
|
|
27
|
+
scheme: string;
|
|
28
|
+
};
|
|
29
|
+
status: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Message signature request body for Dfns Keys API
|
|
33
|
+
*/
|
|
34
|
+
export interface GenerateMessageSignatureRequest {
|
|
35
|
+
kind: 'Message';
|
|
36
|
+
message: string;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Transaction signature request body for Dfns Keys API
|
|
40
|
+
*/
|
|
41
|
+
export interface GenerateTransactionSignatureRequest {
|
|
42
|
+
blockchainKind: string;
|
|
43
|
+
kind: 'Transaction';
|
|
44
|
+
transaction: string;
|
|
45
|
+
}
|
|
46
|
+
export type GenerateSignatureRequest = GenerateMessageSignatureRequest | GenerateTransactionSignatureRequest;
|
|
47
|
+
/**
|
|
48
|
+
* Signature response from Dfns Keys API
|
|
49
|
+
*/
|
|
50
|
+
export interface GenerateSignatureResponse {
|
|
51
|
+
id: string;
|
|
52
|
+
signature?: SignatureComponents;
|
|
53
|
+
signedData?: string;
|
|
54
|
+
status: string;
|
|
55
|
+
}
|
|
56
|
+
export interface SignatureComponents {
|
|
57
|
+
r: string;
|
|
58
|
+
s: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* User action challenge init request
|
|
62
|
+
*/
|
|
63
|
+
export interface UserActionInitRequest {
|
|
64
|
+
userActionHttpMethod: string;
|
|
65
|
+
userActionHttpPath: string;
|
|
66
|
+
userActionPayload: string;
|
|
67
|
+
userActionServerKind: string;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* User action challenge init response
|
|
71
|
+
*/
|
|
72
|
+
export interface UserActionInitResponse {
|
|
73
|
+
allowCredentials: {
|
|
74
|
+
key: Array<{
|
|
75
|
+
id: string;
|
|
76
|
+
}>;
|
|
77
|
+
};
|
|
78
|
+
challenge: string;
|
|
79
|
+
challengeIdentifier: string;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* User action sign request
|
|
83
|
+
*/
|
|
84
|
+
export interface UserActionSignRequest {
|
|
85
|
+
challengeIdentifier: string;
|
|
86
|
+
firstFactor: {
|
|
87
|
+
credentialAssertion: {
|
|
88
|
+
clientData: string;
|
|
89
|
+
credId: string;
|
|
90
|
+
signature: string;
|
|
91
|
+
};
|
|
92
|
+
kind: string;
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* User action sign response
|
|
97
|
+
*/
|
|
98
|
+
export interface UserActionResponse {
|
|
99
|
+
userAction: string;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAElB,4CAA4C;IAC5C,MAAM,EAAE,MAAM,CAAC;IAEf,2FAA2F;IAC3F,aAAa,EAAE,MAAM,CAAC;IAEtB,iGAAiG;IACjG,cAAc,CAAC,EAAE,MAAM,CAAC;IAExB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE;QACR,KAAK,EAAE,MAAM,CAAC;QACd,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC5C,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,mCAAmC;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,MAAM,wBAAwB,GAAG,+BAA+B,GAAG,mCAAmC,CAAC;AAE7G;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAChC,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,oBAAoB,EAAE,MAAM,CAAC;IAC7B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;IAC1B,oBAAoB,EAAE,MAAM,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACnC,gBAAgB,EAAE;QACd,GAAG,EAAE,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KAC9B,CAAC;IACF,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;CAC/B;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IAClC,mBAAmB,EAAE,MAAM,CAAC;IAC5B,WAAW,EAAE;QACT,mBAAmB,EAAE;YACjB,UAAU,EAAE,MAAM,CAAC;YACnB,MAAM,EAAE,MAAM,CAAC;YACf,SAAS,EAAE,MAAM,CAAC;SACrB,CAAC;QACF,IAAI,EAAE,MAAM,CAAC;KAChB,CAAC;CACL;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAC/B,UAAU,EAAE,MAAM,CAAC;CACtB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,12 +1,65 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/keychain-dfns",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
"
|
|
3
|
+
"author": "Solana Foundation",
|
|
4
|
+
"version": "1.0.1",
|
|
5
|
+
"description": "Dfns-based signer for Solana transactions",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"repository": "https://github.com/solana-foundation/solana-keychain",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"solana",
|
|
10
|
+
"signing",
|
|
11
|
+
"wallet",
|
|
12
|
+
"dfns",
|
|
13
|
+
"ed25519",
|
|
14
|
+
"eddsa"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"src"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@solana/keychain-core": "1.0.1"
|
|
32
|
+
},
|
|
33
|
+
"peerDependencies": {
|
|
34
|
+
"@solana/addresses": ">=6.0.1",
|
|
35
|
+
"@solana/codecs-strings": ">=6.0.1",
|
|
36
|
+
"@solana/keys": ">=6.0.1",
|
|
37
|
+
"@solana/signers": ">=6.0.1",
|
|
38
|
+
"@solana/transactions": ">=6.0.1"
|
|
39
|
+
},
|
|
40
|
+
"devDependencies": {
|
|
41
|
+
"@solana/addresses": "^6.0.1",
|
|
42
|
+
"@solana/codecs-strings": "^6.0.1",
|
|
43
|
+
"@solana/keys": "^6.0.1",
|
|
44
|
+
"@solana/kit": "^6.0.1",
|
|
45
|
+
"@solana/signers": "^6.0.1",
|
|
46
|
+
"@solana/transactions": "^6.0.1",
|
|
47
|
+
"dotenv": "^17.2.3",
|
|
48
|
+
"@solana/keychain-test-utils": "1.0.1"
|
|
49
|
+
},
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"access": "public"
|
|
52
|
+
},
|
|
9
53
|
"scripts": {
|
|
10
|
-
"
|
|
54
|
+
"build": "tsc --build",
|
|
55
|
+
"clean": "rm -rf dist *.tsbuildinfo",
|
|
56
|
+
"test": "vitest run",
|
|
57
|
+
"test:unit": "vitest run --config ../../vitest.config.unit.ts",
|
|
58
|
+
"test:integration": "vitest run --config ../../vitest.config.integration.ts",
|
|
59
|
+
"test:watch": "vitest",
|
|
60
|
+
"test:watch:unit": "vitest --config ../../vitest.config.unit.ts",
|
|
61
|
+
"test:watch:integration": "vitest --config ../../vitest.config.integration.ts",
|
|
62
|
+
"typecheck": "tsc --noEmit",
|
|
63
|
+
"test:treeshakability": "agadoo dist/index.js"
|
|
11
64
|
}
|
|
12
|
-
}
|
|
65
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { describe, it } from 'vitest';
|
|
2
|
+
import { runSignerIntegrationTest } from '@solana/keychain-test-utils';
|
|
3
|
+
import { getConfig } from './setup';
|
|
4
|
+
import { config } from 'dotenv';
|
|
5
|
+
config();
|
|
6
|
+
|
|
7
|
+
describe('DfnsSigner Integration', () => {
|
|
8
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('signs transactions with real API', async () => {
|
|
9
|
+
await runSignerIntegrationTest(await getConfig(['signTransaction']));
|
|
10
|
+
});
|
|
11
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('signs messages with real API', async () => {
|
|
12
|
+
await runSignerIntegrationTest(await getConfig(['signMessage']));
|
|
13
|
+
});
|
|
14
|
+
it.skipIf(!process.env.DFNS_AUTH_TOKEN)('simulates transactions with real API', async () => {
|
|
15
|
+
await runSignerIntegrationTest(await getConfig(['simulateTransaction']));
|
|
16
|
+
});
|
|
17
|
+
});
|