@tineon/t9n 0.1.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.
@@ -0,0 +1,502 @@
1
+ export class CheckoutModal {
2
+ constructor(currencies, handlers) {
3
+ this.currencies = currencies;
4
+ this.handlers = handlers;
5
+ this.chips = [];
6
+ this.confirmLabel = "I have made the payment";
7
+ this.selectedCurrency = null;
8
+ this.host = document.createElement("div");
9
+ this.host.setAttribute("data-slimepay-checkout", "true");
10
+ this.root = this.host.attachShadow({ mode: "open" });
11
+ // Initialize Elements
12
+ this.timerEl = document.createElement("span");
13
+ this.addressEl = document.createElement("input");
14
+ this.qrEl = document.createElement("div");
15
+ this.statusEl = document.createElement("p");
16
+ this.disclaimerEl = document.createElement("p");
17
+ this.confirmBtn = document.createElement("button");
18
+ this.copyBtn = document.createElement("button");
19
+ this.backBtn = document.createElement("button");
20
+ this.actionsContainer = document.createElement("div");
21
+ this.selectionSection = document.createElement("div");
22
+ this.paymentSection = document.createElement("div");
23
+ this.resultSection = document.createElement("div");
24
+ this.resultTitle = document.createElement("h3");
25
+ this.resultMessage = document.createElement("p");
26
+ this.resultIcon = document.createElement("div");
27
+ this.retryBtn = document.createElement("button");
28
+ this.resultCloseBtn = document.createElement("button");
29
+ this.mount();
30
+ }
31
+ mount() {
32
+ const style = document.createElement("style");
33
+ style.textContent = `
34
+ :host {
35
+ --sp-primary: #005CFD;
36
+ --sp-primary-hover: #004ecc;
37
+ --sp-bg: #ffffff;
38
+ --sp-text: #0f172a;
39
+ --sp-text-muted: #64748b;
40
+ --sp-border: rgba(0, 0, 0, 0.08);
41
+ --sp-radius: 24px;
42
+ font-family: 'Inter', system-ui, -apple-system, sans-serif;
43
+ }
44
+
45
+ .overlay {
46
+ position: fixed; inset: 0;
47
+ background: rgba(15, 23, 42, 0.6);
48
+ backdrop-filter: blur(8px);
49
+ display: flex; align-items: center; justify-content: center;
50
+ padding: 20px; z-index: 2147483647;
51
+ animation: fadeIn 0.3s ease-out;
52
+ }
53
+
54
+ .modal {
55
+ width: 100%; max-width: 440px;
56
+ background: var(--sp-bg);
57
+ border-radius: var(--sp-radius);
58
+ box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
59
+ overflow: hidden;
60
+ display: flex; flex-direction: column;
61
+ border: 1px solid rgba(255, 255, 255, 0.1);
62
+ }
63
+
64
+ .header {
65
+ padding: 24px 24px 16px;
66
+ display: flex; justify-content: space-between; align-items: flex-start;
67
+ }
68
+
69
+ .brand { display: flex; align-items: center; gap: 10px; }
70
+ .brand-name { font-weight: 800; font-size: 18px; letter-spacing: -0.02em; }
71
+ .close-btn {
72
+ background: #f1f5f9;
73
+ border: 1px solid var(--sp-border);
74
+ width: 32px; height: 32px;
75
+ border-radius: 10px;
76
+ display: grid; place-items: center;
77
+ cursor: pointer;
78
+ transition: all 0.2s;
79
+ }
80
+ .close-btn:hover { background: #e2e8f0; }
81
+
82
+ .timer-pill {
83
+ background: #f1f5f9;
84
+ padding: 6px 12px;
85
+ border-radius: 99px;
86
+ font-size: 12px; font-weight: 600; color: var(--sp-text-muted);
87
+ display: flex; align-items: center; gap: 6px;
88
+ }
89
+
90
+ .content { padding: 0 24px 24px; }
91
+
92
+ .title-group { margin-bottom: 20px; }
93
+ .title { font-size: 20px; font-weight: 700; margin: 0; color: var(--sp-text); }
94
+ .subtitle { font-size: 14px; color: var(--sp-text-muted); margin: 4px 0 0; }
95
+
96
+ .grid-chips {
97
+ display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
98
+ }
99
+
100
+ .chip {
101
+ background: #fff; border: 1px solid var(--sp-border);
102
+ padding: 12px; border-radius: 16px;
103
+ display: flex; align-items: center; gap: 10px;
104
+ cursor: pointer; transition: all 0.2s;
105
+ font-weight: 600; font-size: 14px;
106
+ }
107
+
108
+ .chip:hover { border-color: var(--sp-primary); background: #f8faff; }
109
+ .chip img { width: 24px; height: 24px; border-radius: 6px; }
110
+
111
+ .payment-area { display: none; flex-direction: column; align-items: center; text-align: center; }
112
+ .payment-area.active { display: flex; }
113
+
114
+ .qr-container {
115
+ background: #f8fafc; border-radius: 20px;
116
+ padding: 20px; margin-bottom: 20px;
117
+ border: 1px solid var(--sp-border);
118
+ }
119
+ .qr-container img { width: 180px; height: 180px; display: block; border-radius: 12px; }
120
+
121
+ .address-box {
122
+ width: 100%; background: #f1f5f9;
123
+ border-radius: 14px; padding: 4px;
124
+ display: flex; align-items: center; gap: 4px;
125
+ margin-bottom: 16px;
126
+ }
127
+ .address-input {
128
+ flex: 1; border: none; background: transparent;
129
+ padding: 10px 12px; font-size: 13px; font-family: monospace;
130
+ color: var(--sp-text); outline: none;
131
+ }
132
+ .copy-btn {
133
+ background: #fff; border: 1px solid var(--sp-border);
134
+ padding: 8px 12px; border-radius: 10px;
135
+ font-size: 12px; font-weight: 700; cursor: pointer;
136
+ }
137
+
138
+ .status-msg { display: none; }
139
+ .disclaimer { font-size: 12px; color: var(--sp-text); background: #eef2ff; border: 1px solid rgba(59,130,246,0.25); padding: 10px 12px; border-radius: 12px; margin-bottom: 12px; }
140
+
141
+ .footer-actions {
142
+ padding: 16px 24px 24px;
143
+ display: none; grid-template-columns: 1fr; gap: 10px;
144
+ border-top: 1px solid var(--sp-border);
145
+ }
146
+ .footer-actions.visible { display: grid; }
147
+ .result-area { display: none; flex-direction: column; align-items: center; text-align: center; gap: 12px; padding: 18px 16px; border: 1px solid var(--sp-border); border-radius: 18px; background: #fff; }
148
+ .result-area.visible { display: flex; }
149
+ .result-icon { width: 70px; height: 70px; border-radius: 999px; display: grid; place-items: center; }
150
+ .result-icon.success { background: rgba(16, 185, 129, 0.12); color: #10b981; }
151
+ .result-icon.fail { background: rgba(244, 63, 94, 0.12); color: #f43f5e; }
152
+ .result-title { margin: 0; font-size: 18px; font-weight: 800; color: var(--sp-text); }
153
+ .result-msg { margin: 0; font-size: 13px; color: var(--sp-text-muted); }
154
+ .result-actions { display: grid; width: 100%; gap: 8px; }
155
+ .result-actions button { width: 100%; }
156
+
157
+ button.primary {
158
+ background: var(--sp-primary); color: white;
159
+ border: none; padding: 14px; border-radius: 14px;
160
+ font-weight: 700; font-size: 14px; cursor: pointer;
161
+ transition: background 0.2s;
162
+ }
163
+ button.primary:hover { background: var(--sp-primary-hover); }
164
+ button.secondary {
165
+ background: #f1f5f9; color: var(--sp-text);
166
+ border: none; padding: 12px; border-radius: 14px;
167
+ font-weight: 700; font-size: 14px; cursor: pointer;
168
+ display: flex; align-items: center; justify-content: center;
169
+ text-align: center;
170
+ }
171
+
172
+ .back-btn {
173
+ background: none; border: none; color: var(--sp-primary);
174
+ font-size: 13px; font-weight: 700; cursor: pointer;
175
+ display: flex; align-items: center; gap: 4px; margin-bottom: 12px;
176
+ }
177
+
178
+ .spin { animation: spin 1s linear infinite; display: inline-block; }
179
+ @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
180
+ @keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
181
+
182
+ @media (max-width: 480px) {
183
+ .modal { max-width: 100%; border-radius: 24px 24px 0 0; position: absolute; bottom: 0; max-height: 92vh; }
184
+ .grid-chips { grid-template-columns: 1fr; }
185
+ .content { max-height: calc(92vh - 90px); overflow-y: auto; }
186
+ }
187
+ `;
188
+ // Structure
189
+ const overlay = document.createElement("div");
190
+ overlay.className = "overlay";
191
+ const modal = document.createElement("div");
192
+ modal.className = "modal";
193
+ // Header
194
+ const header = document.createElement("div");
195
+ header.className = "header";
196
+ header.innerHTML = `
197
+ <div class="brand">
198
+ ${slimepayLogoSvg()}
199
+ <span class="brand-name">Slimepay</span>
200
+ </div>
201
+ `;
202
+ const closeBtn = document.createElement("button");
203
+ closeBtn.className = "close-btn";
204
+ closeBtn.type = "button";
205
+ closeBtn.innerHTML = `${closeIconSvg()}`;
206
+ closeBtn.onclick = this.handlers.onClose;
207
+ const timerPill = document.createElement("div");
208
+ timerPill.className = "timer-pill";
209
+ timerPill.innerHTML = `<span>🕒</span>`;
210
+ timerPill.appendChild(this.timerEl);
211
+ const headerRight = document.createElement("div");
212
+ headerRight.style.display = "flex";
213
+ headerRight.style.alignItems = "center";
214
+ headerRight.style.gap = "8px";
215
+ headerRight.append(timerPill, closeBtn);
216
+ header.appendChild(headerRight);
217
+ // Content Area
218
+ const content = document.createElement("div");
219
+ content.className = "content";
220
+ // Selection Section
221
+ this.selectionSection.className = "selection-section";
222
+ const titleGroup = document.createElement("div");
223
+ titleGroup.className = "title-group";
224
+ titleGroup.innerHTML = `
225
+ <h2 class="title">Pay with Crypto</h2>
226
+ <p class="subtitle">Select your preferred asset to continue</p>
227
+ `;
228
+ const chipsContainer = document.createElement("div");
229
+ chipsContainer.className = "grid-chips";
230
+ this.currencies.forEach((currency) => {
231
+ const chip = document.createElement("button");
232
+ chip.className = "chip";
233
+ const iconUrl = COIN_IMAGES[currency] || "";
234
+ chip.innerHTML = `
235
+ ${iconUrl ? `<img src="${iconUrl}" />` : `<div style="width:24px;height:24px;background:#eee;border-radius:4px"></div>`}
236
+ <span>${currency}</span>
237
+ `;
238
+ chip.onclick = () => this.handleCurrencySelect(currency);
239
+ this.chips.push(chip);
240
+ chipsContainer.appendChild(chip);
241
+ });
242
+ this.selectionSection.append(titleGroup, chipsContainer);
243
+ // Payment Section
244
+ this.paymentSection.className = "payment-area";
245
+ this.backBtn.className = "back-btn";
246
+ this.backBtn.innerHTML = `${arrowLeftSvg()} Change Currency`;
247
+ this.backBtn.onclick = () => this.resetSelection();
248
+ const qrContainer = document.createElement("div");
249
+ qrContainer.className = "qr-container";
250
+ qrContainer.appendChild(this.qrEl);
251
+ const addressBox = document.createElement("div");
252
+ addressBox.className = "address-box";
253
+ this.addressEl.className = "address-input";
254
+ this.addressEl.readOnly = true;
255
+ this.copyBtn.className = "copy-btn";
256
+ this.copyBtn.textContent = "Copy";
257
+ this.copyBtn.onclick = () => {
258
+ navigator.clipboard.writeText(this.addressEl.value);
259
+ this.copyBtn.textContent = "Copied!";
260
+ setTimeout(() => (this.copyBtn.textContent = "Copy"), 2000);
261
+ };
262
+ addressBox.append(this.addressEl, this.copyBtn);
263
+ this.statusEl.className = "status-msg";
264
+ this.disclaimerEl.className = "disclaimer";
265
+ this.disclaimerEl.textContent = "Send only the exact amount to the generated address to avoid loss of funds.";
266
+ this.paymentSection.append(this.backBtn, this.disclaimerEl, qrContainer, addressBox);
267
+ // Footer Actions (Initially Hidden)
268
+ this.actionsContainer.className = "footer-actions";
269
+ this.confirmBtn.className = "primary";
270
+ this.confirmBtn.textContent = this.confirmLabel;
271
+ this.confirmBtn.onclick = () => this.handlers.onConfirmPayment();
272
+ const cancelBtn = document.createElement("button");
273
+ cancelBtn.className = "secondary";
274
+ cancelBtn.textContent = "Cancel Payment";
275
+ cancelBtn.onclick = this.handlers.onClose;
276
+ this.actionsContainer.append(this.confirmBtn, cancelBtn);
277
+ // Result Section
278
+ this.resultSection.className = "result-area";
279
+ this.resultIcon.className = "result-icon success";
280
+ this.resultIcon.innerHTML = successIconSvg();
281
+ this.resultTitle.className = "result-title";
282
+ this.resultTitle.textContent = "Payment confirmed";
283
+ this.resultMessage.className = "result-msg";
284
+ this.resultMessage.textContent = "Your payment has been received.";
285
+ this.retryBtn.className = "secondary";
286
+ this.retryBtn.textContent = "Retry check";
287
+ this.retryBtn.onclick = () => {
288
+ this.showPaymentView();
289
+ this.handlers.onConfirmPayment();
290
+ };
291
+ this.resultCloseBtn.className = "primary";
292
+ this.resultCloseBtn.textContent = "Close";
293
+ this.resultCloseBtn.onclick = this.handlers.onClose;
294
+ const resultActions = document.createElement("div");
295
+ resultActions.className = "result-actions";
296
+ resultActions.append(this.retryBtn, this.resultCloseBtn);
297
+ this.resultSection.append(this.resultIcon, this.resultTitle, this.resultMessage, resultActions);
298
+ // Final Assembly
299
+ content.append(this.selectionSection, this.paymentSection, this.resultSection);
300
+ modal.append(header, content, this.actionsContainer);
301
+ overlay.appendChild(modal);
302
+ this.root.append(style, overlay);
303
+ document.body.appendChild(this.host);
304
+ }
305
+ async handleCurrencySelect(currency) {
306
+ this.selectedCurrency = currency;
307
+ this.selectionSection.style.display = "none";
308
+ this.paymentSection.classList.add("active");
309
+ this.resultSection.classList.remove("visible");
310
+ this.qrEl.innerHTML = `<div class="spin" style="margin: 60px 0;">${loaderIconSvg()}</div><p style="font-size:12px;color:#64748b">Generating Address...</p>`;
311
+ try {
312
+ await this.handlers.onSelectCurrency(currency);
313
+ }
314
+ catch (e) {
315
+ this.resetSelection();
316
+ }
317
+ }
318
+ setConfirmLabel(label) {
319
+ this.confirmLabel = label;
320
+ this.confirmBtn.innerHTML = label;
321
+ }
322
+ setTimer(value) {
323
+ this.timerEl.textContent = value;
324
+ }
325
+ setAddress(address) {
326
+ this.addressEl.value = address;
327
+ if (address) {
328
+ this.actionsContainer.classList.add("visible");
329
+ }
330
+ }
331
+ setQrPayload(payload) {
332
+ if (!payload)
333
+ return;
334
+ const qrSrc = `https://api.qrserver.com/v1/create-qr-code/?size=260x260&margin=10&data=${encodeURIComponent(payload)}`;
335
+ this.qrEl.innerHTML = `<img src="${qrSrc}" alt="Payment QR" />`;
336
+ }
337
+ setStatus(message) {
338
+ this.statusEl.textContent = message;
339
+ }
340
+ setDisclaimer(message) {
341
+ this.disclaimerEl.textContent = message;
342
+ }
343
+ setConfirmPending(pending) {
344
+ this.confirmBtn.disabled = pending;
345
+ this.confirmBtn.innerHTML = pending
346
+ ? `<span class="spin">${loaderIconSvg()}</span> Verifying...`
347
+ : this.confirmLabel;
348
+ }
349
+ showResult(status, message) {
350
+ this.resultSection.classList.add("visible");
351
+ this.paymentSection.classList.remove("active");
352
+ this.actionsContainer.classList.remove("visible");
353
+ if (status === "success") {
354
+ this.resultIcon.className = "result-icon success";
355
+ this.resultIcon.innerHTML = successIconSvg();
356
+ this.resultTitle.textContent = "Payment confirmed";
357
+ this.retryBtn.style.display = "none";
358
+ }
359
+ else {
360
+ this.resultIcon.className = "result-icon fail";
361
+ this.resultIcon.innerHTML = failIconSvg();
362
+ this.resultTitle.textContent = "Payment not detected";
363
+ this.retryBtn.style.display = "inline-flex";
364
+ }
365
+ this.resultMessage.textContent = message;
366
+ }
367
+ showPaymentView() {
368
+ this.resultSection.classList.remove("visible");
369
+ this.paymentSection.classList.add("active");
370
+ this.actionsContainer.classList.add("visible");
371
+ }
372
+ resetSelection() {
373
+ this.selectedCurrency = null;
374
+ this.addressEl.value = "";
375
+ this.paymentSection.classList.remove("active");
376
+ this.selectionSection.style.display = "block";
377
+ this.actionsContainer.classList.remove("visible");
378
+ this.resultSection.classList.remove("visible");
379
+ }
380
+ close() {
381
+ this.host.remove();
382
+ }
383
+ }
384
+ // Helpers
385
+ function loaderIconSvg() {
386
+ return `<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round"><path d="M12 2v4m0 12v4M4.93 4.93l2.83 2.83m8.48 8.48l2.83 2.83M2 12h4m12 0h4M4.93 19.07l2.83-2.83m8.48-8.48l2.83-2.83"/></svg>`;
387
+ }
388
+ function arrowLeftSvg() {
389
+ return `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="m15 18-6-6 6-6"/></svg>`;
390
+ }
391
+ function successIconSvg() {
392
+ return `<svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>`;
393
+ }
394
+ function failIconSvg() {
395
+ return `<svg width="34" height="34" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="m6 6 12 12M18 6 6 18"/></svg>`;
396
+ }
397
+ function closeIconSvg() {
398
+ return `<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>`;
399
+ }
400
+ function slimepayLogoSvg() {
401
+ return `<svg width="24" height="24" viewBox="0 0 100 100" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M33.458 93.622l51.489-51.488c4.502-4.502 4.502-11.803 0-16.307-4.502-4.503-11.803-4.503-16.307 0L8.998 85.467l8.057 8.058.098.097.098.098c4.51 4.404 11.738 4.372 16.207-.098z" fill="#005CFD"/><path d="M15.554 74.33l50.684-50.683.11-.112.112-.11c5.69-5.574 14.794-5.582 20.496-.027 2.713-4.349 2.252-10.116-1.382-13.985L77.161 1 17.617 60.543l-.097.098-.098.098c-3.622 3.708-4.243 9.25-1.868 13.59v.002z" fill="#0122AF"/></svg>`;
402
+ }
403
+ const COIN_IMAGES = {
404
+ BTC: "https://assets.coingecko.com/coins/images/1/large/bitcoin.png?1547033579",
405
+ HBAR: "https://assets.coingecko.com/coins/images/3688/large/hbar.png",
406
+ "BTC.h": "https://assets.coingecko.com/coins/images/55129/large/bitcoinHT_%281%29.png?1753601555",
407
+ "BTC.H": "https://assets.coingecko.com/coins/images/55129/large/bitcoinHT_%281%29.png?1753601555",
408
+ ETH: "https://assets.coingecko.com/coins/images/279/large/ethereum.png?1595348880",
409
+ USDT: "https://assets.coingecko.com/coins/images/325/large/Tether.png?1668148663",
410
+ SOL: "https://assets.coingecko.com/coins/images/4128/large/solana.png?1640133422",
411
+ XRP: "https://assets.coingecko.com/coins/images/44/large/xrp-symbol-white-128.png?1605772276",
412
+ BNB: "https://assets.coingecko.com/coins/images/825/large/bnb-icon2_2x.png?1644979850",
413
+ ADA: "https://assets.coingecko.com/coins/images/975/large/cardano.png?1547034860",
414
+ DOGE: "https://assets.coingecko.com/coins/images/5/large/dogecoin.png?1547792256",
415
+ TRX: "https://assets.coingecko.com/coins/images/1094/large/tron-logo.png?1547035066",
416
+ LTC: "https://assets.coingecko.com/coins/images/2/large/litecoin.png?1547033580",
417
+ MATIC: "https://assets.coingecko.com/coins/images/4713/large/matic-token-icon.png?1624446975",
418
+ DOT: "https://assets.coingecko.com/coins/images/12171/large/polkadot_new.png?1639703501",
419
+ SHIB: "https://assets.coingecko.com/coins/images/11939/large/shiba.png?1622619446",
420
+ AVAX: "https://cryptach.org/crypto-logo/avalanche-avax-logo.svg",
421
+ ARB: "https://cryptach.org/crypto-logo/arbitrum-arb-logo.svg",
422
+ UNI: "https://assets.coingecko.com/coins/images/12455/large/uniswap-uni.png?1600306604",
423
+ LINK: "https://assets.coingecko.com/coins/images/877/large/chainlink-new-logo.png?1547034700",
424
+ BCH: "https://assets.coingecko.com/coins/images/780/large/bitcoin-cash-circle.png?1594689492",
425
+ ETC: "https://assets.coingecko.com/coins/images/453/large/ethereum-classic-logo.png?1547034009",
426
+ XLM: "https://assets.coingecko.com/coins/images/100/large/Stellar_symbol_black_rgb.png?1552356157",
427
+ VET: "https://assets.coingecko.com/coins/images/1167/large/VeChain-Logo-768x768.png?1547035260",
428
+ FIL: "https://assets.coingecko.com/coins/images/12812/large/filecoin.png?1602753904",
429
+ ICP: "https://assets.coingecko.com/coins/images/14495/large/Internet_Computer_logo.png?1620703079",
430
+ THETA: "https://assets.coingecko.com/coins/images/2206/large/theta-token-logo.png?1548387191",
431
+ EOS: "https://assets.coingecko.com/coins/images/738/large/eos-eos-logo.png?1547034569",
432
+ XTZ: "https://assets.coingecko.com/coins/images/976/large/Tezos-logo.png?1547034862",
433
+ NEO: "https://assets.coingecko.com/coins/images/48/large/NEO.png?1594357361",
434
+ IOTA: "https://assets.coingecko.com/coins/images/132/large/iota_logo.png?1547033690",
435
+ DASH: "https://assets.coingecko.com/coins/images/10/large/dash-logo.png?1547033593",
436
+ ZEC: "https://assets.coingecko.com/coins/images/486/large/zcash.png?1547034039",
437
+ XMR: "https://assets.coingecko.com/coins/images/1/large/monero.png?1547033579",
438
+ WAVES: "https://assets.coingecko.com/coins/images/188/large/waves.png?1547033775",
439
+ ONT: "https://assets.coingecko.com/coins/images/1008/large/ontology.png?1547034902",
440
+ ALGO: "https://assets.coingecko.com/coins/images/4380/large/algorand.png?1570035510",
441
+ ATOM: "https://assets.coingecko.com/coins/images/1481/large/cosmos_hub.png?1555657960",
442
+ QTUM: "https://assets.coingecko.com/coins/images/370/large/qtum.png?1547033920",
443
+ DCR: "https://assets.coingecko.com/coins/images/228/large/decred.png?1547033810",
444
+ ZIL: "https://assets.coingecko.com/coins/images/253/large/zilliqa.png?1547033830",
445
+ OMG: "https://assets.coingecko.com/coins/images/778/large/omg-network-logo.png?1605772276",
446
+ BAT: "https://assets.coingecko.com/coins/images/677/large/basic-attention-token.png?1547034427",
447
+ ENJ: "https://assets.coingecko.com/coins/images/1102/large/enjin-coin-logo.png?1547035078",
448
+ KSM: "https://assets.coingecko.com/coins/images/9568/large/kusama-logo.png?1604278312",
449
+ SNX: "https://assets.coingecko.com/coins/images/843/large/synthetix-logo.png?1547034660",
450
+ COMP: "https://assets.coingecko.com/coins/images/10775/large/COMP.png?1592627929",
451
+ MKR: "https://assets.coingecko.com/coins/images/136/large/maker-logo.png?1547033709",
452
+ YFI: "https://assets.coingecko.com/coins/images/11849/large/yfi-192x192.png?1598325330",
453
+ CRV: "https://assets.coingecko.com/coins/images/12124/large/Curve.png?1597002956",
454
+ SUSHI: "https://assets.coingecko.com/coins/images/12271/large/512x512_PNG.png?1597844647",
455
+ GRT: "https://assets.coingecko.com/coins/images/13397/large/Graph_Token.png?1608145566",
456
+ MANA: "https://assets.coingecko.com/coins/images/878/large/decentraland-mana.png?1550124374",
457
+ AAVE: "https://assets.coingecko.com/coins/images/12645/large/AAVE.png?1601374110",
458
+ CHZ: "https://assets.coingecko.com/coins/images/831/large/ChZ_Logo_Blue.png?1547034649",
459
+ GALA: "https://assets.coingecko.com/coins/images/12493/large/gala.png?1600233435",
460
+ AXS: "https://assets.coingecko.com/coins/images/13029/large/axie_infinity_logo.png?1604471677",
461
+ SAND: "https://assets.coingecko.com/coins/images/12129/large/sandbox_logo.png?1597002956",
462
+ APE: "https://assets.coingecko.com/coins/images/24383/large/apecoin.jpg?1647476482",
463
+ DAI: "https://assets.coingecko.com/coins/images/995/large/dai-multi-collateral-dai.png?1574218778",
464
+ WBTC: "https://assets.coingecko.com/coins/images/759/large/wrapped_bitcoin_wbtc.png?1596348944",
465
+ TUSD: "https://assets.coingecko.com/coins/images/3449/large/TUSD.png?1612189019",
466
+ USDP: "https://assets.coingecko.com/coins/images/1026/large/pax_dollar.png?1547034926",
467
+ FET: "https://assets.coingecko.com/coins/images/1009/large/fetch-ai.png?1547034903",
468
+ BLUR: "https://assets.coingecko.com/coins/images/28834/large/blur.png?1674637840",
469
+ MEME: "https://assets.coingecko.com/coins/images/32060/large/MEMECOIN.png?1695950000",
470
+ BOME: "https://assets.coingecko.com/coins/images/35002/large/BOME.png?1710040000",
471
+ BEAM: "https://assets.coingecko.com/coins/images/1005/large/beam.png?1547034899",
472
+ PEPE: "https://assets.coingecko.com/coins/images/29800/large/pepe-token.jpeg?1679481329",
473
+ COQ: "https://assets.coingecko.com/coins/images/33300/large/coq.png?1701920000",
474
+ STRK: "https://assets.coingecko.com/coins/images/33677/large/starknet.png?1703748000",
475
+ SUI: "https://assets.coingecko.com/coins/images/26375/large/sui_logo.png?1657210000",
476
+ ENS: "https://assets.coingecko.com/coins/images/19731/large/ens.png?1635024944",
477
+ RNDR: "https://assets.coingecko.com/coins/images/11636/large/RenderToken.png?1592627929",
478
+ MOG: "https://assets.coingecko.com/coins/images/30920/large/Mog_Coin.png?1687939200",
479
+ MNT: "https://assets.coingecko.com/coins/images/28077/large/mantle.png?1666676000",
480
+ ONE: "https://assets.coingecko.com/coins/images/4377/large/harmony.png?1570035464",
481
+ CFX: "https://assets.coingecko.com/coins/images/1315/large/conflux.png?1547035302",
482
+ NEAR: "https://assets.coingecko.com/coins/images/10365/large/near_icon.png?1601359077",
483
+ TON: "https://assets.coingecko.com/coins/images/17980/large/ton_symbol.png?1629479260",
484
+ INJ: "https://assets.coingecko.com/coins/images/12882/large/injective_v3_logo.png?1639530038",
485
+ SLP: "https://assets.coingecko.com/coins/images/13049/large/small_love_potion.png?1604640213",
486
+ TRUMP: "https://assets.coingecko.com/coins/images/34800/large/MAGA.png?1709000000",
487
+ MYRO: "https://assets.coingecko.com/coins/images/33090/large/myro.png?1700000000",
488
+ CAKE: "https://assets.coingecko.com/coins/images/12632/large/pancakeswap-logo-new.png?1601374110",
489
+ GNO: "https://assets.coingecko.com/coins/images/1080/large/gnosis-gno.png?1547035059",
490
+ STX: "https://assets.coingecko.com/coins/images/776/large/stacks-logo.png?1547034594",
491
+ WIF: "https://assets.coingecko.com/coins/images/34784/large/dogwifhat.png?1708900000",
492
+ JUP: "https://assets.coingecko.com/coins/images/33721/large/Jupiter_logo.png?1704000000",
493
+ ORDI: "https://assets.coingecko.com/coins/images/32646/large/ordi.png?1700000000",
494
+ BOB: "https://assets.coingecko.com/coins/images/30920/large/Mog_Coin.png?1687939200",
495
+ PAYPAL: "https://www.paypalobjects.com/webstatic/mktg/logo/pp_cc_mark_37x23.jpg",
496
+ LSK: "https://logo.svgcdn.com/token-branded/lisk.svg",
497
+ FLOW: "https://www.cryptologos.cc/logos/flow-flow-logo.png",
498
+ RON: "https://logo.svgcdn.com/token-branded/ronin.svg",
499
+ ZETA: "https://logo.svgcdn.com/token-branded/zeta-chain.png",
500
+ SEI: "https://logo.svgcdn.com/token-branded/sei-network.png",
501
+ FTM: "https://logo.svgcdn.com/token-branded/fantom.png",
502
+ };
package/package.json ADDED
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@tineon/t9n",
3
+ "version": "0.1.2",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "files": [
8
+ "dist",
9
+ "README.md"
10
+ ],
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "scripts": {
15
+ "build": "tsc -p tsconfig.json"
16
+ },
17
+ "dependencies": {
18
+ "zod": "^3.24.1"
19
+ },
20
+ "devDependencies": {
21
+ "typescript": "^5.7.3"
22
+ }
23
+ }