@stackup-fi/sdk 1.0.11 → 1.0.12

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/README.md CHANGED
@@ -1,15 +1,38 @@
1
- # stackup
1
+ # @stackup-fi/sdk
2
2
 
3
- To install dependencies:
3
+ Official TypeScript SDK for Stackup Pay.
4
+
5
+ ## Installation
4
6
 
5
7
  ```bash
6
- bun install
8
+ npm install @stackup-fi/sdk
7
9
  ```
8
10
 
9
- To run:
11
+ ## Usage
10
12
 
11
- ```bash
12
- bun run index.ts
13
+ ```typescript
14
+ import { createStackup } from "@stackup-fi/sdk";
15
+
16
+ const { client } = createStackup({
17
+ accessToken: process.env.STACKUP_SECRET_KEY,
18
+ });
19
+
20
+ // Create a product
21
+ const product = await client.product.create({
22
+ payoutWalletAddress: "0xd4E5aA212d7b9CD781E0708B5A3764c949E4Ce95",
23
+ chain: "8453",
24
+ currency: "USDC",
25
+ amount: 29.99,
26
+ });
27
+
28
+ // Create a checkout session
29
+ const checkout = await client.checkout.session.create({
30
+ items: [{ product: product.data.id }],
31
+ });
32
+
33
+ console.log(checkout.data.url);
13
34
  ```
14
35
 
15
- This project was created using `bun init` in bun v1.3.3. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
36
+ ## API Reference
37
+
38
+ See [stackup.finance/docs](https://stackup.finance/docs) for full documentation.
@@ -0,0 +1,15 @@
1
+ import type { CheckoutEventMap, CheckoutEvent, CheckoutOptions } from "./types.js";
2
+ export declare class StackupCheckout {
3
+ private sessionId;
4
+ private options?;
5
+ private iframe;
6
+ private container;
7
+ private listeners;
8
+ private origin;
9
+ constructor(sessionId: string, options?: CheckoutOptions | undefined);
10
+ mount(selector: string | HTMLElement): void;
11
+ unmount(): void;
12
+ on<E extends CheckoutEvent>(event: E, callback: (data: CheckoutEventMap[E]) => void): () => void;
13
+ private buildUrl;
14
+ private handleMessage;
15
+ }
@@ -0,0 +1,72 @@
1
+ export class StackupCheckout {
2
+ sessionId;
3
+ options;
4
+ iframe = null;
5
+ container = null;
6
+ listeners = new Map();
7
+ origin;
8
+ constructor(sessionId, options) {
9
+ this.sessionId = sessionId;
10
+ this.options = options;
11
+ this.origin = options?.baseUrl ?? window.location.origin;
12
+ }
13
+ mount(selector) {
14
+ if (this.iframe)
15
+ throw new Error("Already mounted. Call unmount() first.");
16
+ this.container =
17
+ typeof selector === "string"
18
+ ? document.querySelector(selector)
19
+ : selector;
20
+ if (!this.container)
21
+ throw new Error("Container not found");
22
+ this.iframe = document.createElement("iframe");
23
+ this.iframe.src = this.buildUrl();
24
+ console.log("iframe", this.iframe.src);
25
+ this.iframe.style.cssText = "border:none;width:100%;min-height:400px;";
26
+ this.iframe.allow = "clipboard-write";
27
+ this.iframe.addEventListener("error", () => {
28
+ this.listeners
29
+ .get("error")
30
+ ?.forEach((cb) => cb({ message: "Failed to load checkout" }));
31
+ });
32
+ window.addEventListener("message", this.handleMessage);
33
+ this.container.appendChild(this.iframe);
34
+ }
35
+ unmount() {
36
+ if (!this.iframe)
37
+ return;
38
+ window.removeEventListener("message", this.handleMessage);
39
+ this.iframe.remove();
40
+ this.iframe = null;
41
+ this.container = null;
42
+ this.listeners.clear();
43
+ }
44
+ on(event, callback) {
45
+ if (!this.listeners.has(event))
46
+ this.listeners.set(event, new Set());
47
+ this.listeners.get(event).add(callback);
48
+ return () => this.listeners.get(event)?.delete(callback);
49
+ }
50
+ buildUrl() {
51
+ const url = new URL(`/c/${this.sessionId}`, this.origin);
52
+ url.searchParams.set("embedded", "1");
53
+ url.searchParams.set("origin", window.location.origin);
54
+ if (this.options?.theme) {
55
+ url.searchParams.set("theme", JSON.stringify(this.options.theme));
56
+ }
57
+ return url.toString();
58
+ }
59
+ handleMessage = (event) => {
60
+ if (event.origin !== this.origin)
61
+ return;
62
+ if (event.source !== this.iframe?.contentWindow)
63
+ return;
64
+ const { type, data } = event.data ?? {};
65
+ if (!type || !this.listeners.has(type))
66
+ return;
67
+ this.listeners.get(type)?.forEach((cb) => cb(data));
68
+ if (type === "resize" && this.iframe && data?.height) {
69
+ this.iframe.style.height = `${data.height}px`;
70
+ }
71
+ };
72
+ }
@@ -0,0 +1,5 @@
1
+ export type { CheckoutOptions, CheckoutTheme, CheckoutEventMap, CheckoutEvent, CompleteEvent, ErrorEvent, CancelledEvent, ResizeEvent, } from "./types.js";
2
+ export { StackupCheckout } from "./checkout.js";
3
+ import type { CheckoutOptions } from "./types.js";
4
+ import { StackupCheckout } from "./checkout.js";
5
+ export declare function loadStackupCheckout(sessionId: string, options?: CheckoutOptions): StackupCheckout;
@@ -0,0 +1,5 @@
1
+ export { StackupCheckout } from "./checkout.js";
2
+ import { StackupCheckout } from "./checkout.js";
3
+ export function loadStackupCheckout(sessionId, options) {
4
+ return new StackupCheckout(sessionId, options);
5
+ }
@@ -0,0 +1,31 @@
1
+ export interface CheckoutTheme {
2
+ primary?: string;
3
+ background?: string;
4
+ radius?: "none" | "sm" | "md" | "lg" | "full";
5
+ font?: string;
6
+ }
7
+ export interface CheckoutOptions {
8
+ baseUrl?: string;
9
+ theme?: Partial<CheckoutTheme>;
10
+ }
11
+ export interface CompleteEvent {
12
+ sessionId: string;
13
+ transactionHash: string;
14
+ }
15
+ export interface ErrorEvent {
16
+ message: string;
17
+ }
18
+ export interface CancelledEvent {
19
+ reason: "user_rejected";
20
+ }
21
+ export interface ResizeEvent {
22
+ height: number;
23
+ }
24
+ export type CheckoutEventMap = {
25
+ ready: undefined;
26
+ complete: CompleteEvent;
27
+ error: ErrorEvent;
28
+ cancelled: CancelledEvent;
29
+ resize: ResizeEvent;
30
+ };
31
+ export type CheckoutEvent = keyof CheckoutEventMap;
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ export function createStackup(options) {
6
6
  headers: {
7
7
  Authorization: `Bearer ${options.accessToken}`,
8
8
  },
9
- baseUrl: options.baseUrl ?? "https://api.stackup.finance",
9
+ baseUrl: options.baseUrl ?? process.env.STACKUP_BASE_URL ?? "https://api.stackup.finance",
10
10
  });
11
11
  return {
12
12
  client,
@@ -1,4 +1,3 @@
1
- import { type CheckArgs, type CheckResult, type WebhookArgs } from "./types.js";
1
+ import { type WebhookArgs } from "./types.js";
2
2
  export * from "./types.js";
3
- export declare function notify(args: CheckArgs): Promise<CheckResult>;
4
- export declare function notify(args: WebhookArgs): (req: Request) => Promise<Response>;
3
+ export declare function notify(config: WebhookArgs): (req: Request) => Promise<Response>;
@@ -1,28 +1,7 @@
1
- import { createClient } from "../v1/gen/client/client.gen.js";
2
- import { StackupClient } from "../v1/gen/sdk.gen.js";
3
1
  import { verifyTimestamp } from "./util.js";
4
2
  export * from "./types.js";
5
3
  const DEFAULT_TOLERANCE = 300; // 5 minutes
6
- export function notify(args) {
7
- if (args.mode === "check")
8
- return check(args);
9
- return webhook(args);
10
- }
11
- async function check(args) {
12
- const client = new StackupClient({
13
- client: createClient({
14
- baseUrl: args.baseUrl ?? "https://api.stackup.finance",
15
- headers: {
16
- Authorization: `Bearer ${args.accessToken}`,
17
- },
18
- }),
19
- });
20
- return client.customer.check({
21
- customerID: args.customerID,
22
- productID: args.productID,
23
- });
24
- }
25
- function webhook(config) {
4
+ export function notify(config) {
26
5
  const tolerance = config.tolerance ?? DEFAULT_TOLERANCE;
27
6
  return async (req) => {
28
7
  const timestamp = req.headers.get("x-webhook-timestamp");
@@ -1,7 +1,5 @@
1
1
  type Address = `0x${string}`;
2
2
  type Hex = `0x${string}`;
3
- import type { CustomerCheckErrors, CustomerCheckResponses } from "../v1/gen/types.gen.js";
4
- import type { RequestResult } from "../v1/gen/client/types.gen.js";
5
3
  type Prettify<T> = {
6
4
  [K in keyof T]: Prettify<T[K]>;
7
5
  } & {};
@@ -26,20 +24,11 @@ export type WebhookEvent = Prettify<{
26
24
  payment: Payment;
27
25
  };
28
26
  }>;
29
- export interface CheckArgs {
30
- mode: "check";
31
- accessToken: string;
32
- customerID: string;
33
- productID: string;
34
- baseUrl?: string;
35
- }
36
27
  export interface WebhookArgs {
37
- mode: "webhook";
38
28
  secret: string;
39
29
  tolerance?: number;
40
30
  handler: WebhookHandler;
41
31
  }
42
- export type CheckResult = RequestResult<CustomerCheckResponses, CustomerCheckErrors, false>;
43
32
  export type WebhookHandler = (event: WebhookEvent) => Promise<void>;
44
33
  export declare class WebhookError extends Error {
45
34
  code: "invalid_signature" | "invalid_timestamp" | "invalid_payload";
@@ -86,15 +86,10 @@ export declare class Product extends HeyApiClient {
86
86
  * Create a new product
87
87
  */
88
88
  create<ThrowOnError extends boolean = false>(parameters?: {
89
- id?: string;
90
89
  payoutWalletAddress?: string;
91
90
  chain?: "1" | "8453";
92
91
  currency?: "USDC";
93
92
  amount?: number;
94
- supply?: number | null;
95
- name?: string;
96
- description?: string | null;
97
- tokens?: Array<string> | null;
98
93
  }, options?: Options<never, ThrowOnError>): import("./client/types.gen.js").RequestResult<ProductCreateResponses, ProductCreateErrors, ThrowOnError, "fields">;
99
94
  /**
100
95
  * List products
@@ -147,56 +142,20 @@ export declare class Session extends HeyApiClient {
147
142
  /**
148
143
  * Create checkout session
149
144
  *
150
- * Generate a checkout session URL for one or more products. Customer is optional - if not provided, a customer will be created from the buyer's wallet address at payment time.
145
+ * Generate a checkout session URL for one or more products.
151
146
  *
152
147
  * ```ts
153
148
  * const session = await client.checkout.session.create({
154
- * items: [
155
- * { product: "prd_01ABC123", qty: 1 },
156
- * { product: "prd_01DEF456", qty: 2 },
157
- * ],
158
- * customer: "cus_01DEF456", // optional
159
- * theme: {
160
- * primary: { light: "#7c3aed", dark: "#a78bfa" },
161
- * background: { light: "#ffffff", dark: "#0b1220" },
162
- * radius: "lg",
163
- * }
149
+ * items: [{ product: "prd_01ABC123" }],
164
150
  * });
165
151
  * console.log(session.url);
166
152
  * ```
167
153
  */
168
154
  create<ThrowOnError extends boolean = false>(parameters?: {
155
+ type?: "hosted" | "embedded";
169
156
  items?: Array<{
170
157
  product: string;
171
- mode?: "required" | "optional" | "pick";
172
- quantity?: number;
173
- default?: boolean;
174
- editable?: boolean;
175
- max?: number | null;
176
- group?: string | null;
177
158
  }>;
178
- customer?: string | null;
179
- theme?: {
180
- primary?: string | {
181
- light: string;
182
- dark: string;
183
- };
184
- background?: string | {
185
- light: string;
186
- dark: string;
187
- };
188
- radius?: "none" | "sm" | "md" | "lg" | "full";
189
- font?: {
190
- family?: string;
191
- scale?: string;
192
- };
193
- logo?: string | {
194
- light: string;
195
- dark: string;
196
- };
197
- favicon?: string;
198
- css?: string;
199
- } | null;
200
159
  }, options?: Options<never, ThrowOnError>): import("./client/types.gen.js").RequestResult<CheckoutSessionCreateResponses, CheckoutSessionCreateErrors, ThrowOnError, "fields">;
201
160
  }
202
161
  export declare class Checkout extends HeyApiClient {
@@ -140,15 +140,10 @@ export class Product extends HeyApiClient {
140
140
  const params = buildClientParams([parameters], [
141
141
  {
142
142
  args: [
143
- { in: "body", key: "id" },
144
143
  { in: "body", key: "payoutWalletAddress" },
145
144
  { in: "body", key: "chain" },
146
145
  { in: "body", key: "currency" },
147
146
  { in: "body", key: "amount" },
148
- { in: "body", key: "supply" },
149
- { in: "body", key: "name" },
150
- { in: "body", key: "description" },
151
- { in: "body", key: "tokens" },
152
147
  ],
153
148
  },
154
149
  ]);
@@ -250,20 +245,11 @@ export class Session extends HeyApiClient {
250
245
  /**
251
246
  * Create checkout session
252
247
  *
253
- * Generate a checkout session URL for one or more products. Customer is optional - if not provided, a customer will be created from the buyer's wallet address at payment time.
248
+ * Generate a checkout session URL for one or more products.
254
249
  *
255
250
  * ```ts
256
251
  * const session = await client.checkout.session.create({
257
- * items: [
258
- * { product: "prd_01ABC123", qty: 1 },
259
- * { product: "prd_01DEF456", qty: 2 },
260
- * ],
261
- * customer: "cus_01DEF456", // optional
262
- * theme: {
263
- * primary: { light: "#7c3aed", dark: "#a78bfa" },
264
- * background: { light: "#ffffff", dark: "#0b1220" },
265
- * radius: "lg",
266
- * }
252
+ * items: [{ product: "prd_01ABC123" }],
267
253
  * });
268
254
  * console.log(session.url);
269
255
  * ```
@@ -272,9 +258,8 @@ export class Session extends HeyApiClient {
272
258
  const params = buildClientParams([parameters], [
273
259
  {
274
260
  args: [
261
+ { in: "body", key: "type" },
275
262
  { in: "body", key: "items" },
276
- { in: "body", key: "customer" },
277
- { in: "body", key: "theme" },
278
263
  ],
279
264
  },
280
265
  ]);
@@ -193,7 +193,6 @@ export type CustomerCheckResponses = {
193
193
  export type CustomerCheckResponse = CustomerCheckResponses[keyof CustomerCheckResponses];
194
194
  export type ProductCreateData = {
195
195
  body?: {
196
- id?: string;
197
196
  /**
198
197
  * Ethereum address for payouts
199
198
  */
@@ -201,10 +200,6 @@ export type ProductCreateData = {
201
200
  chain: "1" | "8453";
202
201
  currency: "USDC";
203
202
  amount: number;
204
- supply?: number | null;
205
- name?: string;
206
- description?: string | null;
207
- tokens?: Array<string> | null;
208
203
  };
209
204
  path?: never;
210
205
  query?: never;
@@ -433,37 +428,10 @@ export type ProductUpdateResponses = {
433
428
  export type ProductUpdateResponse = ProductUpdateResponses[keyof ProductUpdateResponses];
434
429
  export type CheckoutSessionCreateData = {
435
430
  body?: {
431
+ type?: "hosted" | "embedded";
436
432
  items: Array<{
437
433
  product: string;
438
- mode?: "required" | "optional" | "pick";
439
- quantity?: number;
440
- default?: boolean;
441
- editable?: boolean;
442
- max?: number | null;
443
- group?: string | null;
444
434
  }>;
445
- customer?: string | null;
446
- theme?: {
447
- primary?: string | {
448
- light: string;
449
- dark: string;
450
- };
451
- background?: string | {
452
- light: string;
453
- dark: string;
454
- };
455
- radius?: "none" | "sm" | "md" | "lg" | "full";
456
- font?: {
457
- family?: string;
458
- scale?: string;
459
- };
460
- logo?: string | {
461
- light: string;
462
- dark: string;
463
- };
464
- favicon?: string;
465
- css?: string;
466
- } | null;
467
435
  };
468
436
  path?: never;
469
437
  query?: never;
@@ -486,7 +454,11 @@ export type CheckoutSessionCreateResponses = {
486
454
  */
487
455
  200: {
488
456
  id: string;
457
+ type: "hosted";
489
458
  url: string;
459
+ } | {
460
+ id: string;
461
+ type: "embedded";
490
462
  };
491
463
  };
492
464
  export type CheckoutSessionCreateResponse = CheckoutSessionCreateResponses[keyof CheckoutSessionCreateResponses];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stackup-fi/sdk",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "module": "index.ts",
5
5
  "type": "module",
6
6
  "exports": {