@skinramp/ts-sdk 0.0.2 → 0.0.4

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,23 +1,54 @@
1
- # tsdown-starter
1
+ # @skinramp/ts-sdk
2
2
 
3
- A starter for creating a TypeScript package.
3
+ Official TypeScript SDK for the Skinramp API.
4
4
 
5
- ## Development
6
-
7
- - Install dependencies:
5
+ ## Installation
8
6
 
9
7
  ```bash
10
- npm install
8
+ npm install @skinramp/ts-sdk
9
+ # or
10
+ yarn add @skinramp/ts-sdk
11
+ # or
12
+ pnpm add @skinramp/ts-sdk
13
+ # or
14
+ bun add @skinramp/ts-sdk
11
15
  ```
12
16
 
13
- - Run the unit tests:
17
+ ## Usage
14
18
 
15
- ```bash
16
- npm run test
19
+ ### Create a Payment
20
+
21
+ ```typescript
22
+ import Skinramp from "@skinramp/ts-sdk";
23
+
24
+ const skinramp = new Skinramp("sk_live_...");
25
+
26
+ const paymentId = await skinramp.payments.create({
27
+ amount: 1000, // $10.00 in cents
28
+ gameId: "CS2", // optional: "CS2" | "ROBLOX" | "RUST"
29
+ metadata: { orderId: "order_123" }, // optional
30
+ });
17
31
  ```
18
32
 
19
- - Build the library:
33
+ ### Verify Webhooks
20
34
 
21
- ```bash
22
- npm run build
35
+ ```typescript
36
+ import { Webhook } from "@skinramp/ts-sdk";
37
+
38
+ const webhook = new Webhook("whsec_...");
39
+
40
+ // In your webhook handler
41
+ const event = webhook.verify(rawBody, {
42
+ "webhook-id": req.headers["webhook-id"],
43
+ "webhook-timestamp": req.headers["webhook-timestamp"],
44
+ "webhook-signature": req.headers["webhook-signature"],
45
+ });
46
+
47
+ // event is typed as WebhookEvent<PaymentData>
48
+ console.log(event.type); // "payment.paid"
49
+ console.log(event.data); // { _id, amount, status, ... }
23
50
  ```
51
+
52
+ ## License
53
+
54
+ MIT
package/dist/index.d.mts CHANGED
@@ -26,4 +26,50 @@ declare class Skinramp {
26
26
  };
27
27
  }
28
28
  //#endregion
29
- export { Skinramp, Skinramp as default };
29
+ //#region src/webhook.d.ts
30
+ declare class WebhookVerificationError extends Error {
31
+ constructor(message: string);
32
+ }
33
+ type WebhookEventType = "payment.created" | "payment.paid" | "payment.failed" | "payment.blocked" | "payment.disputed" | "payment.dispute_won" | "payment.dispute_lost" | "payment.refunded" | "payout.created";
34
+ interface PaymentData {
35
+ _id: string;
36
+ _creationTime: number;
37
+ amount: number;
38
+ status: "PENDING" | "PAID" | "FAILED" | "BLOCKED" | "DISPUTED" | "DISPUTE_WON" | "DISPUTE_LOST" | "REFUNDED";
39
+ gameId: "CS2" | "ROBLOX" | "RUST";
40
+ merchantId: string;
41
+ paidAt?: number;
42
+ cardInfo?: {
43
+ brand?: string;
44
+ last4?: string;
45
+ };
46
+ billingAddress?: {
47
+ name?: string;
48
+ line1?: string;
49
+ line2?: string;
50
+ city?: string;
51
+ state?: string;
52
+ postalCode?: string;
53
+ country?: string;
54
+ };
55
+ userInfo?: {
56
+ name?: string;
57
+ email?: string;
58
+ };
59
+ }
60
+ interface WebhookEvent<T = PaymentData> {
61
+ id: string;
62
+ type: WebhookEventType;
63
+ timestamp: string;
64
+ data: T;
65
+ }
66
+ declare class Webhook {
67
+ private static prefix;
68
+ private readonly key;
69
+ constructor(secret: string);
70
+ verify(payload: string, headers: Record<string, string>): WebhookEvent<PaymentData>;
71
+ private sign;
72
+ private verifyTimestamp;
73
+ }
74
+ //#endregion
75
+ export { type PaymentData, Skinramp, Skinramp as default, Webhook, type WebhookEvent, type WebhookEventType, WebhookVerificationError };
package/dist/index.mjs CHANGED
@@ -1,41 +1 @@
1
- import { ConvexHttpClient } from "convex/browser";
2
- import { anyApi } from "convex/server";
3
- import "convex/values";
4
-
5
- //#region src/api.ts
6
- const api = anyApi;
7
-
8
- //#endregion
9
- //#region src/client.ts
10
- /**
11
- * Skinramp SDK client
12
- *
13
- * @example
14
- * ```typescript
15
- * const skinramp = new Skinramp('sk_development_...')
16
- *
17
- * // Create a payment
18
- * const payment = await skinramp.payments.create('user_123')
19
- * ```
20
- */
21
- var Skinramp = class {
22
- convexHttp;
23
- apiKey;
24
- constructor(apiKey, apiUrl = "https://sync.skinramp.com") {
25
- if (!apiKey) throw new Error("API key is required");
26
- this.apiKey = apiKey;
27
- this.convexHttp = new ConvexHttpClient(apiUrl);
28
- }
29
- payments = { create: async (data) => {
30
- if (!this.apiKey) throw new Error("API key is required");
31
- return await this.convexHttp.mutation(api.payments.createPayment, {
32
- apiKey: this.apiKey,
33
- amount: data.amount,
34
- gameId: data.gameId,
35
- metadata: data.metadata
36
- });
37
- } };
38
- };
39
-
40
- //#endregion
41
- export { Skinramp, Skinramp as default };
1
+ import{ConvexHttpClient as e}from"convex/browser";import{anyApi as t}from"convex/server";import"convex/values";import*as n from"@stablelib/base64";import*as r from"fast-sha256";const i=t;var a=class{convexHttp;apiKey;constructor(t,n=`https://sync.skinramp.com`){if(!t)throw Error(`API key is required`);this.apiKey=t,this.convexHttp=new e(n)}payments={create:async e=>{if(!this.apiKey)throw Error(`API key is required`);return await this.convexHttp.mutation(i.payments.createPayment,{apiKey:this.apiKey,amount:e.amount,gameId:e.gameId,metadata:e.metadata})}}},o=class extends Error{constructor(e){super(e),this.name=`WebhookVerificationError`}};function s(e,t){if(e.byteLength!==t.byteLength)return!1;let n=e instanceof DataView?e:new DataView(ArrayBuffer.isView(e)?e.buffer:e),r=t instanceof DataView?t:new DataView(ArrayBuffer.isView(t)?t.buffer:t),i=n.byteLength,a=0;for(let e=0;e<i;e++)a|=n.getUint8(e)^r.getUint8(e);return a===0}var c=class e{static prefix=`whsec_`;key;constructor(t){if(!t)throw Error(`Secret can't be empty.`);t.startsWith(e.prefix)&&(t=t.substring(e.prefix.length)),this.key=n.decode(t)}verify(e,t){let n={};for(let e of Object.keys(t))n[e.toLowerCase()]=t[e];let r=n[`webhook-id`],i=n[`webhook-signature`],a=n[`webhook-timestamp`];if(!i||!r||!a)throw new o(`Missing required headers`);let c=this.verifyTimestamp(a),l=this.sign(r,c,e),u=i.split(` `),d=new TextEncoder;for(let t of u){let[n,r]=t.split(`,`);if(n===`v1`&&s(d.encode(r),d.encode(l)))return JSON.parse(e)}throw new o(`No matching signature found`)}sign(e,t,i){let a=new TextEncoder,o=Math.floor(t.getTime()/1e3),s=a.encode(`${e}.${o}.${i}`);return n.encode(r.hmac(this.key,s))}verifyTimestamp(e){let t=Math.floor(Date.now()/1e3),n=parseInt(e,10);if(isNaN(n))throw new o(`Invalid timestamp header`);if(t-n>300)throw new o(`Message timestamp too old`);if(n>t+300)throw new o(`Message timestamp too new`);return new Date(n*1e3)}};export{a as Skinramp,a as default,c as Webhook,o as WebhookVerificationError};
package/package.json CHANGED
@@ -1,9 +1,9 @@
1
1
  {
2
2
  "name": "@skinramp/ts-sdk",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Skinramp TypeScript SDK",
5
5
  "license": "MIT",
6
- "homepage": "https://docs.skinramp.com",
6
+ "homepage": "https://skinramp.com",
7
7
  "author": "Skinramp <support@skinramp.com>",
8
8
  "type": "module",
9
9
  "main": "./dist/index.mjs",
@@ -32,6 +32,8 @@
32
32
  "vitest": "^4.0.16"
33
33
  },
34
34
  "dependencies": {
35
- "convex": "^1.31.2"
35
+ "@stablelib/base64": "^2.0.0",
36
+ "convex": "^1.31.2",
37
+ "fast-sha256": "^1.3.0"
36
38
  }
37
39
  }