@stellar-snaps/sdk 0.1.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,521 @@
1
+ import * as StellarSdk from '@stellar/stellar-sdk';
2
+
3
+ interface PaymentSnapOptions {
4
+ destination: string;
5
+ amount?: string;
6
+ assetCode?: string;
7
+ assetIssuer?: string;
8
+ memo?: string;
9
+ memoType?: 'MEMO_TEXT' | 'MEMO_ID' | 'MEMO_HASH' | 'MEMO_RETURN';
10
+ message?: string;
11
+ network?: 'public' | 'testnet';
12
+ callback?: string;
13
+ }
14
+ interface PaymentSnapResult {
15
+ uri: string;
16
+ params: Record<string, string>;
17
+ }
18
+ declare function createPaymentSnap(options: PaymentSnapOptions): PaymentSnapResult;
19
+
20
+ /**
21
+ * Stellar network passphrases used for transaction signing.
22
+ * Each network has a unique passphrase that identifies it.
23
+ */
24
+ declare const NETWORK_PASSPHRASES: {
25
+ readonly public: "Public Global Stellar Network ; September 2015";
26
+ readonly testnet: "Test SDF Network ; September 2015";
27
+ };
28
+ /**
29
+ * Horizon API URLs for each Stellar network.
30
+ * Horizon is the REST API for interacting with the Stellar network.
31
+ */
32
+ declare const HORIZON_URLS: {
33
+ readonly public: "https://horizon.stellar.org";
34
+ readonly testnet: "https://horizon-testnet.stellar.org";
35
+ };
36
+ /**
37
+ * Supported Stellar networks.
38
+ * - `public`: The main Stellar network (real money)
39
+ * - `testnet`: Test network for development (free test tokens)
40
+ */
41
+ type Network = 'public' | 'testnet';
42
+ /**
43
+ * Stellar memo types for attaching metadata to transactions.
44
+ * - `MEMO_TEXT`: Plain text (max 28 bytes)
45
+ * - `MEMO_ID`: 64-bit unsigned integer
46
+ * - `MEMO_HASH`: 32-byte hash
47
+ * - `MEMO_RETURN`: 32-byte hash (for returning payments)
48
+ */
49
+ type MemoType = 'MEMO_TEXT' | 'MEMO_ID' | 'MEMO_HASH' | 'MEMO_RETURN';
50
+
51
+ /**
52
+ * Options for creating a transaction snap URI.
53
+ * Used for advanced use cases where you need to sign arbitrary transactions,
54
+ * not just simple payments.
55
+ */
56
+ interface TransactionSnapOptions {
57
+ /** The transaction in XDR format (Stellar's binary encoding) */
58
+ xdr: string;
59
+ /** The network this transaction is for (default: 'public') */
60
+ network?: Network;
61
+ /** Human-readable message to show the user when signing */
62
+ message?: string;
63
+ /** URL to call after the transaction is signed */
64
+ callback?: string;
65
+ /** Public key of the required signer */
66
+ pubkey?: string;
67
+ }
68
+ /**
69
+ * Result of creating a transaction snap.
70
+ */
71
+ interface TransactionSnapResult {
72
+ /** The complete SEP-0007 URI */
73
+ uri: string;
74
+ /** The parsed parameters */
75
+ params: Record<string, string>;
76
+ }
77
+ /**
78
+ * Creates a SEP-0007 transaction URI for signing arbitrary Stellar transactions.
79
+ *
80
+ * Unlike payment snaps which are for simple payments, transaction snaps can
81
+ * encode any Stellar transaction (multi-operation, account creation, etc.).
82
+ *
83
+ * @param options - Transaction snap configuration
84
+ * @returns The generated URI and parsed parameters
85
+ * @throws {InvalidUriError} If the XDR is missing or invalid
86
+ *
87
+ * @example
88
+ * ```typescript
89
+ * const { uri } = createTransactionSnap({
90
+ * xdr: 'AAAA...', // Your transaction XDR
91
+ * network: 'testnet',
92
+ * message: 'Please sign this transaction',
93
+ * });
94
+ * // => web+stellar:tx?xdr=AAAA...&network_passphrase=Test%20SDF%20Network...
95
+ * ```
96
+ */
97
+ declare function createTransactionSnap(options: TransactionSnapOptions): TransactionSnapResult;
98
+
99
+ interface ParsedSnap {
100
+ type: 'pay' | 'tx';
101
+ destination?: string;
102
+ amount?: string;
103
+ assetCode?: string;
104
+ assetIssuer?: string;
105
+ memo?: string;
106
+ memoType?: string;
107
+ message?: string;
108
+ networkPassphrase?: string;
109
+ callback?: string;
110
+ xdr?: string;
111
+ }
112
+ declare function parseSnapUri(uri: string): ParsedSnap;
113
+
114
+ /**
115
+ * Validates a Stellar public address.
116
+ * Valid addresses are 56 characters long and start with 'G'.
117
+ *
118
+ * @param address - The address to validate
119
+ * @returns true if the address is valid
120
+ *
121
+ * @example
122
+ * ```typescript
123
+ * isValidStellarAddress('GDQP2KPQGKIHYJGXNUIYOMHARUARCA7DJT5FO2FFOOUJ3DTJE4QRK764');
124
+ * // => true
125
+ *
126
+ * isValidStellarAddress('invalid');
127
+ * // => false
128
+ * ```
129
+ */
130
+ declare function isValidStellarAddress(address: string): boolean;
131
+ /**
132
+ * Validates a Stellar asset code.
133
+ * Asset codes are 1-12 alphanumeric characters.
134
+ * "XLM" is the native asset and is always valid.
135
+ *
136
+ * @param code - The asset code to validate
137
+ * @returns true if the asset code is valid
138
+ *
139
+ * @example
140
+ * ```typescript
141
+ * isValidAssetCode('USDC');
142
+ * // => true
143
+ *
144
+ * isValidAssetCode('XLM');
145
+ * // => true
146
+ *
147
+ * isValidAssetCode('ThisIsTooLongForAnAssetCode');
148
+ * // => false
149
+ * ```
150
+ */
151
+ declare function isValidAssetCode(code: string): boolean;
152
+ /**
153
+ * Validates a payment amount.
154
+ * Amounts must be positive numbers represented as strings.
155
+ * Stellar supports up to 7 decimal places.
156
+ *
157
+ * @param amount - The amount to validate
158
+ * @returns true if the amount is valid
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * isValidAmount('10');
163
+ * // => true
164
+ *
165
+ * isValidAmount('0.0000001');
166
+ * // => true
167
+ *
168
+ * isValidAmount('-5');
169
+ * // => false
170
+ *
171
+ * isValidAmount('0');
172
+ * // => false
173
+ * ```
174
+ */
175
+ declare function isValidAmount(amount: string): boolean;
176
+
177
+ /**
178
+ * Options for building a payment transaction.
179
+ */
180
+ interface BuildPaymentOptions {
181
+ /** The payer's Stellar public address */
182
+ source: string;
183
+ /** The account sequence number (prevents replay attacks) */
184
+ sequence: string;
185
+ /** The recipient's Stellar public address */
186
+ destination: string;
187
+ /** The amount to send (as a string for precision) */
188
+ amount: string;
189
+ /** The asset to send (defaults to XLM if not specified) */
190
+ asset?: {
191
+ /** Asset code, e.g., "USDC", "XLM" */
192
+ code: string;
193
+ /** Asset issuer address (required for non-XLM assets) */
194
+ issuer?: string;
195
+ };
196
+ /** Optional memo to attach to the transaction */
197
+ memo?: {
198
+ /** The memo type */
199
+ type: MemoType;
200
+ /** The memo value */
201
+ value: string;
202
+ };
203
+ /** The network to build for */
204
+ network: Network;
205
+ /** Transaction validity timeout in seconds (default: 180) */
206
+ timeout?: number;
207
+ }
208
+ /**
209
+ * Creates a Stellar Asset object.
210
+ *
211
+ * @param code - The asset code (e.g., "XLM", "USDC")
212
+ * @param issuer - The asset issuer address (required for non-XLM assets)
213
+ * @returns A Stellar Asset object
214
+ * @throws {InvalidAssetError} If a non-XLM asset is missing an issuer
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * // Native XLM
219
+ * const xlm = createAsset('XLM');
220
+ *
221
+ * // Custom asset
222
+ * const usdc = createAsset('USDC', 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN');
223
+ * ```
224
+ */
225
+ declare function createAsset(code: string, issuer?: string): StellarSdk.Asset;
226
+ /**
227
+ * Builds a Stellar payment transaction and returns the XDR.
228
+ *
229
+ * This function creates a complete unsigned transaction that can be
230
+ * signed by a wallet like Freighter.
231
+ *
232
+ * @param options - The payment options
233
+ * @returns The transaction XDR string
234
+ * @throws {InvalidAddressError} If source or destination address is invalid
235
+ * @throws {InvalidAmountError} If amount is invalid
236
+ * @throws {InvalidAssetError} If asset configuration is invalid
237
+ *
238
+ * @example
239
+ * ```typescript
240
+ * const xdr = buildPaymentTransaction({
241
+ * source: 'GDQP2K...',
242
+ * sequence: '123456789',
243
+ * destination: 'GBZX...',
244
+ * amount: '10.5',
245
+ * asset: { code: 'USDC', issuer: 'GA5ZS...' },
246
+ * memo: { type: 'MEMO_TEXT', value: 'Payment for coffee' },
247
+ * network: 'public',
248
+ * });
249
+ * ```
250
+ */
251
+ declare function buildPaymentTransaction(options: BuildPaymentOptions): string;
252
+
253
+ /**
254
+ * Result of connecting to Freighter wallet.
255
+ */
256
+ interface FreighterConnectionResult {
257
+ /** The user's Stellar public address */
258
+ publicKey: string;
259
+ /** The network the wallet is connected to */
260
+ network: Network;
261
+ }
262
+ /**
263
+ * Result of submitting a transaction.
264
+ */
265
+ interface TransactionSubmitResult {
266
+ /** The transaction hash (can be used in block explorers) */
267
+ hash: string;
268
+ /** Whether the transaction was successful */
269
+ successful: boolean;
270
+ /** The ledger number the transaction was included in */
271
+ ledger?: number;
272
+ }
273
+ /**
274
+ * Checks if Freighter wallet extension is installed and connected.
275
+ *
276
+ * @returns true if Freighter is installed and the user has granted access
277
+ *
278
+ * @example
279
+ * ```typescript
280
+ * if (await isFreighterConnected()) {
281
+ * console.log('Ready to sign transactions!');
282
+ * } else {
283
+ * console.log('Please connect your Freighter wallet');
284
+ * }
285
+ * ```
286
+ */
287
+ declare function isFreighterConnected(): Promise<boolean>;
288
+ /**
289
+ * Gets the current network from Freighter wallet.
290
+ *
291
+ * @returns The network the user's wallet is connected to
292
+ * @throws {StellarSnapError} If unable to get network
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * const network = await getFreighterNetwork();
297
+ * console.log(`Connected to ${network}`); // 'public' or 'testnet'
298
+ * ```
299
+ */
300
+ declare function getFreighterNetwork(): Promise<Network>;
301
+ /**
302
+ * Connects to the Freighter wallet and returns the user's public key and network.
303
+ *
304
+ * This will prompt the user to grant access if they haven't already.
305
+ *
306
+ * @returns The user's public key and current network
307
+ * @throws {StellarSnapError} If Freighter is not installed or connection fails
308
+ *
309
+ * @example
310
+ * ```typescript
311
+ * try {
312
+ * const { publicKey, network } = await connectFreighter();
313
+ * console.log(`Connected: ${publicKey} on ${network}`);
314
+ * } catch (error) {
315
+ * console.error('Failed to connect:', error.message);
316
+ * }
317
+ * ```
318
+ */
319
+ declare function connectFreighter(): Promise<FreighterConnectionResult>;
320
+ /**
321
+ * Signs a transaction using Freighter wallet.
322
+ *
323
+ * This will open the Freighter popup for the user to review and approve the transaction.
324
+ *
325
+ * @param xdr - The unsigned transaction XDR
326
+ * @param network - The network the transaction is for
327
+ * @returns The signed transaction XDR
328
+ * @throws {StellarSnapError} If signing fails or user rejects
329
+ *
330
+ * @example
331
+ * ```typescript
332
+ * const unsignedXdr = buildPaymentTransaction({ ... });
333
+ * const signedXdr = await signWithFreighter(unsignedXdr, 'public');
334
+ * ```
335
+ */
336
+ declare function signWithFreighter(xdr: string, network: Network): Promise<string>;
337
+ /**
338
+ * Submits a signed transaction to the Stellar network.
339
+ *
340
+ * @param signedXdr - The signed transaction XDR
341
+ * @param network - The network to submit to
342
+ * @returns The transaction result including hash and success status
343
+ * @throws {StellarSnapError} If submission fails
344
+ *
345
+ * @example
346
+ * ```typescript
347
+ * const signedXdr = await signWithFreighter(unsignedXdr, 'public');
348
+ * const result = await submitTransaction(signedXdr, 'public');
349
+ *
350
+ * if (result.successful) {
351
+ * console.log(`Transaction successful! Hash: ${result.hash}`);
352
+ * console.log(`View on explorer: https://stellar.expert/explorer/public/tx/${result.hash}`);
353
+ * }
354
+ * ```
355
+ */
356
+ declare function submitTransaction(signedXdr: string, network: Network): Promise<TransactionSubmitResult>;
357
+
358
+ /**
359
+ * A rule for matching URL paths to API endpoints.
360
+ */
361
+ interface DiscoveryRule {
362
+ /**
363
+ * URL path pattern with wildcards.
364
+ * Use `*` as a wildcard that matches any characters.
365
+ *
366
+ * @example "/s/*" matches "/s/abc123"
367
+ * @example "/pay/*" matches "/pay/user123"
368
+ */
369
+ pathPattern: string;
370
+ /**
371
+ * API endpoint path template.
372
+ * Use `$1`, `$2`, etc. to insert captured wildcards.
373
+ *
374
+ * @example "/api/snap/$1" with pathPattern "/s/*" and URL "/s/abc"
375
+ * resolves to "/api/snap/abc"
376
+ */
377
+ apiPath: string;
378
+ }
379
+ /**
380
+ * Discovery file structure for Stellar Snaps.
381
+ *
382
+ * This file should be hosted at `/.well-known/stellar-snap.json` on your domain
383
+ * to enable the browser extension to discover and render your snaps.
384
+ */
385
+ interface DiscoveryFile {
386
+ /** The name of your application */
387
+ name: string;
388
+ /** A short description of your application */
389
+ description?: string;
390
+ /** URL to your application's icon (recommended: 128x128 PNG) */
391
+ icon?: string;
392
+ /** Rules for matching URLs to snap metadata endpoints */
393
+ rules: DiscoveryRule[];
394
+ }
395
+ /**
396
+ * Options for creating a discovery file.
397
+ */
398
+ interface CreateDiscoveryFileOptions {
399
+ /** The name of your application */
400
+ name: string;
401
+ /** A short description of your application */
402
+ description?: string;
403
+ /** URL to your application's icon */
404
+ icon?: string;
405
+ /** Rules for matching URLs to snap metadata endpoints */
406
+ rules: DiscoveryRule[];
407
+ }
408
+ /**
409
+ * Creates a valid discovery file object.
410
+ *
411
+ * Use this to generate the JSON that should be hosted at
412
+ * `/.well-known/stellar-snap.json` on your domain.
413
+ *
414
+ * @param options - The discovery file configuration
415
+ * @returns A valid DiscoveryFile object
416
+ *
417
+ * @example
418
+ * ```typescript
419
+ * const discovery = createDiscoveryFile({
420
+ * name: 'My Payment App',
421
+ * description: 'Accept Stellar payments easily',
422
+ * rules: [
423
+ * { pathPattern: '/pay/*', apiPath: '/api/snap/$1' },
424
+ * { pathPattern: '/donate/*', apiPath: '/api/donation/$1' },
425
+ * ],
426
+ * });
427
+ *
428
+ * // Save as /.well-known/stellar-snap.json
429
+ * fs.writeFileSync(
430
+ * 'public/.well-known/stellar-snap.json',
431
+ * JSON.stringify(discovery, null, 2)
432
+ * );
433
+ * ```
434
+ */
435
+ declare function createDiscoveryFile(options: CreateDiscoveryFileOptions): DiscoveryFile;
436
+ /**
437
+ * Validates that an unknown object is a valid discovery file.
438
+ *
439
+ * Use this to validate discovery files fetched from other domains.
440
+ *
441
+ * @param file - The object to validate
442
+ * @returns true if the object is a valid DiscoveryFile
443
+ *
444
+ * @example
445
+ * ```typescript
446
+ * const response = await fetch('https://example.com/.well-known/stellar-snap.json');
447
+ * const data = await response.json();
448
+ *
449
+ * if (validateDiscoveryFile(data)) {
450
+ * console.log('Valid discovery file:', data.name);
451
+ * } else {
452
+ * console.error('Invalid discovery file');
453
+ * }
454
+ * ```
455
+ */
456
+ declare function validateDiscoveryFile(file: unknown): file is DiscoveryFile;
457
+ /**
458
+ * Matches a URL pathname against discovery rules and returns the API path.
459
+ *
460
+ * This is used to find which API endpoint to call for a given URL.
461
+ *
462
+ * @param pathname - The URL pathname to match (e.g., "/s/abc123")
463
+ * @param rules - The discovery rules to match against
464
+ * @returns The resolved API path, or null if no match
465
+ *
466
+ * @example
467
+ * ```typescript
468
+ * const rules = [
469
+ * { pathPattern: '/s/*', apiPath: '/api/snap/$1' },
470
+ * { pathPattern: '/pay/*', apiPath: '/api/payment/$1' },
471
+ * ];
472
+ *
473
+ * matchUrlToRule('/s/abc123', rules);
474
+ * // => '/api/snap/abc123'
475
+ *
476
+ * matchUrlToRule('/pay/user456', rules);
477
+ * // => '/api/payment/user456'
478
+ *
479
+ * matchUrlToRule('/unknown/path', rules);
480
+ * // => null
481
+ * ```
482
+ */
483
+ declare function matchUrlToRule(pathname: string, rules: DiscoveryRule[]): string | null;
484
+
485
+ /**
486
+ * Base error class for all Stellar Snaps SDK errors.
487
+ * Includes an error code for programmatic error handling.
488
+ */
489
+ declare class StellarSnapError extends Error {
490
+ code: string;
491
+ constructor(message: string, code: string);
492
+ }
493
+ /**
494
+ * Thrown when a Stellar address is invalid.
495
+ * Valid addresses are 56 characters long and start with 'G'.
496
+ */
497
+ declare class InvalidAddressError extends StellarSnapError {
498
+ constructor(address: string);
499
+ }
500
+ /**
501
+ * Thrown when an amount is invalid.
502
+ * Amounts must be positive numbers represented as strings.
503
+ */
504
+ declare class InvalidAmountError extends StellarSnapError {
505
+ constructor(amount: string);
506
+ }
507
+ /**
508
+ * Thrown when an asset configuration is invalid.
509
+ * Non-XLM assets require both a code and an issuer address.
510
+ */
511
+ declare class InvalidAssetError extends StellarSnapError {
512
+ constructor(message: string);
513
+ }
514
+ /**
515
+ * Thrown when a SEP-0007 URI is invalid or malformed.
516
+ */
517
+ declare class InvalidUriError extends StellarSnapError {
518
+ constructor(message: string);
519
+ }
520
+
521
+ export { type BuildPaymentOptions, type CreateDiscoveryFileOptions, type DiscoveryFile, type DiscoveryRule, type FreighterConnectionResult, HORIZON_URLS, InvalidAddressError, InvalidAmountError, InvalidAssetError, InvalidUriError, type MemoType, NETWORK_PASSPHRASES, type Network, type ParsedSnap, type PaymentSnapOptions, type PaymentSnapResult, StellarSnapError, type TransactionSnapOptions, type TransactionSnapResult, type TransactionSubmitResult, buildPaymentTransaction, connectFreighter, createAsset, createDiscoveryFile, createPaymentSnap, createTransactionSnap, getFreighterNetwork, isFreighterConnected, isValidAmount, isValidAssetCode, isValidStellarAddress, matchUrlToRule, parseSnapUri, signWithFreighter, submitTransaction, validateDiscoveryFile };