@settlr/sdk 0.4.4 → 0.6.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/index.js CHANGED
@@ -32,23 +32,40 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  BuyButton: () => BuyButton,
34
34
  CheckoutWidget: () => CheckoutWidget,
35
+ INCO_LIGHTNING_PROGRAM_ID: () => INCO_LIGHTNING_PROGRAM_ID,
36
+ OneClickClient: () => OneClickClient,
35
37
  PaymentModal: () => PaymentModal,
38
+ PrivacyFeatures: () => PrivacyFeatures,
39
+ REACT_NATIVE_EXAMPLE: () => REACT_NATIVE_EXAMPLE,
40
+ REST_API: () => REST_API,
36
41
  SETTLR_CHECKOUT_URL: () => SETTLR_CHECKOUT_URL,
42
+ SETTLR_PROGRAM_ID: () => SETTLR_PROGRAM_ID,
37
43
  SUPPORTED_NETWORKS: () => SUPPORTED_NETWORKS,
38
44
  SUPPORTED_TOKENS: () => SUPPORTED_TOKENS,
39
45
  Settlr: () => Settlr,
40
46
  SettlrProvider: () => SettlrProvider,
47
+ UNITY_EXAMPLE: () => UNITY_EXAMPLE,
41
48
  USDC_MINT_DEVNET: () => USDC_MINT_DEVNET,
42
49
  USDC_MINT_MAINNET: () => USDC_MINT_MAINNET,
43
50
  USDT_MINT_DEVNET: () => USDT_MINT_DEVNET,
44
51
  USDT_MINT_MAINNET: () => USDT_MINT_MAINNET,
52
+ buildAllowanceRemainingAccounts: () => buildAllowanceRemainingAccounts,
53
+ buildPrivateReceiptAccounts: () => buildPrivateReceiptAccounts,
54
+ createOneClickClient: () => createOneClickClient,
45
55
  createWebhookHandler: () => createWebhookHandler,
56
+ encryptAmount: () => encryptAmount,
57
+ findAllowancePda: () => findAllowancePda,
58
+ findPrivateReceiptPda: () => findPrivateReceiptPda,
46
59
  formatUSDC: () => formatUSDC,
60
+ generateCheckoutUrl: () => generateCheckoutUrl,
61
+ generateDeepLinkCheckout: () => generateDeepLinkCheckout,
47
62
  getTokenDecimals: () => getTokenDecimals,
48
63
  getTokenMint: () => getTokenMint,
64
+ parseCallbackUrl: () => parseCallbackUrl,
49
65
  parseUSDC: () => parseUSDC,
50
66
  parseWebhookPayload: () => parseWebhookPayload,
51
67
  shortenAddress: () => shortenAddress,
68
+ simulateAndGetHandle: () => simulateAndGetHandle,
52
69
  usePaymentLink: () => usePaymentLink,
53
70
  usePaymentModal: () => usePaymentModal,
54
71
  useSettlr: () => useSettlr,
@@ -1219,27 +1236,401 @@ function createWebhookHandler(options) {
1219
1236
  }
1220
1237
  };
1221
1238
  }
1239
+
1240
+ // src/privacy.ts
1241
+ var import_web33 = require("@solana/web3.js");
1242
+ var INCO_LIGHTNING_PROGRAM_ID = new import_web33.PublicKey(
1243
+ "5sjEbPiqgZrYwR31ahR6Uk9wf5awoX61YGg7jExQSwaj"
1244
+ );
1245
+ var SETTLR_PROGRAM_ID = new import_web33.PublicKey(
1246
+ "339A4zncMj8fbM2zvEopYXu6TZqRieJKebDiXCKwquA5"
1247
+ );
1248
+ function findAllowancePda(handle, allowedAddress) {
1249
+ const handleBuffer = Buffer.alloc(16);
1250
+ let h = handle;
1251
+ for (let i = 0; i < 16; i++) {
1252
+ handleBuffer[i] = Number(h & BigInt(255));
1253
+ h = h >> BigInt(8);
1254
+ }
1255
+ return import_web33.PublicKey.findProgramAddressSync(
1256
+ [handleBuffer, allowedAddress.toBuffer()],
1257
+ INCO_LIGHTNING_PROGRAM_ID
1258
+ );
1259
+ }
1260
+ function findPrivateReceiptPda(paymentId) {
1261
+ return import_web33.PublicKey.findProgramAddressSync(
1262
+ [Buffer.from("private_receipt"), Buffer.from(paymentId)],
1263
+ SETTLR_PROGRAM_ID
1264
+ );
1265
+ }
1266
+ async function encryptAmount(amount) {
1267
+ const buffer = Buffer.alloc(16);
1268
+ let a = amount;
1269
+ for (let i = 0; i < 16; i++) {
1270
+ buffer[i] = Number(a & BigInt(255));
1271
+ a = a >> BigInt(8);
1272
+ }
1273
+ return new Uint8Array(buffer);
1274
+ }
1275
+ async function buildPrivateReceiptAccounts(config) {
1276
+ const [privateReceiptPda, privateReceiptBump] = findPrivateReceiptPda(config.paymentId);
1277
+ return {
1278
+ customer: config.customer,
1279
+ merchant: config.merchant,
1280
+ privateReceipt: privateReceiptPda,
1281
+ incoLightningProgram: INCO_LIGHTNING_PROGRAM_ID,
1282
+ systemProgram: import_web33.SystemProgram.programId,
1283
+ bump: privateReceiptBump
1284
+ };
1285
+ }
1286
+ async function simulateAndGetHandle(connection, transaction, privateReceiptPda) {
1287
+ try {
1288
+ const simulation = await connection.simulateTransaction(
1289
+ transaction,
1290
+ void 0,
1291
+ [privateReceiptPda]
1292
+ );
1293
+ if (simulation.value.err) {
1294
+ console.error("Simulation failed:", simulation.value.err);
1295
+ return null;
1296
+ }
1297
+ if (simulation.value.accounts?.[0]?.data) {
1298
+ const data = Buffer.from(simulation.value.accounts[0].data[0], "base64");
1299
+ const paymentIdLen = data.readUInt32LE(8);
1300
+ const handleOffset = 8 + 4 + paymentIdLen + 32 + 32;
1301
+ let handle = BigInt(0);
1302
+ for (let i = 15; i >= 0; i--) {
1303
+ handle = handle * BigInt(256) + BigInt(data[handleOffset + i]);
1304
+ }
1305
+ return handle;
1306
+ }
1307
+ return null;
1308
+ } catch (error) {
1309
+ console.error("Simulation error:", error);
1310
+ return null;
1311
+ }
1312
+ }
1313
+ function buildAllowanceRemainingAccounts(handle, customer, merchant) {
1314
+ const [customerAllowancePda] = findAllowancePda(handle, customer);
1315
+ const [merchantAllowancePda] = findAllowancePda(handle, merchant);
1316
+ return [
1317
+ { pubkey: customerAllowancePda, isSigner: false, isWritable: true },
1318
+ { pubkey: merchantAllowancePda, isSigner: false, isWritable: true }
1319
+ ];
1320
+ }
1321
+ var PrivacyFeatures = {
1322
+ /** Amount is FHE-encrypted, only handle stored on-chain */
1323
+ ENCRYPTED_AMOUNTS: true,
1324
+ /** Selective disclosure - only merchant + customer can decrypt */
1325
+ ACCESS_CONTROL: true,
1326
+ /** CSV export still works (decrypts server-side for authorized merchant) */
1327
+ ACCOUNTING_COMPATIBLE: true,
1328
+ /** Inco covalidators ensure trustless decryption */
1329
+ TRUSTLESS_DECRYPTION: true
1330
+ };
1331
+ var BillingCycles = {
1332
+ /** Weekly (7 days) */
1333
+ WEEKLY: 7 * 24 * 60 * 60,
1334
+ /** Bi-weekly (14 days) */
1335
+ BIWEEKLY: 14 * 24 * 60 * 60,
1336
+ /** Monthly (30 days) */
1337
+ MONTHLY: 30 * 24 * 60 * 60,
1338
+ /** Quarterly (90 days) */
1339
+ QUARTERLY: 90 * 24 * 60 * 60,
1340
+ /** Yearly (365 days) */
1341
+ YEARLY: 365 * 24 * 60 * 60
1342
+ };
1343
+
1344
+ // src/one-click.ts
1345
+ var OneClickClient = class {
1346
+ constructor(baseUrl = "https://settlr.dev") {
1347
+ this.baseUrl = baseUrl.replace(/\/$/, "");
1348
+ }
1349
+ /**
1350
+ * Customer approves a spending limit for a merchant
1351
+ */
1352
+ async approve(options) {
1353
+ const response = await fetch(`${this.baseUrl}/api/one-click`, {
1354
+ method: "POST",
1355
+ headers: { "Content-Type": "application/json" },
1356
+ body: JSON.stringify({
1357
+ action: "approve",
1358
+ ...options
1359
+ })
1360
+ });
1361
+ const data = await response.json();
1362
+ if (!response.ok) {
1363
+ throw new Error(data.error || "Failed to create approval");
1364
+ }
1365
+ return {
1366
+ success: true,
1367
+ approval: data.approval
1368
+ };
1369
+ }
1370
+ /**
1371
+ * Check if customer has active approval for merchant
1372
+ */
1373
+ async check(customerWallet, merchantWallet) {
1374
+ const response = await fetch(`${this.baseUrl}/api/one-click`, {
1375
+ method: "POST",
1376
+ headers: { "Content-Type": "application/json" },
1377
+ body: JSON.stringify({
1378
+ action: "check",
1379
+ customerWallet,
1380
+ merchantWallet
1381
+ })
1382
+ });
1383
+ const data = await response.json();
1384
+ return {
1385
+ hasApproval: data.hasApproval || false,
1386
+ remainingLimit: data.remainingLimit,
1387
+ approval: data.approval
1388
+ };
1389
+ }
1390
+ /**
1391
+ * Merchant charges customer using their one-click approval
1392
+ * No customer interaction required if approval exists with sufficient limit
1393
+ */
1394
+ async charge(options) {
1395
+ const response = await fetch(`${this.baseUrl}/api/one-click`, {
1396
+ method: "POST",
1397
+ headers: { "Content-Type": "application/json" },
1398
+ body: JSON.stringify({
1399
+ action: "charge",
1400
+ ...options
1401
+ })
1402
+ });
1403
+ const data = await response.json();
1404
+ if (!response.ok) {
1405
+ return {
1406
+ success: false,
1407
+ error: data.error
1408
+ };
1409
+ }
1410
+ return {
1411
+ success: true,
1412
+ txSignature: data.txSignature,
1413
+ remainingLimit: data.remainingLimit
1414
+ };
1415
+ }
1416
+ /**
1417
+ * Customer revokes merchant's one-click access
1418
+ */
1419
+ async revoke(customerWallet, merchantWallet) {
1420
+ const response = await fetch(`${this.baseUrl}/api/one-click`, {
1421
+ method: "POST",
1422
+ headers: { "Content-Type": "application/json" },
1423
+ body: JSON.stringify({
1424
+ action: "revoke",
1425
+ customerWallet,
1426
+ merchantWallet
1427
+ })
1428
+ });
1429
+ return { success: response.ok };
1430
+ }
1431
+ };
1432
+ function createOneClickClient(baseUrl) {
1433
+ return new OneClickClient(baseUrl);
1434
+ }
1435
+
1436
+ // src/mobile.ts
1437
+ function generateCheckoutUrl(options, baseUrl = "https://settlr.dev") {
1438
+ const params = new URLSearchParams();
1439
+ params.set("amount", options.amount.toString());
1440
+ params.set("merchant", options.merchantWallet);
1441
+ if (options.merchantName) params.set("name", options.merchantName);
1442
+ if (options.memo) params.set("memo", options.memo);
1443
+ if (options.successUrl) params.set("success_url", options.successUrl);
1444
+ if (options.cancelUrl) params.set("cancel_url", options.cancelUrl);
1445
+ if (options.orderId) params.set("order_id", options.orderId);
1446
+ if (options.customerId) params.set("customer_id", options.customerId);
1447
+ return `${baseUrl}/checkout?${params.toString()}`;
1448
+ }
1449
+ function generateDeepLinkCheckout(options, appScheme, baseUrl = "https://settlr.dev") {
1450
+ const orderId = options.orderId || `order_${Date.now()}`;
1451
+ return generateCheckoutUrl({
1452
+ ...options,
1453
+ orderId,
1454
+ successUrl: `${appScheme}://payment-success?order=${orderId}`,
1455
+ cancelUrl: `${appScheme}://payment-cancel?order=${orderId}`
1456
+ }, baseUrl);
1457
+ }
1458
+ function parseCallbackUrl(url) {
1459
+ try {
1460
+ const parsed = new URL(url);
1461
+ const params = parsed.searchParams;
1462
+ if (parsed.host === "payment-success" || parsed.pathname.includes("success")) {
1463
+ return {
1464
+ success: true,
1465
+ signature: params.get("signature") || void 0,
1466
+ orderId: params.get("order") || params.get("order_id") || void 0
1467
+ };
1468
+ }
1469
+ if (parsed.host === "payment-cancel" || parsed.pathname.includes("cancel")) {
1470
+ return {
1471
+ success: false,
1472
+ orderId: params.get("order") || params.get("order_id") || void 0,
1473
+ error: "Payment cancelled by user"
1474
+ };
1475
+ }
1476
+ return {
1477
+ success: false,
1478
+ error: "Unknown callback URL format"
1479
+ };
1480
+ } catch {
1481
+ return {
1482
+ success: false,
1483
+ error: "Failed to parse callback URL"
1484
+ };
1485
+ }
1486
+ }
1487
+ var REST_API = {
1488
+ createSession: "/api/checkout/create",
1489
+ checkStatus: "/api/checkout/status",
1490
+ oneClick: "/api/one-click",
1491
+ webhook: "/api/webhooks"
1492
+ // For server-to-server notifications
1493
+ };
1494
+ var UNITY_EXAMPLE = `
1495
+ // SettlrPayment.cs - Drop into your Unity project
1496
+
1497
+ using UnityEngine;
1498
+ using UnityEngine.Networking;
1499
+ using System.Collections;
1500
+
1501
+ public class SettlrPayment : MonoBehaviour
1502
+ {
1503
+ public string merchantWallet = "YOUR_WALLET_ADDRESS";
1504
+ public string settlrUrl = "https://settlr.dev";
1505
+
1506
+ // Call this to start a payment
1507
+ public void StartPayment(float amount, string orderId, System.Action<bool, string> callback)
1508
+ {
1509
+ string url = $"{settlrUrl}/checkout?amount={amount}&merchant={merchantWallet}&order_id={orderId}";
1510
+
1511
+ // Add deep link callback (register mygame:// scheme in your app)
1512
+ url += $"&success_url=mygame://payment-success?order={orderId}";
1513
+ url += $"&cancel_url=mygame://payment-cancel?order={orderId}";
1514
+
1515
+ Application.OpenURL(url);
1516
+
1517
+ // Start polling for completion
1518
+ StartCoroutine(PollPaymentStatus(orderId, callback));
1519
+ }
1520
+
1521
+ IEnumerator PollPaymentStatus(string orderId, System.Action<bool, string> callback)
1522
+ {
1523
+ string statusUrl = $"{settlrUrl}/api/checkout/status?order_id={orderId}";
1524
+
1525
+ for (int i = 0; i < 60; i++) // Poll for 5 minutes
1526
+ {
1527
+ using (UnityWebRequest request = UnityWebRequest.Get(statusUrl))
1528
+ {
1529
+ yield return request.SendWebRequest();
1530
+
1531
+ if (request.result == UnityWebRequest.Result.Success)
1532
+ {
1533
+ var response = JsonUtility.FromJson<PaymentStatusResponse>(request.downloadHandler.text);
1534
+
1535
+ if (response.status == "completed")
1536
+ {
1537
+ callback(true, response.signature);
1538
+ yield break;
1539
+ }
1540
+ else if (response.status == "expired" || response.status == "cancelled")
1541
+ {
1542
+ callback(false, null);
1543
+ yield break;
1544
+ }
1545
+ }
1546
+ }
1547
+
1548
+ yield return new WaitForSeconds(5f); // Check every 5 seconds
1549
+ }
1550
+
1551
+ callback(false, "Timeout");
1552
+ }
1553
+
1554
+ [System.Serializable]
1555
+ class PaymentStatusResponse
1556
+ {
1557
+ public string status;
1558
+ public string signature;
1559
+ }
1560
+ }
1561
+ `;
1562
+ var REACT_NATIVE_EXAMPLE = `
1563
+ // SettlrPayment.tsx - React Native component
1564
+
1565
+ import { Linking, Alert } from 'react-native';
1566
+ import { useEffect } from 'react';
1567
+
1568
+ const SETTLR_URL = 'https://settlr.dev';
1569
+ const APP_SCHEME = 'mygame';
1570
+
1571
+ export function useSettlrPayment(onSuccess: (sig: string) => void) {
1572
+ useEffect(() => {
1573
+ const handleDeepLink = ({ url }: { url: string }) => {
1574
+ if (url.includes('payment-success')) {
1575
+ const sig = new URL(url).searchParams.get('signature');
1576
+ if (sig) onSuccess(sig);
1577
+ }
1578
+ };
1579
+
1580
+ Linking.addEventListener('url', handleDeepLink);
1581
+ return () => Linking.removeAllListeners('url');
1582
+ }, [onSuccess]);
1583
+
1584
+ const startPayment = async (amount: number, merchantWallet: string) => {
1585
+ const orderId = \`order_\${Date.now()}\`;
1586
+ const url = \`\${SETTLR_URL}/checkout?amount=\${amount}&merchant=\${merchantWallet}\` +
1587
+ \`&success_url=\${APP_SCHEME}://payment-success?order=\${orderId}\` +
1588
+ \`&cancel_url=\${APP_SCHEME}://payment-cancel?order=\${orderId}\`;
1589
+
1590
+ await Linking.openURL(url);
1591
+ };
1592
+
1593
+ return { startPayment };
1594
+ }
1595
+ `;
1222
1596
  // Annotate the CommonJS export names for ESM import in node:
1223
1597
  0 && (module.exports = {
1224
1598
  BuyButton,
1225
1599
  CheckoutWidget,
1600
+ INCO_LIGHTNING_PROGRAM_ID,
1601
+ OneClickClient,
1226
1602
  PaymentModal,
1603
+ PrivacyFeatures,
1604
+ REACT_NATIVE_EXAMPLE,
1605
+ REST_API,
1227
1606
  SETTLR_CHECKOUT_URL,
1607
+ SETTLR_PROGRAM_ID,
1228
1608
  SUPPORTED_NETWORKS,
1229
1609
  SUPPORTED_TOKENS,
1230
1610
  Settlr,
1231
1611
  SettlrProvider,
1612
+ UNITY_EXAMPLE,
1232
1613
  USDC_MINT_DEVNET,
1233
1614
  USDC_MINT_MAINNET,
1234
1615
  USDT_MINT_DEVNET,
1235
1616
  USDT_MINT_MAINNET,
1617
+ buildAllowanceRemainingAccounts,
1618
+ buildPrivateReceiptAccounts,
1619
+ createOneClickClient,
1236
1620
  createWebhookHandler,
1621
+ encryptAmount,
1622
+ findAllowancePda,
1623
+ findPrivateReceiptPda,
1237
1624
  formatUSDC,
1625
+ generateCheckoutUrl,
1626
+ generateDeepLinkCheckout,
1238
1627
  getTokenDecimals,
1239
1628
  getTokenMint,
1629
+ parseCallbackUrl,
1240
1630
  parseUSDC,
1241
1631
  parseWebhookPayload,
1242
1632
  shortenAddress,
1633
+ simulateAndGetHandle,
1243
1634
  usePaymentLink,
1244
1635
  usePaymentModal,
1245
1636
  useSettlr,