@settlr/sdk 0.6.5 → 0.6.7
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.d.mts +430 -2
- package/dist/index.d.ts +430 -2
- package/dist/index.js +353 -1
- package/dist/index.mjs +349 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -145,8 +145,13 @@ var Settlr = class {
|
|
|
145
145
|
* Fetches merchant wallet address if not provided in config.
|
|
146
146
|
*/
|
|
147
147
|
async validateApiKey() {
|
|
148
|
-
|
|
148
|
+
console.log("[Settlr] validateApiKey called, validated:", this.validated, "apiBaseUrl:", this.apiBaseUrl);
|
|
149
|
+
if (this.validated) {
|
|
150
|
+
console.log("[Settlr] Already validated, skipping. merchantWallet:", this.merchantWallet?.toString(), "merchantWalletFromValidation:", this.merchantWalletFromValidation);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
149
153
|
try {
|
|
154
|
+
console.log("[Settlr] Fetching validation from:", `${this.apiBaseUrl}/sdk/validate`);
|
|
150
155
|
const response = await fetch(`${this.apiBaseUrl}/sdk/validate`, {
|
|
151
156
|
method: "POST",
|
|
152
157
|
headers: {
|
|
@@ -162,16 +167,19 @@ var Settlr = class {
|
|
|
162
167
|
throw new Error(error.error || "API key validation failed");
|
|
163
168
|
}
|
|
164
169
|
const data = await response.json();
|
|
170
|
+
console.log("[Settlr] Validation response:", data);
|
|
165
171
|
if (!data.valid) {
|
|
166
172
|
throw new Error(data.error || "Invalid API key");
|
|
167
173
|
}
|
|
168
174
|
this.validated = true;
|
|
169
175
|
this.merchantId = data.merchantId;
|
|
170
176
|
this.tier = data.tier;
|
|
177
|
+
console.log("[Settlr] Setting wallet. data.merchantWallet:", data.merchantWallet, "this.merchantWallet:", this.merchantWallet?.toString());
|
|
171
178
|
if (data.merchantWallet && !this.merchantWallet) {
|
|
172
179
|
this.merchantWallet = new PublicKey2(data.merchantWallet);
|
|
173
180
|
this.merchantWalletFromValidation = data.merchantWallet;
|
|
174
181
|
this.config.merchant.walletAddress = data.merchantWallet;
|
|
182
|
+
console.log("[Settlr] Wallet SET! merchantWallet:", this.merchantWallet.toString(), "merchantWalletFromValidation:", this.merchantWalletFromValidation);
|
|
175
183
|
}
|
|
176
184
|
if (data.merchantName && !this.config.merchant.name) {
|
|
177
185
|
this.config.merchant.name = data.merchantName;
|
|
@@ -212,8 +220,10 @@ var Settlr = class {
|
|
|
212
220
|
*/
|
|
213
221
|
getCheckoutUrl(options) {
|
|
214
222
|
const { amount, memo, orderId, successUrl, cancelUrl } = options;
|
|
223
|
+
console.log("[Settlr] getCheckoutUrl - config.wallet:", this.config.merchant.walletAddress, "merchantWalletFromValidation:", this.merchantWalletFromValidation, "validated:", this.validated);
|
|
215
224
|
const walletAddress = this.config.merchant.walletAddress?.toString() || this.merchantWalletFromValidation;
|
|
216
225
|
if (!walletAddress) {
|
|
226
|
+
console.error("[Settlr] No wallet address available!");
|
|
217
227
|
throw new Error("Wallet address not available. Either provide walletAddress in config or call validateApiKey() first.");
|
|
218
228
|
}
|
|
219
229
|
const baseUrl = this.config.testMode ? SETTLR_CHECKOUT_URL.development : SETTLR_CHECKOUT_URL.production;
|
|
@@ -1586,12 +1596,347 @@ export function useSettlrPayment(onSuccess: (sig: string) => void) {
|
|
|
1586
1596
|
return { startPayment };
|
|
1587
1597
|
}
|
|
1588
1598
|
`;
|
|
1599
|
+
|
|
1600
|
+
// src/subscriptions.ts
|
|
1601
|
+
var SubscriptionClient = class {
|
|
1602
|
+
constructor(config) {
|
|
1603
|
+
if (!config.apiKey) {
|
|
1604
|
+
throw new Error(
|
|
1605
|
+
"API key is required. Get one at https://settlr.dev/dashboard"
|
|
1606
|
+
);
|
|
1607
|
+
}
|
|
1608
|
+
this.apiKey = config.apiKey;
|
|
1609
|
+
this.baseUrl = (config.baseUrl || "https://settlr.dev").replace(/\/$/, "");
|
|
1610
|
+
this.merchantId = config.merchantId;
|
|
1611
|
+
this.merchantWallet = config.merchantWallet;
|
|
1612
|
+
}
|
|
1613
|
+
async fetch(path, options = {}) {
|
|
1614
|
+
const url = `${this.baseUrl}${path}`;
|
|
1615
|
+
const res = await fetch(url, {
|
|
1616
|
+
...options,
|
|
1617
|
+
headers: {
|
|
1618
|
+
"Content-Type": "application/json",
|
|
1619
|
+
"X-API-Key": this.apiKey,
|
|
1620
|
+
...options.headers
|
|
1621
|
+
}
|
|
1622
|
+
});
|
|
1623
|
+
const data = await res.json();
|
|
1624
|
+
if (!res.ok) {
|
|
1625
|
+
throw new Error(
|
|
1626
|
+
data.error || `API error: ${res.status}`
|
|
1627
|
+
);
|
|
1628
|
+
}
|
|
1629
|
+
return data;
|
|
1630
|
+
}
|
|
1631
|
+
/**
|
|
1632
|
+
* Resolve merchant ID from API key
|
|
1633
|
+
*/
|
|
1634
|
+
async ensureMerchantId() {
|
|
1635
|
+
if (this.merchantId) return this.merchantId;
|
|
1636
|
+
const data = await this.fetch("/api/sdk/validate", {
|
|
1637
|
+
method: "POST",
|
|
1638
|
+
body: JSON.stringify({})
|
|
1639
|
+
});
|
|
1640
|
+
this.merchantId = data.merchantId;
|
|
1641
|
+
if (data.merchantWallet && !this.merchantWallet) {
|
|
1642
|
+
this.merchantWallet = data.merchantWallet;
|
|
1643
|
+
}
|
|
1644
|
+
return this.merchantId;
|
|
1645
|
+
}
|
|
1646
|
+
// ═══════════════════════════════════════
|
|
1647
|
+
// PLANS
|
|
1648
|
+
// ═══════════════════════════════════════
|
|
1649
|
+
/**
|
|
1650
|
+
* Create a subscription plan
|
|
1651
|
+
*/
|
|
1652
|
+
async createPlan(options) {
|
|
1653
|
+
const merchantId = await this.ensureMerchantId();
|
|
1654
|
+
const data = await this.fetch(
|
|
1655
|
+
"/api/subscriptions/plans",
|
|
1656
|
+
{
|
|
1657
|
+
method: "POST",
|
|
1658
|
+
body: JSON.stringify({
|
|
1659
|
+
merchantId,
|
|
1660
|
+
name: options.name,
|
|
1661
|
+
description: options.description,
|
|
1662
|
+
amount: options.amount,
|
|
1663
|
+
interval: options.interval,
|
|
1664
|
+
intervalCount: options.intervalCount || 1,
|
|
1665
|
+
trialDays: options.trialDays || 0,
|
|
1666
|
+
features: options.features || []
|
|
1667
|
+
})
|
|
1668
|
+
}
|
|
1669
|
+
);
|
|
1670
|
+
return data.plan;
|
|
1671
|
+
}
|
|
1672
|
+
/**
|
|
1673
|
+
* List all plans for the merchant
|
|
1674
|
+
*/
|
|
1675
|
+
async listPlans() {
|
|
1676
|
+
const merchantId = await this.ensureMerchantId();
|
|
1677
|
+
const data = await this.fetch(
|
|
1678
|
+
`/api/subscriptions/plans?merchantId=${merchantId}`
|
|
1679
|
+
);
|
|
1680
|
+
return data.plans;
|
|
1681
|
+
}
|
|
1682
|
+
/**
|
|
1683
|
+
* Update a plan
|
|
1684
|
+
*/
|
|
1685
|
+
async updatePlan(planId, options) {
|
|
1686
|
+
const data = await this.fetch(
|
|
1687
|
+
`/api/subscriptions/plans/${planId}`,
|
|
1688
|
+
{
|
|
1689
|
+
method: "PUT",
|
|
1690
|
+
body: JSON.stringify(options)
|
|
1691
|
+
}
|
|
1692
|
+
);
|
|
1693
|
+
return data.plan;
|
|
1694
|
+
}
|
|
1695
|
+
/**
|
|
1696
|
+
* Deactivate a plan (stops new subscriptions)
|
|
1697
|
+
*/
|
|
1698
|
+
async deactivatePlan(planId) {
|
|
1699
|
+
await this.updatePlan(planId, { active: false });
|
|
1700
|
+
}
|
|
1701
|
+
// ═══════════════════════════════════════
|
|
1702
|
+
// SUBSCRIPTIONS
|
|
1703
|
+
// ═══════════════════════════════════════
|
|
1704
|
+
/**
|
|
1705
|
+
* Subscribe a customer to a plan
|
|
1706
|
+
*/
|
|
1707
|
+
async subscribe(options) {
|
|
1708
|
+
const data = await this.fetch("/api/subscriptions", {
|
|
1709
|
+
method: "POST",
|
|
1710
|
+
body: JSON.stringify({
|
|
1711
|
+
action: "subscribe",
|
|
1712
|
+
planId: options.planId,
|
|
1713
|
+
customerWallet: options.customerWallet,
|
|
1714
|
+
merchantWallet: options.merchantWallet || this.merchantWallet,
|
|
1715
|
+
customerEmail: options.customerEmail,
|
|
1716
|
+
metadata: options.metadata
|
|
1717
|
+
})
|
|
1718
|
+
});
|
|
1719
|
+
return data;
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* List subscriptions
|
|
1723
|
+
*/
|
|
1724
|
+
async listSubscriptions(options) {
|
|
1725
|
+
const merchantId = await this.ensureMerchantId();
|
|
1726
|
+
const params = new URLSearchParams({ merchantId });
|
|
1727
|
+
if (options?.status) params.set("status", options.status);
|
|
1728
|
+
if (options?.customerWallet)
|
|
1729
|
+
params.set("customer", options.customerWallet);
|
|
1730
|
+
if (options?.planId) params.set("planId", options.planId);
|
|
1731
|
+
const data = await this.fetch(
|
|
1732
|
+
`/api/subscriptions?${params.toString()}`
|
|
1733
|
+
);
|
|
1734
|
+
return data.subscriptions;
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Get subscription details including payment history
|
|
1738
|
+
*/
|
|
1739
|
+
async getSubscription(subscriptionId) {
|
|
1740
|
+
const data = await this.fetch(`/api/subscriptions/${subscriptionId}`);
|
|
1741
|
+
return {
|
|
1742
|
+
...data.subscription,
|
|
1743
|
+
payments: data.payments
|
|
1744
|
+
};
|
|
1745
|
+
}
|
|
1746
|
+
/**
|
|
1747
|
+
* Cancel a subscription
|
|
1748
|
+
* @param immediately - If true, cancels now. If false (default), cancels at end of billing period.
|
|
1749
|
+
*/
|
|
1750
|
+
async cancel(subscriptionId, immediately = false) {
|
|
1751
|
+
return this.fetch("/api/subscriptions", {
|
|
1752
|
+
method: "POST",
|
|
1753
|
+
body: JSON.stringify({
|
|
1754
|
+
action: "cancel",
|
|
1755
|
+
subscriptionId,
|
|
1756
|
+
immediately
|
|
1757
|
+
})
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
/**
|
|
1761
|
+
* Pause a subscription (stops billing, preserves subscription)
|
|
1762
|
+
*/
|
|
1763
|
+
async pause(subscriptionId) {
|
|
1764
|
+
return this.fetch("/api/subscriptions", {
|
|
1765
|
+
method: "POST",
|
|
1766
|
+
body: JSON.stringify({
|
|
1767
|
+
action: "pause",
|
|
1768
|
+
subscriptionId
|
|
1769
|
+
})
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
/**
|
|
1773
|
+
* Resume a paused subscription
|
|
1774
|
+
*/
|
|
1775
|
+
async resume(subscriptionId) {
|
|
1776
|
+
return this.fetch("/api/subscriptions", {
|
|
1777
|
+
method: "POST",
|
|
1778
|
+
body: JSON.stringify({
|
|
1779
|
+
action: "resume",
|
|
1780
|
+
subscriptionId
|
|
1781
|
+
})
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
/**
|
|
1785
|
+
* Manually charge a subscription (useful for metered billing)
|
|
1786
|
+
*/
|
|
1787
|
+
async charge(subscriptionId) {
|
|
1788
|
+
return this.fetch("/api/subscriptions", {
|
|
1789
|
+
method: "POST",
|
|
1790
|
+
body: JSON.stringify({
|
|
1791
|
+
action: "charge",
|
|
1792
|
+
subscriptionId
|
|
1793
|
+
})
|
|
1794
|
+
});
|
|
1795
|
+
}
|
|
1796
|
+
};
|
|
1797
|
+
function createSubscriptionClient(config) {
|
|
1798
|
+
return new SubscriptionClient(config);
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// src/payouts.ts
|
|
1802
|
+
var PayoutClient = class {
|
|
1803
|
+
constructor(config) {
|
|
1804
|
+
if (!config.apiKey) {
|
|
1805
|
+
throw new Error(
|
|
1806
|
+
"API key is required. Get one at https://settlr.dev/dashboard"
|
|
1807
|
+
);
|
|
1808
|
+
}
|
|
1809
|
+
this.apiKey = config.apiKey;
|
|
1810
|
+
this.baseUrl = (config.baseUrl || "https://settlr.dev").replace(/\/$/, "");
|
|
1811
|
+
}
|
|
1812
|
+
async fetch(path, options = {}) {
|
|
1813
|
+
const url = `${this.baseUrl}${path}`;
|
|
1814
|
+
const res = await fetch(url, {
|
|
1815
|
+
...options,
|
|
1816
|
+
headers: {
|
|
1817
|
+
"Content-Type": "application/json",
|
|
1818
|
+
"X-API-Key": this.apiKey,
|
|
1819
|
+
...options.headers
|
|
1820
|
+
}
|
|
1821
|
+
});
|
|
1822
|
+
const data = await res.json();
|
|
1823
|
+
if (!res.ok) {
|
|
1824
|
+
throw new Error(
|
|
1825
|
+
data.error || `Payout API error: ${res.status}`
|
|
1826
|
+
);
|
|
1827
|
+
}
|
|
1828
|
+
return data;
|
|
1829
|
+
}
|
|
1830
|
+
// -----------------------------------------------------------------------
|
|
1831
|
+
// Create a single payout
|
|
1832
|
+
// -----------------------------------------------------------------------
|
|
1833
|
+
/**
|
|
1834
|
+
* Send a payout to a recipient by email.
|
|
1835
|
+
* They'll receive an email with a claim link — no wallet or bank details needed.
|
|
1836
|
+
*
|
|
1837
|
+
* @example
|
|
1838
|
+
* ```typescript
|
|
1839
|
+
* const payout = await payouts.create({
|
|
1840
|
+
* email: 'alice@example.com',
|
|
1841
|
+
* amount: 250.00,
|
|
1842
|
+
* memo: 'March data labeling — 500 tasks',
|
|
1843
|
+
* });
|
|
1844
|
+
* console.log(payout.id); // "po_abc123"
|
|
1845
|
+
* console.log(payout.status); // "sent"
|
|
1846
|
+
* console.log(payout.claimUrl); // "https://settlr.dev/claim/..."
|
|
1847
|
+
* ```
|
|
1848
|
+
*/
|
|
1849
|
+
async create(options) {
|
|
1850
|
+
if (!options.email || !options.email.includes("@")) {
|
|
1851
|
+
throw new Error("Valid email address is required");
|
|
1852
|
+
}
|
|
1853
|
+
if (!options.amount || options.amount <= 0) {
|
|
1854
|
+
throw new Error("Amount must be a positive number");
|
|
1855
|
+
}
|
|
1856
|
+
return this.fetch("/api/payouts", {
|
|
1857
|
+
method: "POST",
|
|
1858
|
+
body: JSON.stringify({
|
|
1859
|
+
email: options.email,
|
|
1860
|
+
amount: options.amount,
|
|
1861
|
+
currency: options.currency || "USDC",
|
|
1862
|
+
memo: options.memo,
|
|
1863
|
+
metadata: options.metadata
|
|
1864
|
+
})
|
|
1865
|
+
});
|
|
1866
|
+
}
|
|
1867
|
+
// -----------------------------------------------------------------------
|
|
1868
|
+
// Create batch payouts
|
|
1869
|
+
// -----------------------------------------------------------------------
|
|
1870
|
+
/**
|
|
1871
|
+
* Send multiple payouts at once. Each recipient gets their own email.
|
|
1872
|
+
*
|
|
1873
|
+
* @example
|
|
1874
|
+
* ```typescript
|
|
1875
|
+
* const batch = await payouts.createBatch([
|
|
1876
|
+
* { email: 'alice@example.com', amount: 250.00, memo: 'March' },
|
|
1877
|
+
* { email: 'bob@example.com', amount: 180.00, memo: 'March' },
|
|
1878
|
+
* ]);
|
|
1879
|
+
* console.log(batch.id); // "batch_xyz"
|
|
1880
|
+
* console.log(batch.total); // 430.00
|
|
1881
|
+
* ```
|
|
1882
|
+
*/
|
|
1883
|
+
async createBatch(payoutsList) {
|
|
1884
|
+
if (!Array.isArray(payoutsList) || payoutsList.length === 0) {
|
|
1885
|
+
throw new Error("Payouts list must be a non-empty array");
|
|
1886
|
+
}
|
|
1887
|
+
return this.fetch("/api/payouts/batch", {
|
|
1888
|
+
method: "POST",
|
|
1889
|
+
body: JSON.stringify({ payouts: payoutsList })
|
|
1890
|
+
});
|
|
1891
|
+
}
|
|
1892
|
+
// -----------------------------------------------------------------------
|
|
1893
|
+
// Get a single payout
|
|
1894
|
+
// -----------------------------------------------------------------------
|
|
1895
|
+
/**
|
|
1896
|
+
* Get a payout by ID.
|
|
1897
|
+
*
|
|
1898
|
+
* @example
|
|
1899
|
+
* ```typescript
|
|
1900
|
+
* const payout = await payouts.get('po_abc123');
|
|
1901
|
+
* console.log(payout.status); // "claimed"
|
|
1902
|
+
* console.log(payout.claimedAt); // "2024-03-15T14:30:00Z"
|
|
1903
|
+
* ```
|
|
1904
|
+
*/
|
|
1905
|
+
async get(id) {
|
|
1906
|
+
if (!id) throw new Error("Payout ID is required");
|
|
1907
|
+
return this.fetch(`/api/payouts/${encodeURIComponent(id)}`);
|
|
1908
|
+
}
|
|
1909
|
+
// -----------------------------------------------------------------------
|
|
1910
|
+
// List payouts
|
|
1911
|
+
// -----------------------------------------------------------------------
|
|
1912
|
+
/**
|
|
1913
|
+
* List payouts for the authenticated merchant.
|
|
1914
|
+
*
|
|
1915
|
+
* @example
|
|
1916
|
+
* ```typescript
|
|
1917
|
+
* const result = await payouts.list({ status: 'claimed', limit: 50 });
|
|
1918
|
+
* result.data.forEach(p => console.log(p.email, p.amount, p.status));
|
|
1919
|
+
* ```
|
|
1920
|
+
*/
|
|
1921
|
+
async list(options) {
|
|
1922
|
+
const params = new URLSearchParams();
|
|
1923
|
+
if (options?.status) params.set("status", options.status);
|
|
1924
|
+
if (options?.limit) params.set("limit", options.limit.toString());
|
|
1925
|
+
if (options?.offset) params.set("offset", options.offset.toString());
|
|
1926
|
+
const qs = params.toString();
|
|
1927
|
+
return this.fetch(`/api/payouts${qs ? `?${qs}` : ""}`);
|
|
1928
|
+
}
|
|
1929
|
+
};
|
|
1930
|
+
function createPayoutClient(config) {
|
|
1931
|
+
return new PayoutClient(config);
|
|
1932
|
+
}
|
|
1589
1933
|
export {
|
|
1590
1934
|
BuyButton,
|
|
1591
1935
|
CheckoutWidget,
|
|
1592
1936
|
INCO_LIGHTNING_PROGRAM_ID,
|
|
1593
1937
|
OneClickClient,
|
|
1594
1938
|
PaymentModal,
|
|
1939
|
+
PayoutClient,
|
|
1595
1940
|
PrivacyFeatures,
|
|
1596
1941
|
REACT_NATIVE_EXAMPLE,
|
|
1597
1942
|
REST_API,
|
|
@@ -1601,6 +1946,7 @@ export {
|
|
|
1601
1946
|
SUPPORTED_TOKENS,
|
|
1602
1947
|
Settlr,
|
|
1603
1948
|
SettlrProvider,
|
|
1949
|
+
SubscriptionClient,
|
|
1604
1950
|
UNITY_EXAMPLE,
|
|
1605
1951
|
USDC_MINT_DEVNET,
|
|
1606
1952
|
USDC_MINT_MAINNET,
|
|
@@ -1609,6 +1955,8 @@ export {
|
|
|
1609
1955
|
buildAllowanceRemainingAccounts,
|
|
1610
1956
|
buildPrivateReceiptAccounts,
|
|
1611
1957
|
createOneClickClient,
|
|
1958
|
+
createPayoutClient,
|
|
1959
|
+
createSubscriptionClient,
|
|
1612
1960
|
createWebhookHandler,
|
|
1613
1961
|
encryptAmount,
|
|
1614
1962
|
findAllowancePda,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@settlr/sdk",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.7",
|
|
4
4
|
"description": "Settlr SDK - Accept Solana USDC payments with privacy. Email checkout, gasless transactions, FHE-encrypted receipts. Private on-chain, compliant off-chain.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|