@stellar-snaps/sdk 0.3.0 → 0.3.2

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/index.mjs CHANGED
@@ -1,8 +1,62 @@
1
1
  import * as StellarSdk from '@stellar/stellar-sdk';
2
2
  import { isConnected, isAllowed, getNetwork, setAllowed, getAddress, signTransaction } from '@stellar/freighter-api';
3
3
 
4
+ // src/errors.ts
5
+ var StellarSnapError = class extends Error {
6
+ constructor(message, code) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = "StellarSnapError";
10
+ }
11
+ };
12
+ var InvalidAddressError = class extends StellarSnapError {
13
+ constructor(address) {
14
+ super(`Invalid Stellar address: ${address}`, "INVALID_ADDRESS");
15
+ this.name = "InvalidAddressError";
16
+ }
17
+ };
18
+ var InvalidAmountError = class extends StellarSnapError {
19
+ constructor(amount) {
20
+ super(`Invalid amount: ${amount}. Must be a positive number.`, "INVALID_AMOUNT");
21
+ this.name = "InvalidAmountError";
22
+ }
23
+ };
24
+ var InvalidAssetError = class extends StellarSnapError {
25
+ constructor(message) {
26
+ super(message, "INVALID_ASSET");
27
+ this.name = "InvalidAssetError";
28
+ }
29
+ };
30
+ var InvalidUriError = class extends StellarSnapError {
31
+ constructor(message) {
32
+ super(message, "INVALID_URI");
33
+ this.name = "InvalidUriError";
34
+ }
35
+ };
36
+ var SnapNotFoundError = class extends StellarSnapError {
37
+ constructor(snapId) {
38
+ super(`Snap not found: ${snapId}`, "SNAP_NOT_FOUND");
39
+ this.name = "SnapNotFoundError";
40
+ }
41
+ };
42
+ var SnapUnauthorizedError = class extends StellarSnapError {
43
+ constructor(message = "Unauthorized") {
44
+ super(message, "SNAP_UNAUTHORIZED");
45
+ this.name = "SnapUnauthorizedError";
46
+ }
47
+ };
48
+ var SnapApiError = class extends StellarSnapError {
49
+ constructor(message, statusCode) {
50
+ super(message, "SNAP_API_ERROR");
51
+ this.statusCode = statusCode;
52
+ this.name = "SnapApiError";
53
+ }
54
+ };
55
+
4
56
  // src/create-snap.ts
57
+ var DEFAULT_BASE_URL = "https://stellar-snaps.vercel.app";
5
58
  async function createSnap(options) {
59
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
6
60
  const {
7
61
  creator,
8
62
  title,
@@ -14,20 +68,19 @@ async function createSnap(options) {
14
68
  memo,
15
69
  memoType = "MEMO_TEXT",
16
70
  network = "testnet",
17
- imageUrl,
18
- serverUrl = "https://stellarsnaps.com"
71
+ imageUrl
19
72
  } = options;
20
73
  if (!creator || creator.length !== 56 || !creator.startsWith("G")) {
21
- throw new Error("Invalid creator address");
74
+ throw new InvalidAddressError(creator || "");
22
75
  }
23
76
  if (!title || title.trim().length === 0) {
24
- throw new Error("Title is required");
77
+ throw new SnapApiError("Title is required");
25
78
  }
26
79
  if (!destination || destination.length !== 56 || !destination.startsWith("G")) {
27
- throw new Error("Invalid destination address");
80
+ throw new InvalidAddressError(destination || "");
28
81
  }
29
82
  if (assetCode !== "XLM" && !assetIssuer) {
30
- throw new Error("Asset issuer is required for non-XLM assets");
83
+ throw new SnapApiError("Asset issuer is required for non-XLM assets");
31
84
  }
32
85
  const body = {
33
86
  creator,
@@ -42,53 +95,133 @@ async function createSnap(options) {
42
95
  network,
43
96
  imageUrl
44
97
  };
45
- const response = await fetch(`${serverUrl}/api/snaps`, {
98
+ const response = await fetch(`${baseUrl}/api/snaps`, {
46
99
  method: "POST",
47
- headers: {
48
- "Content-Type": "application/json"
49
- },
100
+ headers: { "Content-Type": "application/json" },
50
101
  body: JSON.stringify(body)
51
102
  });
52
103
  if (!response.ok) {
53
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
54
- throw new Error(error.error || `Failed to create snap: ${response.status}`);
104
+ const data = await response.json().catch(() => ({ error: "Unknown error" }));
105
+ const message = data.error || `Failed to create snap: ${response.status}`;
106
+ throw new SnapApiError(message, response.status);
55
107
  }
56
108
  const snap = await response.json();
57
109
  return {
58
110
  id: snap.id,
59
- url: `${serverUrl}/s/${snap.id}`,
111
+ url: `${baseUrl}/s/${snap.id}`,
60
112
  snap
61
113
  };
62
114
  }
63
115
  async function getSnap(id, options = {}) {
64
- const { serverUrl = "https://stellarsnaps.com" } = options;
65
- const response = await fetch(`${serverUrl}/api/snaps/${id}`);
116
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
117
+ const response = await fetch(`${baseUrl}/api/snap/${id}`);
66
118
  if (response.status === 404) {
67
- return null;
119
+ throw new SnapNotFoundError(id);
68
120
  }
69
121
  if (!response.ok) {
70
- throw new Error(`Failed to fetch snap: ${response.status}`);
122
+ const data = await response.json().catch(() => ({}));
123
+ const message = data.error || `Failed to fetch snap: ${response.status}`;
124
+ throw new SnapApiError(message, response.status);
71
125
  }
72
126
  return response.json();
73
127
  }
74
128
  async function listSnaps(creator, options = {}) {
75
- const { serverUrl = "https://stellarsnaps.com" } = options;
76
- const response = await fetch(`${serverUrl}/api/snaps?creator=${encodeURIComponent(creator)}`);
129
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
130
+ const response = await fetch(
131
+ `${baseUrl}/api/snaps?creator=${encodeURIComponent(creator)}`
132
+ );
77
133
  if (!response.ok) {
78
- throw new Error(`Failed to list snaps: ${response.status}`);
134
+ const data = await response.json().catch(() => ({}));
135
+ const message = data.error || `Failed to list snaps: ${response.status}`;
136
+ throw new SnapApiError(message, response.status);
79
137
  }
80
138
  return response.json();
81
139
  }
82
- async function deleteSnap(id, options = {}) {
83
- const { serverUrl = "https://stellarsnaps.com" } = options;
84
- const response = await fetch(`${serverUrl}/api/snaps/${id}`, {
85
- method: "DELETE"
86
- });
87
- if (!response.ok && response.status !== 404) {
88
- throw new Error(`Failed to delete snap: ${response.status}`);
140
+ async function deleteSnap(id, creator, options = {}) {
141
+ const baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
142
+ const url = `${baseUrl}/api/snaps?id=${encodeURIComponent(id)}&creator=${encodeURIComponent(creator)}`;
143
+ const response = await fetch(url, { method: "DELETE" });
144
+ if (response.status === 404) {
145
+ throw new SnapNotFoundError(id);
146
+ }
147
+ if (response.status === 403) {
148
+ throw new SnapUnauthorizedError("You do not have permission to delete this snap");
149
+ }
150
+ if (!response.ok) {
151
+ const data = await response.json().catch(() => ({}));
152
+ const message = data.error || `Failed to delete snap: ${response.status}`;
153
+ throw new SnapApiError(message, response.status);
89
154
  }
90
155
  }
91
156
 
157
+ // src/snap-modal.ts
158
+ var MODAL_ID = "stellar-snap-modal";
159
+ var IFRAME_ID = "stellar-snap-modal-iframe";
160
+ function isBrowser() {
161
+ return typeof document !== "undefined" && typeof window !== "undefined";
162
+ }
163
+ function openSnapModal(snapUrl, options = {}) {
164
+ if (!isBrowser()) return;
165
+ closeSnapModal();
166
+ const { width = 420, height = 560, onClose } = options;
167
+ const overlay = document.createElement("div");
168
+ overlay.id = MODAL_ID;
169
+ overlay.setAttribute("role", "dialog");
170
+ overlay.setAttribute("aria-modal", "true");
171
+ overlay.setAttribute("aria-label", "Stellar Snap payment");
172
+ const styles = {
173
+ position: "fixed",
174
+ inset: "0",
175
+ zIndex: "2147483647",
176
+ display: "flex",
177
+ alignItems: "center",
178
+ justifyContent: "center",
179
+ backgroundColor: "rgba(0, 0, 0, 0.6)",
180
+ padding: "20px",
181
+ boxSizing: "border-box"
182
+ };
183
+ Object.assign(overlay.style, styles);
184
+ const container = document.createElement("div");
185
+ container.style.position = "relative";
186
+ container.style.width = `${width}px`;
187
+ container.style.maxWidth = "100%";
188
+ container.style.height = `${height}px`;
189
+ container.style.maxHeight = "90vh";
190
+ container.style.backgroundColor = "rgb(23, 23, 23)";
191
+ container.style.borderRadius = "16px";
192
+ container.style.boxShadow = "0 25px 50px -12px rgba(0, 0, 0, 0.5)";
193
+ container.style.overflow = "hidden";
194
+ const closeBtn = document.createElement("button");
195
+ closeBtn.type = "button";
196
+ closeBtn.setAttribute("aria-label", "Close");
197
+ closeBtn.textContent = "\xD7";
198
+ closeBtn.style.cssText = "position:absolute;top:12px;right:12px;z-index:10;width:32px;height:32px;border:none;border-radius:8px;background:rgba(255,255,255,0.1);color:#e5e5e5;font-size:24px;line-height:1;cursor:pointer;display:flex;align-items:center;justify-content:center;";
199
+ closeBtn.onclick = () => {
200
+ closeSnapModal();
201
+ onClose?.();
202
+ };
203
+ const iframe = document.createElement("iframe");
204
+ iframe.id = IFRAME_ID;
205
+ iframe.src = snapUrl;
206
+ iframe.title = "Stellar Snap payment";
207
+ iframe.style.cssText = "width:100%;height:100%;border:none;border-radius:16px;";
208
+ container.appendChild(closeBtn);
209
+ container.appendChild(iframe);
210
+ overlay.appendChild(container);
211
+ overlay.addEventListener("click", (e) => {
212
+ if (e.target === overlay) {
213
+ closeSnapModal();
214
+ onClose?.();
215
+ }
216
+ });
217
+ document.body.appendChild(overlay);
218
+ }
219
+ function closeSnapModal() {
220
+ if (!isBrowser()) return;
221
+ const el = document.getElementById(MODAL_ID);
222
+ if (el) el.remove();
223
+ }
224
+
92
225
  // src/snap-id.ts
93
226
  var ALPHABET = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";
94
227
  function generateSnapId(length = 8) {
@@ -295,39 +428,6 @@ var HORIZON_URLS = {
295
428
  testnet: "https://horizon-testnet.stellar.org"
296
429
  };
297
430
 
298
- // src/errors.ts
299
- var StellarSnapError = class extends Error {
300
- constructor(message, code) {
301
- super(message);
302
- this.code = code;
303
- this.name = "StellarSnapError";
304
- }
305
- };
306
- var InvalidAddressError = class extends StellarSnapError {
307
- constructor(address) {
308
- super(`Invalid Stellar address: ${address}`, "INVALID_ADDRESS");
309
- this.name = "InvalidAddressError";
310
- }
311
- };
312
- var InvalidAmountError = class extends StellarSnapError {
313
- constructor(amount) {
314
- super(`Invalid amount: ${amount}. Must be a positive number.`, "INVALID_AMOUNT");
315
- this.name = "InvalidAmountError";
316
- }
317
- };
318
- var InvalidAssetError = class extends StellarSnapError {
319
- constructor(message) {
320
- super(message, "INVALID_ASSET");
321
- this.name = "InvalidAssetError";
322
- }
323
- };
324
- var InvalidUriError = class extends StellarSnapError {
325
- constructor(message) {
326
- super(message, "INVALID_URI");
327
- this.name = "InvalidUriError";
328
- }
329
- };
330
-
331
431
  // src/create-transaction-snap.ts
332
432
  function createTransactionSnap(options) {
333
433
  const { xdr, network = "public", message, callback, pubkey } = options;
@@ -1132,6 +1232,6 @@ function parseAddress(input) {
1132
1232
  throw new Error("Invalid address format");
1133
1233
  }
1134
1234
 
1135
- export { CACHE_HEADERS, CORS_HEADERS, EXPLORER_URLS, HORIZON_URLS, InvalidAddressError, InvalidAmountError, InvalidAssetError, InvalidUriError, NETWORK_PASSPHRASES2 as NETWORK_PASSPHRASES, POSTGRES_SCHEMA, SHORTENER_DOMAINS, SQLITE_SCHEMA, StellarSnapError, addDomain, buildPaymentTransaction, buildUrl, connectFreighter, createAsset, createDiscoveryFile, createPaymentSnap, createRateLimiter, createRegistry, createSnap, createSnapObject, createTransactionSnap, deleteSnap, errorResponse, extractDomain, extractPath, extractSnapId, generateJsonLd, generateMetaTags, generateSnapId, getAccountUrl, getAssetUrl, getBlockedDomains, getDomainStatus, getFreighterNetwork, getOperationUrl, getSnap, getTransactionUrl, getVerifiedDomains, isDomainBlocked, isDomainVerified, isFreighterConnected, isShortenerUrl, isValidAmount, isValidAssetCode, isValidSnapId, isValidStellarAddress, listSnaps, matchUrlToRule, metaTagsToHtml, parseAddress, parseQueryParams, parseSnapUri, removeDomain, resolveUrl, resolveUrls, signWithFreighter, submitTransaction, successResponse, validateDiscoveryFile, validateRegistry, validateRequired, validateSnapInput };
1235
+ export { CACHE_HEADERS, CORS_HEADERS, EXPLORER_URLS, HORIZON_URLS, InvalidAddressError, InvalidAmountError, InvalidAssetError, InvalidUriError, NETWORK_PASSPHRASES2 as NETWORK_PASSPHRASES, POSTGRES_SCHEMA, SHORTENER_DOMAINS, SQLITE_SCHEMA, SnapApiError, SnapNotFoundError, SnapUnauthorizedError, StellarSnapError, addDomain, buildPaymentTransaction, buildUrl, closeSnapModal, connectFreighter, createAsset, createDiscoveryFile, createPaymentSnap, createRateLimiter, createRegistry, createSnap, createSnapObject, createTransactionSnap, deleteSnap, errorResponse, extractDomain, extractPath, extractSnapId, generateJsonLd, generateMetaTags, generateSnapId, getAccountUrl, getAssetUrl, getBlockedDomains, getDomainStatus, getFreighterNetwork, getOperationUrl, getSnap, getTransactionUrl, getVerifiedDomains, isDomainBlocked, isDomainVerified, isFreighterConnected, isShortenerUrl, isValidAmount, isValidAssetCode, isValidSnapId, isValidStellarAddress, listSnaps, matchUrlToRule, metaTagsToHtml, openSnapModal, parseAddress, parseQueryParams, parseSnapUri, removeDomain, resolveUrl, resolveUrls, signWithFreighter, submitTransaction, successResponse, validateDiscoveryFile, validateRegistry, validateRequired, validateSnapInput };
1136
1236
  //# sourceMappingURL=index.mjs.map
1137
1237
  //# sourceMappingURL=index.mjs.map