@autopayprotocol/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,295 @@
1
+ type IntervalPreset = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';
2
+ interface CheckoutOptions {
3
+ /** Merchant wallet address (0x-prefixed, 40 hex chars) */
4
+ merchant: string;
5
+ /** Charge amount in human-readable USDC (e.g. 9.99) */
6
+ amount: number;
7
+ /** Billing interval — preset string, or seconds */
8
+ interval: IntervalPreset | number;
9
+ /** URL to plan metadata JSON */
10
+ metadataUrl: string;
11
+ /** Redirect URL on successful subscription */
12
+ successUrl: string;
13
+ /** Redirect URL on cancel */
14
+ cancelUrl: string;
15
+ /** Optional spending cap in human-readable USDC. Omit for unlimited. */
16
+ spendingCap?: number;
17
+ /** Optional base URL override (default: https://app.autopay.xyz) */
18
+ baseUrl?: string;
19
+ }
20
+ interface SuccessRedirect {
21
+ policyId: string;
22
+ txHash: string;
23
+ }
24
+ type WebhookEventType = 'charge.succeeded' | 'charge.failed' | 'policy.created' | 'policy.revoked' | 'policy.cancelled_by_failure';
25
+ interface WebhookBase {
26
+ timestamp: string;
27
+ data: {
28
+ policyId: string;
29
+ chainId: number;
30
+ payer: string;
31
+ merchant: string;
32
+ };
33
+ }
34
+ interface ChargeSucceededEvent extends WebhookBase {
35
+ type: 'charge.succeeded';
36
+ data: WebhookBase['data'] & {
37
+ amount: string;
38
+ protocolFee: string;
39
+ txHash: string;
40
+ };
41
+ }
42
+ interface ChargeFailedEvent extends WebhookBase {
43
+ type: 'charge.failed';
44
+ data: WebhookBase['data'] & {
45
+ reason: string;
46
+ };
47
+ }
48
+ interface PolicyCreatedEvent extends WebhookBase {
49
+ type: 'policy.created';
50
+ data: WebhookBase['data'] & {
51
+ chargeAmount: string;
52
+ interval: number;
53
+ spendingCap: string;
54
+ metadataUrl: string;
55
+ };
56
+ }
57
+ interface PolicyRevokedEvent extends WebhookBase {
58
+ type: 'policy.revoked';
59
+ data: WebhookBase['data'] & {
60
+ endTime: number;
61
+ };
62
+ }
63
+ interface PolicyCancelledByFailureEvent extends WebhookBase {
64
+ type: 'policy.cancelled_by_failure';
65
+ data: WebhookBase['data'] & {
66
+ consecutiveFailures: number;
67
+ endTime: number;
68
+ };
69
+ }
70
+ type WebhookEvent = ChargeSucceededEvent | ChargeFailedEvent | PolicyCreatedEvent | PolicyRevokedEvent | PolicyCancelledByFailureEvent;
71
+ interface CheckoutMetadata {
72
+ version: string;
73
+ plan: {
74
+ name: string;
75
+ description: string;
76
+ tier?: string;
77
+ features?: string[];
78
+ };
79
+ merchant: {
80
+ name: string;
81
+ logo?: string;
82
+ website?: string;
83
+ supportEmail?: string;
84
+ };
85
+ display?: {
86
+ color?: string;
87
+ badge?: string;
88
+ };
89
+ }
90
+ interface FeeBreakdown {
91
+ /** Total charge in human-readable USDC (e.g. "9.99") */
92
+ total: string;
93
+ /** Amount merchant receives after fee */
94
+ merchantReceives: string;
95
+ /** Protocol fee deducted */
96
+ protocolFee: string;
97
+ /** Fee as percentage string (e.g. "2.5%") */
98
+ feePercentage: string;
99
+ }
100
+
101
+ declare class AutoPayError extends Error {
102
+ readonly code: string;
103
+ constructor(message: string, code: string);
104
+ }
105
+ declare class AutoPayWebhookError extends AutoPayError {
106
+ constructor(message: string);
107
+ }
108
+ declare class AutoPayCheckoutError extends AutoPayError {
109
+ constructor(message: string);
110
+ }
111
+ declare class AutoPayMetadataError extends AutoPayError {
112
+ constructor(message: string);
113
+ }
114
+
115
+ declare const intervals: {
116
+ /** 1 minute — useful for testing */
117
+ readonly minute: 60;
118
+ /** 7 days */
119
+ readonly weekly: 604800;
120
+ /** 14 days */
121
+ readonly biweekly: 1209600;
122
+ /** 30 days */
123
+ readonly monthly: 2592000;
124
+ /** 90 days */
125
+ readonly quarterly: 7776000;
126
+ /** 365 days */
127
+ readonly yearly: 31536000;
128
+ /** Build a custom interval from a count and unit */
129
+ readonly custom: (count: number, unit: "minutes" | "hours" | "days" | "months" | "years") => number;
130
+ };
131
+ /** Protocol fee in basis points (2.5%) */
132
+ declare const PROTOCOL_FEE_BPS = 250;
133
+ /** USDC uses 6 decimals */
134
+ declare const USDC_DECIMALS = 6;
135
+ /** Minimum interval (1 minute) */
136
+ declare const MIN_INTERVAL = 60;
137
+ /** Maximum interval (365 days) */
138
+ declare const MAX_INTERVAL = 31536000;
139
+ /** Max consecutive failures before auto-cancel */
140
+ declare const MAX_RETRIES = 3;
141
+ interface ChainConfig {
142
+ name: string;
143
+ chainId: number;
144
+ cctpDomain: number;
145
+ usdc: string;
146
+ explorer: string;
147
+ }
148
+ declare const chains: Record<string, ChainConfig>;
149
+ /** Default checkout base URL */
150
+ declare const DEFAULT_CHECKOUT_BASE_URL = "https://app.autopay.xyz";
151
+
152
+ /** Resolve an interval preset or number to seconds */
153
+ declare function resolveInterval(interval: IntervalPreset | number): number;
154
+ /**
155
+ * Build a checkout URL that a merchant can redirect users to.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * const url = createCheckoutUrl({
160
+ * merchant: '0x2B8b...',
161
+ * amount: 9.99,
162
+ * interval: 'monthly',
163
+ * metadataUrl: 'https://mysite.com/plans/pro.json',
164
+ * successUrl: 'https://mysite.com/success',
165
+ * cancelUrl: 'https://mysite.com/cancel',
166
+ * })
167
+ * ```
168
+ */
169
+ declare function createCheckoutUrl(options: CheckoutOptions): string;
170
+ /**
171
+ * Parse the query params from the success redirect URL.
172
+ *
173
+ * After a user subscribes, they are redirected to the merchant's `successUrl`
174
+ * with `?policyId=0x...&txHash=0x...` appended.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * // On your success page:
179
+ * const { policyId, txHash } = parseSuccessRedirect(window.location.search)
180
+ * ```
181
+ */
182
+ declare function parseSuccessRedirect(queryString: string): SuccessRedirect;
183
+
184
+ /**
185
+ * Sign a payload string with HMAC-SHA256.
186
+ * Used by the relayer — exposed here so merchants can test locally.
187
+ */
188
+ declare function signPayload(payload: string, secret: string): string;
189
+ /**
190
+ * Verify an HMAC-SHA256 signature using constant-time comparison.
191
+ */
192
+ declare function verifySignature(payload: string, signature: string, secret: string): boolean;
193
+ /**
194
+ * Verify and parse a webhook from AutoPay.
195
+ *
196
+ * @param rawBody - The raw request body string (JSON.stringify of the body)
197
+ * @param signature - The `x-autopay-signature` header value
198
+ * @param secret - Your webhook secret
199
+ * @returns A fully-typed {@link WebhookEvent} with discriminated union on `type`
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * const event = verifyWebhook(rawBody, req.headers['x-autopay-signature'], secret)
204
+ * if (event.type === 'charge.succeeded') {
205
+ * console.log(event.data.amount) // TypeScript knows this exists
206
+ * }
207
+ * ```
208
+ */
209
+ declare function verifyWebhook(rawBody: string, signature: string | undefined, secret: string): WebhookEvent;
210
+
211
+ /**
212
+ * Format a raw USDC amount (6-decimal string) to a human-readable string.
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * formatUSDC('9990000') // "9.99"
217
+ * formatUSDC('100000') // "0.10"
218
+ * ```
219
+ */
220
+ declare function formatUSDC(rawAmount: string): string;
221
+ /**
222
+ * Parse a human-readable USDC amount to a raw 6-decimal string.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * parseUSDC(9.99) // "9990000"
227
+ * parseUSDC(0.10) // "100000"
228
+ * ```
229
+ */
230
+ declare function parseUSDC(amount: number): string;
231
+ /**
232
+ * Calculate the fee breakdown for a charge amount.
233
+ *
234
+ * @param rawAmount - Raw USDC amount (6-decimal string) OR human-readable number
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * calculateFeeBreakdown('9990000')
239
+ * // { total: "9.99", merchantReceives: "9.74", protocolFee: "0.25", feePercentage: "2.5%" }
240
+ * ```
241
+ */
242
+ declare function calculateFeeBreakdown(rawAmount: string): FeeBreakdown;
243
+ /**
244
+ * Format an interval in seconds to a human-readable label.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * formatInterval(2592000) // "monthly"
249
+ * formatInterval(604800) // "weekly"
250
+ * formatInterval(86400) // "1 day"
251
+ * formatInterval(172800) // "2 days"
252
+ * ```
253
+ */
254
+ declare function formatInterval(seconds: number): string;
255
+
256
+ interface MetadataValidationResult {
257
+ valid: boolean;
258
+ errors: string[];
259
+ }
260
+ /**
261
+ * Validate a metadata JSON object against the AutoPay metadata schema.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * const { valid, errors } = validateMetadata(jsonData)
266
+ * if (!valid) console.error(errors)
267
+ * ```
268
+ */
269
+ declare function validateMetadata(data: unknown): MetadataValidationResult;
270
+ /**
271
+ * Create a valid metadata object with sensible defaults.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const metadata = createMetadata({
276
+ * planName: 'Pro',
277
+ * planDescription: 'All premium features',
278
+ * merchantName: 'Acme Corp',
279
+ * })
280
+ * ```
281
+ */
282
+ declare function createMetadata(options: {
283
+ planName: string;
284
+ planDescription: string;
285
+ merchantName: string;
286
+ tier?: string;
287
+ features?: string[];
288
+ logo?: string;
289
+ website?: string;
290
+ supportEmail?: string;
291
+ color?: string;
292
+ badge?: string;
293
+ }): CheckoutMetadata;
294
+
295
+ export { AutoPayCheckoutError, AutoPayError, AutoPayMetadataError, AutoPayWebhookError, type ChainConfig, type ChargeFailedEvent, type ChargeSucceededEvent, type CheckoutMetadata, type CheckoutOptions, DEFAULT_CHECKOUT_BASE_URL, type FeeBreakdown, type IntervalPreset, MAX_INTERVAL, MAX_RETRIES, MIN_INTERVAL, type MetadataValidationResult, PROTOCOL_FEE_BPS, type PolicyCancelledByFailureEvent, type PolicyCreatedEvent, type PolicyRevokedEvent, type SuccessRedirect, USDC_DECIMALS, type WebhookEvent, type WebhookEventType, calculateFeeBreakdown, chains, createCheckoutUrl, createMetadata, formatInterval, formatUSDC, intervals, parseSuccessRedirect, parseUSDC, resolveInterval, signPayload, validateMetadata, verifySignature, verifyWebhook };
@@ -0,0 +1,295 @@
1
+ type IntervalPreset = 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly';
2
+ interface CheckoutOptions {
3
+ /** Merchant wallet address (0x-prefixed, 40 hex chars) */
4
+ merchant: string;
5
+ /** Charge amount in human-readable USDC (e.g. 9.99) */
6
+ amount: number;
7
+ /** Billing interval — preset string, or seconds */
8
+ interval: IntervalPreset | number;
9
+ /** URL to plan metadata JSON */
10
+ metadataUrl: string;
11
+ /** Redirect URL on successful subscription */
12
+ successUrl: string;
13
+ /** Redirect URL on cancel */
14
+ cancelUrl: string;
15
+ /** Optional spending cap in human-readable USDC. Omit for unlimited. */
16
+ spendingCap?: number;
17
+ /** Optional base URL override (default: https://app.autopay.xyz) */
18
+ baseUrl?: string;
19
+ }
20
+ interface SuccessRedirect {
21
+ policyId: string;
22
+ txHash: string;
23
+ }
24
+ type WebhookEventType = 'charge.succeeded' | 'charge.failed' | 'policy.created' | 'policy.revoked' | 'policy.cancelled_by_failure';
25
+ interface WebhookBase {
26
+ timestamp: string;
27
+ data: {
28
+ policyId: string;
29
+ chainId: number;
30
+ payer: string;
31
+ merchant: string;
32
+ };
33
+ }
34
+ interface ChargeSucceededEvent extends WebhookBase {
35
+ type: 'charge.succeeded';
36
+ data: WebhookBase['data'] & {
37
+ amount: string;
38
+ protocolFee: string;
39
+ txHash: string;
40
+ };
41
+ }
42
+ interface ChargeFailedEvent extends WebhookBase {
43
+ type: 'charge.failed';
44
+ data: WebhookBase['data'] & {
45
+ reason: string;
46
+ };
47
+ }
48
+ interface PolicyCreatedEvent extends WebhookBase {
49
+ type: 'policy.created';
50
+ data: WebhookBase['data'] & {
51
+ chargeAmount: string;
52
+ interval: number;
53
+ spendingCap: string;
54
+ metadataUrl: string;
55
+ };
56
+ }
57
+ interface PolicyRevokedEvent extends WebhookBase {
58
+ type: 'policy.revoked';
59
+ data: WebhookBase['data'] & {
60
+ endTime: number;
61
+ };
62
+ }
63
+ interface PolicyCancelledByFailureEvent extends WebhookBase {
64
+ type: 'policy.cancelled_by_failure';
65
+ data: WebhookBase['data'] & {
66
+ consecutiveFailures: number;
67
+ endTime: number;
68
+ };
69
+ }
70
+ type WebhookEvent = ChargeSucceededEvent | ChargeFailedEvent | PolicyCreatedEvent | PolicyRevokedEvent | PolicyCancelledByFailureEvent;
71
+ interface CheckoutMetadata {
72
+ version: string;
73
+ plan: {
74
+ name: string;
75
+ description: string;
76
+ tier?: string;
77
+ features?: string[];
78
+ };
79
+ merchant: {
80
+ name: string;
81
+ logo?: string;
82
+ website?: string;
83
+ supportEmail?: string;
84
+ };
85
+ display?: {
86
+ color?: string;
87
+ badge?: string;
88
+ };
89
+ }
90
+ interface FeeBreakdown {
91
+ /** Total charge in human-readable USDC (e.g. "9.99") */
92
+ total: string;
93
+ /** Amount merchant receives after fee */
94
+ merchantReceives: string;
95
+ /** Protocol fee deducted */
96
+ protocolFee: string;
97
+ /** Fee as percentage string (e.g. "2.5%") */
98
+ feePercentage: string;
99
+ }
100
+
101
+ declare class AutoPayError extends Error {
102
+ readonly code: string;
103
+ constructor(message: string, code: string);
104
+ }
105
+ declare class AutoPayWebhookError extends AutoPayError {
106
+ constructor(message: string);
107
+ }
108
+ declare class AutoPayCheckoutError extends AutoPayError {
109
+ constructor(message: string);
110
+ }
111
+ declare class AutoPayMetadataError extends AutoPayError {
112
+ constructor(message: string);
113
+ }
114
+
115
+ declare const intervals: {
116
+ /** 1 minute — useful for testing */
117
+ readonly minute: 60;
118
+ /** 7 days */
119
+ readonly weekly: 604800;
120
+ /** 14 days */
121
+ readonly biweekly: 1209600;
122
+ /** 30 days */
123
+ readonly monthly: 2592000;
124
+ /** 90 days */
125
+ readonly quarterly: 7776000;
126
+ /** 365 days */
127
+ readonly yearly: 31536000;
128
+ /** Build a custom interval from a count and unit */
129
+ readonly custom: (count: number, unit: "minutes" | "hours" | "days" | "months" | "years") => number;
130
+ };
131
+ /** Protocol fee in basis points (2.5%) */
132
+ declare const PROTOCOL_FEE_BPS = 250;
133
+ /** USDC uses 6 decimals */
134
+ declare const USDC_DECIMALS = 6;
135
+ /** Minimum interval (1 minute) */
136
+ declare const MIN_INTERVAL = 60;
137
+ /** Maximum interval (365 days) */
138
+ declare const MAX_INTERVAL = 31536000;
139
+ /** Max consecutive failures before auto-cancel */
140
+ declare const MAX_RETRIES = 3;
141
+ interface ChainConfig {
142
+ name: string;
143
+ chainId: number;
144
+ cctpDomain: number;
145
+ usdc: string;
146
+ explorer: string;
147
+ }
148
+ declare const chains: Record<string, ChainConfig>;
149
+ /** Default checkout base URL */
150
+ declare const DEFAULT_CHECKOUT_BASE_URL = "https://app.autopay.xyz";
151
+
152
+ /** Resolve an interval preset or number to seconds */
153
+ declare function resolveInterval(interval: IntervalPreset | number): number;
154
+ /**
155
+ * Build a checkout URL that a merchant can redirect users to.
156
+ *
157
+ * @example
158
+ * ```ts
159
+ * const url = createCheckoutUrl({
160
+ * merchant: '0x2B8b...',
161
+ * amount: 9.99,
162
+ * interval: 'monthly',
163
+ * metadataUrl: 'https://mysite.com/plans/pro.json',
164
+ * successUrl: 'https://mysite.com/success',
165
+ * cancelUrl: 'https://mysite.com/cancel',
166
+ * })
167
+ * ```
168
+ */
169
+ declare function createCheckoutUrl(options: CheckoutOptions): string;
170
+ /**
171
+ * Parse the query params from the success redirect URL.
172
+ *
173
+ * After a user subscribes, they are redirected to the merchant's `successUrl`
174
+ * with `?policyId=0x...&txHash=0x...` appended.
175
+ *
176
+ * @example
177
+ * ```ts
178
+ * // On your success page:
179
+ * const { policyId, txHash } = parseSuccessRedirect(window.location.search)
180
+ * ```
181
+ */
182
+ declare function parseSuccessRedirect(queryString: string): SuccessRedirect;
183
+
184
+ /**
185
+ * Sign a payload string with HMAC-SHA256.
186
+ * Used by the relayer — exposed here so merchants can test locally.
187
+ */
188
+ declare function signPayload(payload: string, secret: string): string;
189
+ /**
190
+ * Verify an HMAC-SHA256 signature using constant-time comparison.
191
+ */
192
+ declare function verifySignature(payload: string, signature: string, secret: string): boolean;
193
+ /**
194
+ * Verify and parse a webhook from AutoPay.
195
+ *
196
+ * @param rawBody - The raw request body string (JSON.stringify of the body)
197
+ * @param signature - The `x-autopay-signature` header value
198
+ * @param secret - Your webhook secret
199
+ * @returns A fully-typed {@link WebhookEvent} with discriminated union on `type`
200
+ *
201
+ * @example
202
+ * ```ts
203
+ * const event = verifyWebhook(rawBody, req.headers['x-autopay-signature'], secret)
204
+ * if (event.type === 'charge.succeeded') {
205
+ * console.log(event.data.amount) // TypeScript knows this exists
206
+ * }
207
+ * ```
208
+ */
209
+ declare function verifyWebhook(rawBody: string, signature: string | undefined, secret: string): WebhookEvent;
210
+
211
+ /**
212
+ * Format a raw USDC amount (6-decimal string) to a human-readable string.
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * formatUSDC('9990000') // "9.99"
217
+ * formatUSDC('100000') // "0.10"
218
+ * ```
219
+ */
220
+ declare function formatUSDC(rawAmount: string): string;
221
+ /**
222
+ * Parse a human-readable USDC amount to a raw 6-decimal string.
223
+ *
224
+ * @example
225
+ * ```ts
226
+ * parseUSDC(9.99) // "9990000"
227
+ * parseUSDC(0.10) // "100000"
228
+ * ```
229
+ */
230
+ declare function parseUSDC(amount: number): string;
231
+ /**
232
+ * Calculate the fee breakdown for a charge amount.
233
+ *
234
+ * @param rawAmount - Raw USDC amount (6-decimal string) OR human-readable number
235
+ *
236
+ * @example
237
+ * ```ts
238
+ * calculateFeeBreakdown('9990000')
239
+ * // { total: "9.99", merchantReceives: "9.74", protocolFee: "0.25", feePercentage: "2.5%" }
240
+ * ```
241
+ */
242
+ declare function calculateFeeBreakdown(rawAmount: string): FeeBreakdown;
243
+ /**
244
+ * Format an interval in seconds to a human-readable label.
245
+ *
246
+ * @example
247
+ * ```ts
248
+ * formatInterval(2592000) // "monthly"
249
+ * formatInterval(604800) // "weekly"
250
+ * formatInterval(86400) // "1 day"
251
+ * formatInterval(172800) // "2 days"
252
+ * ```
253
+ */
254
+ declare function formatInterval(seconds: number): string;
255
+
256
+ interface MetadataValidationResult {
257
+ valid: boolean;
258
+ errors: string[];
259
+ }
260
+ /**
261
+ * Validate a metadata JSON object against the AutoPay metadata schema.
262
+ *
263
+ * @example
264
+ * ```ts
265
+ * const { valid, errors } = validateMetadata(jsonData)
266
+ * if (!valid) console.error(errors)
267
+ * ```
268
+ */
269
+ declare function validateMetadata(data: unknown): MetadataValidationResult;
270
+ /**
271
+ * Create a valid metadata object with sensible defaults.
272
+ *
273
+ * @example
274
+ * ```ts
275
+ * const metadata = createMetadata({
276
+ * planName: 'Pro',
277
+ * planDescription: 'All premium features',
278
+ * merchantName: 'Acme Corp',
279
+ * })
280
+ * ```
281
+ */
282
+ declare function createMetadata(options: {
283
+ planName: string;
284
+ planDescription: string;
285
+ merchantName: string;
286
+ tier?: string;
287
+ features?: string[];
288
+ logo?: string;
289
+ website?: string;
290
+ supportEmail?: string;
291
+ color?: string;
292
+ badge?: string;
293
+ }): CheckoutMetadata;
294
+
295
+ export { AutoPayCheckoutError, AutoPayError, AutoPayMetadataError, AutoPayWebhookError, type ChainConfig, type ChargeFailedEvent, type ChargeSucceededEvent, type CheckoutMetadata, type CheckoutOptions, DEFAULT_CHECKOUT_BASE_URL, type FeeBreakdown, type IntervalPreset, MAX_INTERVAL, MAX_RETRIES, MIN_INTERVAL, type MetadataValidationResult, PROTOCOL_FEE_BPS, type PolicyCancelledByFailureEvent, type PolicyCreatedEvent, type PolicyRevokedEvent, type SuccessRedirect, USDC_DECIMALS, type WebhookEvent, type WebhookEventType, calculateFeeBreakdown, chains, createCheckoutUrl, createMetadata, formatInterval, formatUSDC, intervals, parseSuccessRedirect, parseUSDC, resolveInterval, signPayload, validateMetadata, verifySignature, verifyWebhook };