@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 +43 -12
- package/dist/index.d.mts +47 -1
- package/dist/index.mjs +1 -41
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -1,23 +1,54 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @skinramp/ts-sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official TypeScript SDK for the Skinramp API.
|
|
4
4
|
|
|
5
|
-
##
|
|
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
|
-
|
|
17
|
+
## Usage
|
|
14
18
|
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
|
|
33
|
+
### Verify Webhooks
|
|
20
34
|
|
|
21
|
-
```
|
|
22
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "Skinramp TypeScript SDK",
|
|
5
5
|
"license": "MIT",
|
|
6
|
-
"homepage": "https://
|
|
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
|
-
"
|
|
35
|
+
"@stablelib/base64": "^2.0.0",
|
|
36
|
+
"convex": "^1.31.2",
|
|
37
|
+
"fast-sha256": "^1.3.0"
|
|
36
38
|
}
|
|
37
39
|
}
|