@mentaproject/signer-react-native 0.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/dist/signer.js ADDED
@@ -0,0 +1,378 @@
1
+ import { Passkey } from "react-native-passkey";
2
+ import { hashTypedData, keccak256, } from "viem";
3
+ import { extractPublicKeyFromAttestation, encodeUncompressedPublicKey, isValidP256PublicKey, COSEParseError, } from "./utils/cose.js";
4
+ import { bytesToBase64Url, base64UrlToHex } from "./utils/base64url.js";
5
+ import { parseWebAuthnAssertion, encodeWebAuthnSignature, createAssertionOptions, SignatureError, } from "./utils/passkey.js";
6
+ /**
7
+ * Error thrown when passkey operations fail.
8
+ */
9
+ export class PasskeySignerError extends Error {
10
+ cause;
11
+ constructor(message, cause) {
12
+ super(message);
13
+ this.cause = cause;
14
+ this.name = "PasskeySignerError";
15
+ }
16
+ }
17
+ /**
18
+ * ReactNativePasskeySigner implements SmartAccountSigner using WebAuthn/Passkeys.
19
+ *
20
+ * This signer uses the device's biometric authentication (Face ID, Touch ID, fingerprint)
21
+ * to sign messages and transactions for ERC-4337 smart accounts.
22
+ *
23
+ * The public key is a P-256 (secp256r1) key stored in the device's secure enclave.
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Register a new passkey
28
+ * const signer = await ReactNativePasskeySigner.register("user@example.com", {
29
+ * rpId: "example.com",
30
+ * rpName: "Example App",
31
+ * });
32
+ *
33
+ * // Sign a message (triggers biometric prompt)
34
+ * const signature = await signer.signMessage({
35
+ * message: { raw: userOpHash },
36
+ * });
37
+ * ```
38
+ */
39
+ export class ReactNativePasskeySigner {
40
+ source = "passkey";
41
+ /**
42
+ * The credential ID in Base64URL format.
43
+ */
44
+ credentialId;
45
+ /**
46
+ * The credential ID as hex.
47
+ */
48
+ credentialIdHex;
49
+ /**
50
+ * The P-256 public key coordinates (x, y).
51
+ */
52
+ publicKeyCoordinates;
53
+ /**
54
+ * The encoded public key (uncompressed SEC1 format: 0x04 || x || y).
55
+ */
56
+ publicKey;
57
+ /**
58
+ * Configuration for passkey operations.
59
+ */
60
+ config;
61
+ /**
62
+ * Creates a new ReactNativePasskeySigner instance.
63
+ * Use the static `register` or `fromCredential` methods instead of calling this directly.
64
+ *
65
+ * @param credential - The passkey credential data
66
+ * @param config - Configuration for passkey operations
67
+ */
68
+ constructor(credential, config) {
69
+ this.credentialId = credential.credentialId;
70
+ this.credentialIdHex = credential.credentialIdHex;
71
+ this.publicKeyCoordinates = credential.publicKey;
72
+ this.publicKey = credential.publicKeyHex;
73
+ this.config = {
74
+ ...config,
75
+ timeout: config.timeout ?? 60000,
76
+ userVerification: config.userVerification ?? "required",
77
+ signatureFormat: config.signatureFormat ?? "kernel",
78
+ };
79
+ }
80
+ /**
81
+ * Registers a new passkey and returns a signer instance.
82
+ *
83
+ * This triggers the device's WebAuthn registration flow:
84
+ * 1. Shows a system prompt to create a new passkey
85
+ * 2. User authenticates with biometrics
86
+ * 3. Device generates a new P-256 key pair in the secure enclave
87
+ * 4. Returns the public key and credential ID
88
+ *
89
+ * @param username - The username for the passkey (displayed in system UI)
90
+ * @param config - Configuration for the passkey
91
+ * @returns A new ReactNativePasskeySigner instance
92
+ * @throws PasskeySignerError if registration fails
93
+ */
94
+ static async register(username, config) {
95
+ // Generate a random user ID
96
+ const userId = new Uint8Array(32);
97
+ crypto.getRandomValues(userId);
98
+ const userIdB64 = bytesToBase64Url(userId);
99
+ // Generate a random challenge
100
+ const challenge = new Uint8Array(32);
101
+ crypto.getRandomValues(challenge);
102
+ const challengeB64 = bytesToBase64Url(challenge);
103
+ try {
104
+ // Call the native passkey creation
105
+ const result = await Passkey.create({
106
+ challenge: challengeB64,
107
+ rp: {
108
+ id: config.rpId,
109
+ name: config.rpName,
110
+ },
111
+ user: {
112
+ id: userIdB64,
113
+ name: username,
114
+ displayName: username,
115
+ },
116
+ pubKeyCredParams: [
117
+ {
118
+ type: "public-key",
119
+ alg: -7, // ES256 (P-256 with SHA-256)
120
+ },
121
+ ],
122
+ authenticatorSelection: {
123
+ authenticatorAttachment: "platform",
124
+ residentKey: "required",
125
+ requireResidentKey: true,
126
+ userVerification: config.userVerification ?? "required",
127
+ },
128
+ timeout: config.timeout ?? 60000,
129
+ attestation: "none",
130
+ });
131
+ // Extract the credential ID
132
+ const credentialId = result.id;
133
+ const credentialIdHex = base64UrlToHex(credentialId);
134
+ // Parse the attestation to extract the public key
135
+ // The attestationObject contains the COSE-encoded public key
136
+ if (!result.response.attestationObject) {
137
+ throw new PasskeySignerError("Registration response missing attestationObject");
138
+ }
139
+ const { publicKey } = extractPublicKeyFromAttestation(result.response.attestationObject);
140
+ // Validate the public key
141
+ if (!isValidP256PublicKey(publicKey)) {
142
+ throw new PasskeySignerError("Invalid public key extracted from attestation");
143
+ }
144
+ // Encode the public key in uncompressed format
145
+ const publicKeyHex = encodeUncompressedPublicKey(publicKey);
146
+ const credential = {
147
+ credentialId,
148
+ credentialIdHex,
149
+ publicKey,
150
+ publicKeyHex,
151
+ };
152
+ return new ReactNativePasskeySigner(credential, config);
153
+ }
154
+ catch (error) {
155
+ if (error instanceof COSEParseError) {
156
+ throw new PasskeySignerError(`Failed to parse attestation: ${error.message}`, error);
157
+ }
158
+ if (error instanceof PasskeySignerError) {
159
+ throw error;
160
+ }
161
+ throw new PasskeySignerError(`Passkey registration failed: ${error instanceof Error ? error.message : "Unknown error"}`, error);
162
+ }
163
+ }
164
+ /**
165
+ * Creates a signer from an existing credential.
166
+ *
167
+ * Use this when you have previously registered a passkey and stored the credential data.
168
+ *
169
+ * @param credential - The stored credential data
170
+ * @param config - Configuration for passkey operations
171
+ * @returns A new ReactNativePasskeySigner instance
172
+ */
173
+ static fromCredential(credential, config) {
174
+ if (!isValidP256PublicKey(credential.publicKey)) {
175
+ throw new PasskeySignerError("Invalid public key in credential");
176
+ }
177
+ return new ReactNativePasskeySigner(credential, config);
178
+ }
179
+ /**
180
+ * Signs a message using the passkey.
181
+ *
182
+ * This triggers the device's biometric authentication prompt.
183
+ * The message can be a string or raw bytes (typically a UserOpHash).
184
+ *
185
+ * @param params - The message to sign
186
+ * @returns The encoded signature
187
+ * @throws PasskeySignerError if signing fails
188
+ */
189
+ async signMessage({ message, }) {
190
+ // Convert message to bytes
191
+ let messageBytes;
192
+ if (typeof message === "string") {
193
+ // For string messages, hash with EIP-191 prefix
194
+ const encoder = new TextEncoder();
195
+ const msgBytes = encoder.encode(message);
196
+ const prefix = `\x19Ethereum Signed Message:\n${msgBytes.length}`;
197
+ const prefixBytes = encoder.encode(prefix);
198
+ const combined = new Uint8Array(prefixBytes.length + msgBytes.length);
199
+ combined.set(prefixBytes, 0);
200
+ combined.set(msgBytes, prefixBytes.length);
201
+ // Hash the prefixed message
202
+ const hash = keccak256(combined);
203
+ messageBytes = this.hexToBytes(hash);
204
+ }
205
+ else if ("raw" in message) {
206
+ // For raw bytes, use them directly (typically already a hash)
207
+ if (typeof message.raw === "string") {
208
+ messageBytes = this.hexToBytes(message.raw);
209
+ }
210
+ else {
211
+ messageBytes = message.raw;
212
+ }
213
+ }
214
+ else {
215
+ throw new PasskeySignerError("Invalid message format");
216
+ }
217
+ // Create challenge from the message bytes
218
+ const challenge = bytesToBase64Url(messageBytes);
219
+ return this.signWithPasskey(challenge);
220
+ }
221
+ /**
222
+ * Signs typed data according to EIP-712.
223
+ *
224
+ * @param typedData - The typed data to sign
225
+ * @returns The encoded signature
226
+ * @throws PasskeySignerError if signing fails
227
+ */
228
+ async signTypedData(typedData) {
229
+ // Hash the typed data according to EIP-712
230
+ const hash = hashTypedData(typedData);
231
+ // Convert hash to bytes for challenge
232
+ const messageBytes = this.hexToBytes(hash);
233
+ const challenge = bytesToBase64Url(messageBytes);
234
+ return this.signWithPasskey(challenge);
235
+ }
236
+ /**
237
+ * Returns the address derived from the public key.
238
+ *
239
+ * Note: P-256 keys don't directly map to Ethereum addresses.
240
+ * This returns a pseudo-address derived from the public key hash.
241
+ * The actual smart account address is determined by the account implementation.
242
+ *
243
+ * @returns A derived address (not a real EOA address)
244
+ */
245
+ async getAddress() {
246
+ // Derive an address from the public key by hashing it
247
+ // This is not a real EOA address, just an identifier
248
+ const hash = keccak256(this.publicKey);
249
+ // Take the last 20 bytes
250
+ return `0x${hash.slice(-40)}`;
251
+ }
252
+ /**
253
+ * Returns the X coordinate of the public key.
254
+ */
255
+ getPublicKeyX() {
256
+ return this.publicKeyCoordinates.x;
257
+ }
258
+ /**
259
+ * Returns the Y coordinate of the public key.
260
+ */
261
+ getPublicKeyY() {
262
+ return this.publicKeyCoordinates.y;
263
+ }
264
+ /**
265
+ * Returns the full credential data for storage/restoration.
266
+ */
267
+ getCredential() {
268
+ return {
269
+ credentialId: this.credentialId,
270
+ credentialIdHex: this.credentialIdHex,
271
+ publicKey: this.publicKeyCoordinates,
272
+ publicKeyHex: this.publicKey,
273
+ };
274
+ }
275
+ /**
276
+ * Sets the signature encoding format.
277
+ *
278
+ * @param format - The format to use for encoding signatures
279
+ * @returns A new signer instance with the updated format
280
+ */
281
+ withSignatureFormat(format) {
282
+ return new ReactNativePasskeySigner(this.getCredential(), {
283
+ ...this.config,
284
+ signatureFormat: format,
285
+ });
286
+ }
287
+ /**
288
+ * Internal method to sign a challenge with the passkey.
289
+ *
290
+ * @param challenge - The Base64URL-encoded challenge
291
+ * @returns The encoded signature
292
+ */
293
+ async signWithPasskey(challenge) {
294
+ try {
295
+ // Create assertion options
296
+ const options = createAssertionOptions(challenge, this.config.rpId, this.credentialId, this.config.userVerification, this.config.timeout);
297
+ // Call native passkey assertion
298
+ const result = await Passkey.get(options);
299
+ // Parse the assertion response
300
+ const webAuthnSignature = parseWebAuthnAssertion({
301
+ authenticatorData: result.response.authenticatorData,
302
+ clientDataJSON: result.response.clientDataJSON,
303
+ signature: result.response.signature,
304
+ });
305
+ // Encode the signature according to the configured format
306
+ return encodeWebAuthnSignature(webAuthnSignature, this.config.signatureFormat);
307
+ }
308
+ catch (error) {
309
+ if (error instanceof SignatureError) {
310
+ throw new PasskeySignerError(`Signature parsing failed: ${error.message}`, error);
311
+ }
312
+ throw new PasskeySignerError(`Passkey signing failed: ${error instanceof Error ? error.message : "Unknown error"}`, error);
313
+ }
314
+ }
315
+ /**
316
+ * Converts a hex string to Uint8Array.
317
+ */
318
+ hexToBytes(hex) {
319
+ const cleanHex = hex.startsWith("0x") ? hex.slice(2) : hex;
320
+ const bytes = new Uint8Array(cleanHex.length / 2);
321
+ for (let i = 0; i < cleanHex.length; i += 2) {
322
+ bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16);
323
+ }
324
+ return bytes;
325
+ }
326
+ }
327
+ /**
328
+ * Type guard to check if a value is a valid PasskeyCredential.
329
+ */
330
+ export function isPasskeyCredential(value) {
331
+ if (typeof value !== "object" || value === null) {
332
+ return false;
333
+ }
334
+ const obj = value;
335
+ return (typeof obj.credentialId === "string" &&
336
+ typeof obj.credentialIdHex === "string" &&
337
+ obj.credentialIdHex.startsWith("0x") &&
338
+ typeof obj.publicKey === "object" &&
339
+ obj.publicKey !== null &&
340
+ typeof obj.publicKey.x === "string" &&
341
+ typeof obj.publicKey.y === "string" &&
342
+ typeof obj.publicKeyHex === "string" &&
343
+ obj.publicKeyHex.startsWith("0x"));
344
+ }
345
+ /**
346
+ * Serializes a PasskeyCredential to a JSON-safe object.
347
+ */
348
+ export function serializeCredential(credential) {
349
+ return {
350
+ credentialId: credential.credentialId,
351
+ credentialIdHex: credential.credentialIdHex,
352
+ publicKeyX: credential.publicKey.x,
353
+ publicKeyY: credential.publicKey.y,
354
+ publicKeyHex: credential.publicKeyHex,
355
+ };
356
+ }
357
+ /**
358
+ * Deserializes a PasskeyCredential from a JSON object.
359
+ */
360
+ export function deserializeCredential(data) {
361
+ if (!data.credentialId ||
362
+ !data.credentialIdHex ||
363
+ !data.publicKeyX ||
364
+ !data.publicKeyY ||
365
+ !data.publicKeyHex) {
366
+ throw new PasskeySignerError("Invalid serialized credential data");
367
+ }
368
+ return {
369
+ credentialId: data.credentialId,
370
+ credentialIdHex: data.credentialIdHex,
371
+ publicKey: {
372
+ x: data.publicKeyX,
373
+ y: data.publicKeyY,
374
+ },
375
+ publicKeyHex: data.publicKeyHex,
376
+ };
377
+ }
378
+ //# sourceMappingURL=signer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"signer.js","sourceRoot":"","sources":["../src/signer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,117 @@
1
+ import type { Address, Hex, TypedData, TypedDataDefinition } from "viem";
2
+ /**
3
+ * Represents the source of a SmartAccountSigner - either a custom source or a known type.
4
+ */
5
+ export type SmartAccountSignerSource = "passkey" | "custom";
6
+ /**
7
+ * Interface for signing messages and typed data for Smart Accounts.
8
+ * Compatible with permissionless.js and viem account abstraction.
9
+ */
10
+ export interface SmartAccountSigner<TSource extends SmartAccountSignerSource = SmartAccountSignerSource> {
11
+ /** The type/source of the signer */
12
+ readonly source: TSource;
13
+ /** The public key associated with this signer (for passkeys, this is the encoded P256 key) */
14
+ readonly publicKey: Hex;
15
+ /**
16
+ * Signs a message and returns the signature.
17
+ * For passkeys, this triggers the biometric prompt.
18
+ */
19
+ signMessage: (params: {
20
+ message: SignableMessage;
21
+ }) => Promise<Hex>;
22
+ /**
23
+ * Signs typed data according to EIP-712 and returns the signature.
24
+ * For passkeys, this triggers the biometric prompt.
25
+ */
26
+ signTypedData: <const TTypedData extends TypedData | Record<string, unknown>, TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData>(typedData: TypedDataDefinition<TTypedData, TPrimaryType>) => Promise<Hex>;
27
+ /**
28
+ * Returns the address derived from or associated with this signer.
29
+ * For passkeys with P256 keys, this may be a derived address or the account address.
30
+ */
31
+ getAddress: () => Promise<Address>;
32
+ }
33
+ /**
34
+ * Message types that can be signed.
35
+ * Matches viem's SignableMessage type.
36
+ */
37
+ export type SignableMessage = string | {
38
+ raw: Hex | Uint8Array;
39
+ };
40
+ /**
41
+ * Configuration for WebAuthn/Passkey operations.
42
+ */
43
+ export interface PasskeyConfig {
44
+ /** The Relying Party ID (usually the domain) */
45
+ rpId: string;
46
+ /** The Relying Party name for display */
47
+ rpName: string;
48
+ /** Challenge timeout in milliseconds (default: 60000) */
49
+ timeout?: number;
50
+ /** User verification requirement */
51
+ userVerification?: "required" | "preferred" | "discouraged";
52
+ }
53
+ /**
54
+ * Represents the parsed public key coordinates from a P256/secp256r1 key.
55
+ */
56
+ export interface P256PublicKey {
57
+ /** X coordinate of the public key (32 bytes) */
58
+ x: Hex;
59
+ /** Y coordinate of the public key (32 bytes) */
60
+ y: Hex;
61
+ }
62
+ /**
63
+ * Credential data stored after passkey registration.
64
+ */
65
+ export interface PasskeyCredential {
66
+ /** The credential ID in base64url format */
67
+ credentialId: string;
68
+ /** The raw credential ID as hex */
69
+ credentialIdHex: Hex;
70
+ /** The public key coordinates */
71
+ publicKey: P256PublicKey;
72
+ /** The encoded public key for the signer interface */
73
+ publicKeyHex: Hex;
74
+ }
75
+ /**
76
+ * WebAuthn authenticator data structure.
77
+ */
78
+ export interface AuthenticatorData {
79
+ /** RP ID hash (32 bytes) */
80
+ rpIdHash: Hex;
81
+ /** Flags byte */
82
+ flags: number;
83
+ /** Sign counter */
84
+ signCount: number;
85
+ /** Raw authenticator data */
86
+ raw: Hex;
87
+ }
88
+ /**
89
+ * Parsed WebAuthn assertion response for signing.
90
+ */
91
+ export interface WebAuthnSignature {
92
+ /** Raw authenticator data */
93
+ authenticatorData: Hex;
94
+ /** Client data JSON string */
95
+ clientDataJSON: string;
96
+ /** The r component of the signature (32 bytes) */
97
+ r: Hex;
98
+ /** The s component of the signature (32 bytes) */
99
+ s: Hex;
100
+ /** Challenge location in clientDataJSON */
101
+ challengeLocation: number;
102
+ /** Response type location in clientDataJSON */
103
+ responseTypeLocation: number;
104
+ }
105
+ /**
106
+ * Options for signature encoding format.
107
+ * Different smart contract implementations expect different formats.
108
+ */
109
+ export type SignatureEncodingFormat = "kernel" | "rhinestone" | "raw";
110
+ /**
111
+ * Configuration for the ReactNativePasskeySigner.
112
+ */
113
+ export interface ReactNativePasskeySignerConfig extends PasskeyConfig {
114
+ /** The format to use when encoding signatures */
115
+ signatureFormat?: SignatureEncodingFormat;
116
+ }
117
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE5D;;;GAGG;AACH,MAAM,WAAW,kBAAkB,CACjC,OAAO,SAAS,wBAAwB,GAAG,wBAAwB;IAEnE,oCAAoC;IACpC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IAEzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,GAAG,CAAC;IAExB;;;OAGG;IACH,WAAW,EAAE,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,eAAe,CAAA;KAAE,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;IAEpE;;;OAGG;IACH,aAAa,EAAE,CACb,KAAK,CAAC,UAAU,SAAS,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5D,YAAY,SAAS,MAAM,UAAU,GAAG,cAAc,GAAG,MAAM,UAAU,EAEzE,SAAS,EAAE,mBAAmB,CAAC,UAAU,EAAE,YAAY,CAAC,KACrD,OAAO,CAAC,GAAG,CAAC,CAAC;IAElB;;;OAGG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;CACpC;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN;IACE,GAAG,EAAE,GAAG,GAAG,UAAU,CAAC;CACvB,CAAC;AAEN;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,gBAAgB,CAAC,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,CAAC;CAC7D;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,gDAAgD;IAChD,CAAC,EAAE,GAAG,CAAC;IACP,gDAAgD;IAChD,CAAC,EAAE,GAAG,CAAC;CACR;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4CAA4C;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,mCAAmC;IACnC,eAAe,EAAE,GAAG,CAAC;IACrB,iCAAiC;IACjC,SAAS,EAAE,aAAa,CAAC;IACzB,sDAAsD;IACtD,YAAY,EAAE,GAAG,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,4BAA4B;IAC5B,QAAQ,EAAE,GAAG,CAAC;IACd,iBAAiB;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,mBAAmB;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,6BAA6B;IAC7B,GAAG,EAAE,GAAG,CAAC;CACV;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6BAA6B;IAC7B,iBAAiB,EAAE,GAAG,CAAC;IACvB,8BAA8B;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,kDAAkD;IAClD,CAAC,EAAE,GAAG,CAAC;IACP,kDAAkD;IAClD,CAAC,EAAE,GAAG,CAAC;IACP,2CAA2C;IAC3C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,+CAA+C;IAC/C,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,MAAM,MAAM,uBAAuB,GAC/B,QAAQ,GACR,YAAY,GACZ,KAAK,CAAC;AAEV;;GAEG;AACH,MAAM,WAAW,8BAA+B,SAAQ,aAAa;IACnE,iDAAiD;IACjD,eAAe,CAAC,EAAE,uBAAuB,CAAC;CAC3C"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,75 @@
1
+ import { type Hex } from "viem";
2
+ /**
3
+ * Converts a Base64URL encoded string to a Uint8Array.
4
+ * Base64URL uses - instead of + and _ instead of /, with no padding.
5
+ *
6
+ * @param base64url - The Base64URL encoded string
7
+ * @returns The decoded bytes as Uint8Array
8
+ */
9
+ export declare function base64UrlToBytes(base64url: string): Uint8Array;
10
+ /**
11
+ * Converts a Uint8Array to a Base64URL encoded string.
12
+ *
13
+ * @param bytes - The bytes to encode
14
+ * @returns The Base64URL encoded string (no padding)
15
+ */
16
+ export declare function bytesToBase64Url(bytes: Uint8Array): string;
17
+ /**
18
+ * Converts a Base64URL encoded string to a Hex string.
19
+ *
20
+ * @param base64url - The Base64URL encoded string
21
+ * @returns The hex representation with 0x prefix
22
+ */
23
+ export declare function base64UrlToHex(base64url: string): Hex;
24
+ /**
25
+ * Converts a Hex string to a Base64URL encoded string.
26
+ *
27
+ * @param hex - The hex string (with or without 0x prefix)
28
+ * @returns The Base64URL encoded string
29
+ */
30
+ export declare function hexToBase64Url(hex: Hex): string;
31
+ /**
32
+ * Converts a Uint8Array to a Hex string.
33
+ *
34
+ * @param bytes - The bytes to convert
35
+ * @returns The hex representation with 0x prefix
36
+ */
37
+ export declare function bytesToHex(bytes: Uint8Array): Hex;
38
+ /**
39
+ * Converts a Hex string to a Uint8Array.
40
+ *
41
+ * @param hex - The hex string (with or without 0x prefix)
42
+ * @returns The bytes as Uint8Array
43
+ */
44
+ export declare function hexToBytes(hex: Hex): Uint8Array;
45
+ /**
46
+ * Converts a UTF-8 string to a Base64URL encoded string.
47
+ *
48
+ * @param str - The UTF-8 string
49
+ * @returns The Base64URL encoded string
50
+ */
51
+ export declare function stringToBase64Url(str: string): string;
52
+ /**
53
+ * Converts a Base64URL encoded string to a UTF-8 string.
54
+ *
55
+ * @param base64url - The Base64URL encoded string
56
+ * @returns The decoded UTF-8 string
57
+ */
58
+ export declare function base64UrlToString(base64url: string): string;
59
+ /**
60
+ * Pads a hex value to ensure it has the specified byte length.
61
+ * Useful for ensuring coordinates are 32 bytes.
62
+ *
63
+ * @param hex - The hex string to pad
64
+ * @param byteLength - The desired byte length (default: 32)
65
+ * @returns The padded hex string with 0x prefix
66
+ */
67
+ export declare function padHex(hex: Hex, byteLength?: number): Hex;
68
+ /**
69
+ * Concatenates multiple Hex values into a single Hex value.
70
+ *
71
+ * @param hexValues - The hex values to concatenate
72
+ * @returns The concatenated hex string with 0x prefix
73
+ */
74
+ export declare function concatHex(...hexValues: Hex[]): Hex;
75
+ //# sourceMappingURL=base64url.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base64url.d.ts","sourceRoot":"","sources":["../../src/utils/base64url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAEvC;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,CAoB9D;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAY1D;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,GAAG,CAGrD;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAW/C;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,UAAU,GAAG,GAAG,CAEjD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,GAAG,GAAG,UAAU,CAO/C;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAIrD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAI3D;AAED;;;;;;;GAOG;AACH,wBAAgB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,UAAU,SAAK,GAAG,GAAG,CASrD;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,GAAG,SAAS,EAAE,GAAG,EAAE,GAAG,GAAG,CAKlD"}