@opencardsdk/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.
package/README.md ADDED
@@ -0,0 +1,139 @@
1
+ # @opencard/sdk
2
+
3
+ Client SDK for OpenCard — create virtual cards with USDC payments via the x402 protocol.
4
+
5
+ Wraps the raw x402 flow (402 → parse challenge → pay USDC → retry with proof) into one-liner methods.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ npm install @opencard/sdk viem
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```typescript
16
+ import { OpenCardClient } from '@opencard/sdk';
17
+
18
+ const client = new OpenCardClient({
19
+ privateKey: '0x...', // or pass a viem WalletClient
20
+ baseUrl: 'https://api.opencard.com',
21
+ });
22
+
23
+ // One line — SDK handles payment automatically
24
+ const card = await client.createCard({
25
+ amount: 10, // $10 tier
26
+ nameOnCard: 'AI AGENT',
27
+ email: 'agent@example.com',
28
+ });
29
+
30
+ console.log(card.cardDetails); // { cardNumber, cvv, expiry, ... }
31
+ ```
32
+
33
+ ## API
34
+
35
+ ### `new OpenCardClient(config)`
36
+
37
+ | Option | Type | Required | Description |
38
+ |--------|------|----------|-------------|
39
+ | `privateKey` | `0x${string}` | One of | Hex private key — SDK creates wallet internally |
40
+ | `walletClient` | `WalletClient` | One of | Your own viem WalletClient (takes precedence) |
41
+ | `baseUrl` | `string` | No | API URL (default: `https://api.opencard.com`) |
42
+ | `rpcUrl` | `string` | No | Base RPC URL (default: public RPC) |
43
+ | `timeout` | `number` | No | Request timeout in ms (default: 60000) |
44
+
45
+ ### `client.createCard(params): Promise<CardResult>`
46
+
47
+ Create a virtual card. Pays USDC automatically.
48
+
49
+ ```typescript
50
+ const result = await client.createCard({
51
+ amount: 50, // 10 | 25 | 50 | 100 | 200 | 500
52
+ nameOnCard: 'AI AGENT',
53
+ email: 'agent@example.com',
54
+ });
55
+ ```
56
+
57
+ ### `client.fundCard(params): Promise<FundResult>`
58
+
59
+ Fund an existing card.
60
+
61
+ ```typescript
62
+ const result = await client.fundCard({
63
+ amount: 25,
64
+ cardId: 'card-uuid',
65
+ });
66
+ ```
67
+
68
+ ### `client.getTiers(): Promise<TiersResponse>`
69
+
70
+ Get pricing tiers and fee breakdown (no payment required).
71
+
72
+ ### `client.health(): Promise<{ status: string }>`
73
+
74
+ Check if the OpenCard API is reachable.
75
+
76
+ ### `client.address: 0x${string}`
77
+
78
+ The wallet address being used for payments.
79
+
80
+ ## Error Handling
81
+
82
+ ```typescript
83
+ import {
84
+ OpenCardClient,
85
+ InsufficientBalanceError,
86
+ PaymentError,
87
+ ApiError,
88
+ TimeoutError,
89
+ } from '@opencard/sdk';
90
+
91
+ try {
92
+ const card = await client.createCard({ ... });
93
+ } catch (error) {
94
+ if (error instanceof InsufficientBalanceError) {
95
+ console.log(`Need ${error.required}, have ${error.available}`);
96
+ } else if (error instanceof PaymentError) {
97
+ console.log(`Payment failed: ${error.message}, tx: ${error.txHash}`);
98
+ } else if (error instanceof ApiError) {
99
+ console.log(`Server error ${error.status}:`, error.body);
100
+ } else if (error instanceof TimeoutError) {
101
+ console.log('Request timed out');
102
+ }
103
+ }
104
+ ```
105
+
106
+ ## Advanced: Low-Level x402 Utilities
107
+
108
+ For custom integrations, the x402 protocol helpers are exported directly:
109
+
110
+ ```typescript
111
+ import {
112
+ parseChallenge,
113
+ checkBalance,
114
+ executePayment,
115
+ buildPaymentProof,
116
+ handleX402Payment,
117
+ } from '@opencard/sdk';
118
+ ```
119
+
120
+ ## How It Works
121
+
122
+ ```
123
+ Your Code SDK OpenCard API Base Chain
124
+ | | | |
125
+ |-- createCard ->| | |
126
+ | |--- POST /create/tier -->| |
127
+ | |<-- 402 + challenge -----| |
128
+ | | | |
129
+ | |--- USDC.transfer() -----|-------- tx ------->|
130
+ | |<-- txHash --------------|-------- receipt ---|
131
+ | | | |
132
+ | |--- POST + X-Payment --->| |
133
+ | |<-- 201 + card details --| |
134
+ |<- CardResult --| | |
135
+ ```
136
+
137
+ ## License
138
+
139
+ MIT
@@ -0,0 +1,43 @@
1
+ import type { OpenCardConfig, CreateCardParams, FundCardParams, CardResult, FundResult, TiersResponse } from "./types.js";
2
+ export declare class OpenCardClient {
3
+ private walletClient;
4
+ private baseUrl;
5
+ private timeout;
6
+ constructor(config: OpenCardConfig);
7
+ /** The wallet address used for payments */
8
+ get address(): `0x${string}`;
9
+ /**
10
+ * Create a virtual card with automatic USDC payment.
11
+ *
12
+ * Handles the full x402 flow:
13
+ * 1. Sends request → gets 402 with payment requirements
14
+ * 2. Executes USDC transfer on Base
15
+ * 3. Retries with payment proof
16
+ * 4. Returns card details
17
+ */
18
+ createCard(params: CreateCardParams): Promise<CardResult>;
19
+ /**
20
+ * Fund an existing card with automatic USDC payment.
21
+ */
22
+ fundCard(params: FundCardParams): Promise<FundResult>;
23
+ /**
24
+ * Get available tiers and pricing breakdown (no payment required).
25
+ */
26
+ getTiers(): Promise<TiersResponse>;
27
+ /**
28
+ * Health check — verify the server is reachable.
29
+ */
30
+ health(): Promise<{
31
+ status: string;
32
+ }>;
33
+ /**
34
+ * Execute a paid request with automatic x402 handling.
35
+ *
36
+ * 1. POST to endpoint → expect 402
37
+ * 2. Parse challenge → execute USDC payment → build proof
38
+ * 3. Retry POST with X-Payment header
39
+ */
40
+ private paidRequest;
41
+ private fetch;
42
+ }
43
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,UAAU,EACV,aAAa,EACd,MAAM,YAAY,CAAC;AAOpB,qBAAa,cAAc;IACzB,OAAO,CAAC,YAAY,CAA0C;IAC9D,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;gBAEZ,MAAM,EAAE,cAAc;IAqBlC,2CAA2C;IAC3C,IAAI,OAAO,IAAI,KAAK,MAAM,EAAE,CAE3B;IAID;;;;;;;;OAQG;IACG,UAAU,CAAC,MAAM,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,CAAC;IAU/D;;OAEG;IACG,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,UAAU,CAAC;IAU3D;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,aAAa,CAAC;IAgBxC;;OAEG;IACG,MAAM,IAAI,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAO3C;;;;;;OAMG;YACW,WAAW;YAqDX,KAAK;CAepB"}
package/dist/client.js ADDED
@@ -0,0 +1,143 @@
1
+ import { createWalletClient, http, } from "viem";
2
+ import { privateKeyToAccount } from "viem/accounts";
3
+ import { base } from "viem/chains";
4
+ import { handleX402Payment } from "./x402.js";
5
+ import { ConfigError, ApiError, TimeoutError } from "./errors.js";
6
+ const DEFAULT_BASE_URL = "https://api.opencard.com";
7
+ const DEFAULT_TIMEOUT = 60_000;
8
+ export class OpenCardClient {
9
+ walletClient;
10
+ baseUrl;
11
+ timeout;
12
+ constructor(config) {
13
+ this.baseUrl = (config.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
14
+ this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
15
+ if (config.walletClient) {
16
+ if (!config.walletClient.account) {
17
+ throw new ConfigError("walletClient must have an account attached");
18
+ }
19
+ this.walletClient = config.walletClient;
20
+ }
21
+ else if (config.privateKey) {
22
+ const account = privateKeyToAccount(config.privateKey);
23
+ this.walletClient = createWalletClient({
24
+ account,
25
+ chain: base,
26
+ transport: http(config.rpcUrl),
27
+ });
28
+ }
29
+ else {
30
+ throw new ConfigError("Provide either privateKey or walletClient");
31
+ }
32
+ }
33
+ /** The wallet address used for payments */
34
+ get address() {
35
+ return this.walletClient.account.address;
36
+ }
37
+ // ── Card Creation ───────────────────────────────────────────────────
38
+ /**
39
+ * Create a virtual card with automatic USDC payment.
40
+ *
41
+ * Handles the full x402 flow:
42
+ * 1. Sends request → gets 402 with payment requirements
43
+ * 2. Executes USDC transfer on Base
44
+ * 3. Retries with payment proof
45
+ * 4. Returns card details
46
+ */
47
+ async createCard(params) {
48
+ const { amount, nameOnCard, email } = params;
49
+ const endpoint = `${this.baseUrl}/cards/create/tier/${amount}`;
50
+ const body = JSON.stringify({ nameOnCard, email });
51
+ return this.paidRequest(endpoint, body);
52
+ }
53
+ // ── Card Funding ────────────────────────────────────────────────────
54
+ /**
55
+ * Fund an existing card with automatic USDC payment.
56
+ */
57
+ async fundCard(params) {
58
+ const { amount, cardId } = params;
59
+ const endpoint = `${this.baseUrl}/cards/fund/tier/${amount}`;
60
+ const body = JSON.stringify({ cardId });
61
+ return this.paidRequest(endpoint, body);
62
+ }
63
+ // ── Pricing ─────────────────────────────────────────────────────────
64
+ /**
65
+ * Get available tiers and pricing breakdown (no payment required).
66
+ */
67
+ async getTiers() {
68
+ const res = await this.fetch(`${this.baseUrl}/cards/tiers`, {
69
+ method: "GET",
70
+ });
71
+ if (!res.ok) {
72
+ throw new ApiError(`Failed to fetch tiers: ${res.statusText}`, res.status, await res.json().catch(() => null));
73
+ }
74
+ return res.json();
75
+ }
76
+ /**
77
+ * Health check — verify the server is reachable.
78
+ */
79
+ async health() {
80
+ const res = await this.fetch(`${this.baseUrl}/health`, { method: "GET" });
81
+ return res.json();
82
+ }
83
+ // ── Internal: x402 Payment Flow ─────────────────────────────────────
84
+ /**
85
+ * Execute a paid request with automatic x402 handling.
86
+ *
87
+ * 1. POST to endpoint → expect 402
88
+ * 2. Parse challenge → execute USDC payment → build proof
89
+ * 3. Retry POST with X-Payment header
90
+ */
91
+ async paidRequest(endpoint, body) {
92
+ // Step 1: Initial request — expect 402
93
+ const initialRes = await this.fetch(endpoint, {
94
+ method: "POST",
95
+ headers: { "Content-Type": "application/json" },
96
+ body,
97
+ });
98
+ // If server doesn't return 402, handle accordingly
99
+ if (initialRes.status !== 402) {
100
+ if (initialRes.ok) {
101
+ // No payment needed (shouldn't happen but handle gracefully)
102
+ return initialRes.json();
103
+ }
104
+ const errorBody = await initialRes.json().catch(() => null);
105
+ throw new ApiError(`Unexpected response: ${initialRes.status} ${initialRes.statusText}`, initialRes.status, errorBody);
106
+ }
107
+ // Step 2: Parse 402, pay, get proof
108
+ const challengeBody = await initialRes.json();
109
+ const { header, txHash } = await handleX402Payment(this.walletClient, challengeBody);
110
+ // Step 3: Retry with payment proof
111
+ const paidRes = await this.fetch(endpoint, {
112
+ method: "POST",
113
+ headers: {
114
+ "Content-Type": "application/json",
115
+ "X-Payment": header,
116
+ },
117
+ body,
118
+ });
119
+ if (!paidRes.ok) {
120
+ const errorBody = await paidRes.json().catch(() => null);
121
+ throw new ApiError(`Request failed after payment (tx: ${txHash}): ${paidRes.status}`, paidRes.status, errorBody);
122
+ }
123
+ return paidRes.json();
124
+ }
125
+ // ── Internal: Fetch with timeout ────────────────────────────────────
126
+ async fetch(url, init) {
127
+ const controller = new AbortController();
128
+ const timer = setTimeout(() => controller.abort(), this.timeout);
129
+ try {
130
+ return await fetch(url, { ...init, signal: controller.signal });
131
+ }
132
+ catch (error) {
133
+ if (error instanceof DOMException && error.name === "AbortError") {
134
+ throw new TimeoutError(this.timeout);
135
+ }
136
+ throw error;
137
+ }
138
+ finally {
139
+ clearTimeout(timer);
140
+ }
141
+ }
142
+ }
143
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /** Base error for all OpenCard SDK errors */
2
+ export declare class OpenCardError extends Error {
3
+ readonly code: string;
4
+ constructor(message: string, code: string);
5
+ }
6
+ /** Configuration is invalid or missing */
7
+ export declare class ConfigError extends OpenCardError {
8
+ constructor(message: string);
9
+ }
10
+ /** Server returned 402 but payment failed */
11
+ export declare class PaymentError extends OpenCardError {
12
+ readonly txHash?: string;
13
+ constructor(message: string, options?: {
14
+ txHash?: string;
15
+ });
16
+ }
17
+ /** Insufficient USDC balance to cover the payment */
18
+ export declare class InsufficientBalanceError extends OpenCardError {
19
+ readonly required: bigint;
20
+ readonly available: bigint;
21
+ constructor(required: bigint, available: bigint);
22
+ }
23
+ /** Server returned a non-402 error */
24
+ export declare class ApiError extends OpenCardError {
25
+ readonly status: number;
26
+ readonly body?: unknown | undefined;
27
+ constructor(message: string, status: number, body?: unknown | undefined);
28
+ }
29
+ /** Request timed out */
30
+ export declare class TimeoutError extends OpenCardError {
31
+ constructor(ms: number);
32
+ }
33
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,qBAAa,aAAc,SAAQ,KAAK;aAGpB,IAAI,EAAE,MAAM;gBAD5B,OAAO,EAAE,MAAM,EACC,IAAI,EAAE,MAAM;CAK/B;AAED,0CAA0C;AAC1C,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM;CAI5B;AAED,6CAA6C;AAC7C,qBAAa,YAAa,SAAQ,aAAa;IAC7C,SAAgB,MAAM,CAAC,EAAE,MAAM,CAAC;gBAG9B,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;CAMhC;AAED,qDAAqD;AACrD,qBAAa,wBAAyB,SAAQ,aAAa;aAEvC,QAAQ,EAAE,MAAM;aAChB,SAAS,EAAE,MAAM;gBADjB,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM;CAQpC;AAED,sCAAsC;AACtC,qBAAa,QAAS,SAAQ,aAAa;aAGvB,MAAM,EAAE,MAAM;aACd,IAAI,CAAC,EAAE,OAAO;gBAF9B,OAAO,EAAE,MAAM,EACC,MAAM,EAAE,MAAM,EACd,IAAI,CAAC,EAAE,OAAO,YAAA;CAKjC;AAED,wBAAwB;AACxB,qBAAa,YAAa,SAAQ,aAAa;gBACjC,EAAE,EAAE,MAAM;CAIvB"}
package/dist/errors.js ADDED
@@ -0,0 +1,55 @@
1
+ /** Base error for all OpenCard SDK errors */
2
+ export class OpenCardError extends Error {
3
+ code;
4
+ constructor(message, code) {
5
+ super(message);
6
+ this.code = code;
7
+ this.name = "OpenCardError";
8
+ }
9
+ }
10
+ /** Configuration is invalid or missing */
11
+ export class ConfigError extends OpenCardError {
12
+ constructor(message) {
13
+ super(message, "CONFIG_ERROR");
14
+ this.name = "ConfigError";
15
+ }
16
+ }
17
+ /** Server returned 402 but payment failed */
18
+ export class PaymentError extends OpenCardError {
19
+ txHash;
20
+ constructor(message, options) {
21
+ super(message, "PAYMENT_ERROR");
22
+ this.name = "PaymentError";
23
+ this.txHash = options?.txHash;
24
+ }
25
+ }
26
+ /** Insufficient USDC balance to cover the payment */
27
+ export class InsufficientBalanceError extends OpenCardError {
28
+ required;
29
+ available;
30
+ constructor(required, available) {
31
+ super(`Insufficient USDC balance: need ${required} but have ${available} (amounts in 6-decimal units)`, "INSUFFICIENT_BALANCE");
32
+ this.required = required;
33
+ this.available = available;
34
+ this.name = "InsufficientBalanceError";
35
+ }
36
+ }
37
+ /** Server returned a non-402 error */
38
+ export class ApiError extends OpenCardError {
39
+ status;
40
+ body;
41
+ constructor(message, status, body) {
42
+ super(message, "API_ERROR");
43
+ this.status = status;
44
+ this.body = body;
45
+ this.name = "ApiError";
46
+ }
47
+ }
48
+ /** Request timed out */
49
+ export class TimeoutError extends OpenCardError {
50
+ constructor(ms) {
51
+ super(`Request timed out after ${ms}ms`, "TIMEOUT");
52
+ this.name = "TimeoutError";
53
+ }
54
+ }
55
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,MAAM,OAAO,aAAc,SAAQ,KAAK;IAGpB;IAFlB,YACE,OAAe,EACC,IAAY;QAE5B,KAAK,CAAC,OAAO,CAAC,CAAC;QAFC,SAAI,GAAJ,IAAI,CAAQ;QAG5B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,0CAA0C;AAC1C,MAAM,OAAO,WAAY,SAAQ,aAAa;IAC5C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,EAAE,cAAc,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,6CAA6C;AAC7C,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC7B,MAAM,CAAU;IAEhC,YACE,OAAe,EACf,OAA6B;QAE7B,KAAK,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;QAC3B,IAAI,CAAC,MAAM,GAAG,OAAO,EAAE,MAAM,CAAC;IAChC,CAAC;CACF;AAED,qDAAqD;AACrD,MAAM,OAAO,wBAAyB,SAAQ,aAAa;IAEvC;IACA;IAFlB,YACkB,QAAgB,EAChB,SAAiB;QAEjC,KAAK,CACH,mCAAmC,QAAQ,aAAa,SAAS,+BAA+B,EAChG,sBAAsB,CACvB,CAAC;QANc,aAAQ,GAAR,QAAQ,CAAQ;QAChB,cAAS,GAAT,SAAS,CAAQ;QAMjC,IAAI,CAAC,IAAI,GAAG,0BAA0B,CAAC;IACzC,CAAC;CACF;AAED,sCAAsC;AACtC,MAAM,OAAO,QAAS,SAAQ,aAAa;IAGvB;IACA;IAHlB,YACE,OAAe,EACC,MAAc,EACd,IAAc;QAE9B,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAHZ,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAU;QAG9B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,wBAAwB;AACxB,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC7C,YAAY,EAAU;QACpB,KAAK,CAAC,2BAA2B,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export { OpenCardClient } from "./client.js";
2
+ export type { OpenCardConfig, CreateCardParams, FundCardParams, CardResult, FundResult, TiersResponse, TierBreakdown, X402Challenge, X402PaymentOption, X402PaymentProof, } from "./types.js";
3
+ export { OpenCardError, ConfigError, PaymentError, InsufficientBalanceError, ApiError, TimeoutError, } from "./errors.js";
4
+ export { parseChallenge, checkBalance, executePayment, buildPaymentProof, handleX402Payment, } from "./x402.js";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7C,YAAY,EACV,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,UAAU,EACV,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,wBAAwB,EACxB,QAAQ,EACR,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ // ── Main Client ─────────────────────────────────────────────────────
2
+ export { OpenCardClient } from "./client.js";
3
+ // ── Errors ──────────────────────────────────────────────────────────
4
+ export { OpenCardError, ConfigError, PaymentError, InsufficientBalanceError, ApiError, TimeoutError, } from "./errors.js";
5
+ // ── Low-level x402 utilities (for advanced usage) ───────────────────
6
+ export { parseChallenge, checkBalance, executePayment, buildPaymentProof, handleX402Payment, } from "./x402.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAgB7C,uEAAuE;AACvE,OAAO,EACL,aAAa,EACb,WAAW,EACX,YAAY,EACZ,wBAAwB,EACxB,QAAQ,EACR,YAAY,GACb,MAAM,aAAa,CAAC;AAErB,uEAAuE;AACvE,OAAO,EACL,cAAc,EACd,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,WAAW,CAAC"}
@@ -0,0 +1,121 @@
1
+ import type { Account, Chain, Transport, WalletClient } from "viem";
2
+ export interface OpenCardConfig {
3
+ /** Private key (hex string with 0x prefix) — creates a wallet client internally */
4
+ privateKey?: `0x${string}`;
5
+ /** Or pass your own viem WalletClient (takes precedence over privateKey) */
6
+ walletClient?: WalletClient<Transport, Chain, Account>;
7
+ /** OpenCard API base URL (default: https://api.opencard.com) */
8
+ baseUrl?: string;
9
+ /** RPC URL for Base network (default: public Base RPC) */
10
+ rpcUrl?: string;
11
+ /** Request timeout in ms (default: 60000) */
12
+ timeout?: number;
13
+ }
14
+ export interface CreateCardParams {
15
+ /** Tier amount in USD (10, 25, 50, 100, 200, 500) */
16
+ amount: number;
17
+ /** Name printed on the card (auto-uppercased) */
18
+ nameOnCard: string;
19
+ /** Email for card notifications */
20
+ email: string;
21
+ }
22
+ export interface FundCardParams {
23
+ /** Tier amount in USD (10, 25, 50, 100, 200, 500) */
24
+ amount: number;
25
+ /** Card ID to fund */
26
+ cardId: string;
27
+ }
28
+ export interface CardResult {
29
+ success: boolean;
30
+ card: {
31
+ cardId: string;
32
+ kripiCardId: string;
33
+ nameOnCard: string;
34
+ lastFour?: string;
35
+ balance: number | null;
36
+ status: string;
37
+ createdAt: string;
38
+ };
39
+ cardDetails?: {
40
+ cardNumber: string;
41
+ expiryMonth: number;
42
+ expiryYear: number;
43
+ cvv: string;
44
+ billingAddress: {
45
+ street: string;
46
+ city: string;
47
+ state: string;
48
+ zip: string;
49
+ country: string;
50
+ };
51
+ };
52
+ payment: {
53
+ walletAddress: string;
54
+ txHash?: string;
55
+ amountUsd: number;
56
+ };
57
+ }
58
+ export interface FundResult {
59
+ success: boolean;
60
+ card: {
61
+ cardId: string;
62
+ newBalance?: number;
63
+ };
64
+ payment: {
65
+ walletAddress: string;
66
+ txHash?: string;
67
+ amountUsd: number;
68
+ };
69
+ }
70
+ export interface TierBreakdown {
71
+ loadAmount?: number;
72
+ fundAmount?: number;
73
+ totalCost: number;
74
+ endpoint: string;
75
+ breakdown: {
76
+ cardLoad?: number;
77
+ fundAmount?: number;
78
+ issuanceFee?: number;
79
+ topUpFee: number;
80
+ ourFee: number;
81
+ buffer?: number;
82
+ };
83
+ }
84
+ export interface TiersResponse {
85
+ creation: TierBreakdown[];
86
+ funding: TierBreakdown[];
87
+ }
88
+ export interface X402Challenge {
89
+ x402Version: number;
90
+ accepts: X402PaymentOption[];
91
+ error?: string;
92
+ }
93
+ export interface X402PaymentOption {
94
+ scheme: string;
95
+ network: string;
96
+ maxAmountRequired: string;
97
+ resource: string;
98
+ description: string;
99
+ mimeType: string;
100
+ payTo: `0x${string}`;
101
+ maxTimeoutSeconds: number;
102
+ asset: `0x${string}`;
103
+ extra?: Record<string, unknown>;
104
+ }
105
+ export interface X402PaymentProof {
106
+ scheme: string;
107
+ network: string;
108
+ payload: {
109
+ authorization: {
110
+ from: string;
111
+ to: string;
112
+ value: string;
113
+ validAfter: string;
114
+ validBefore: string;
115
+ nonce: string;
116
+ };
117
+ signature: string;
118
+ txHash: string;
119
+ };
120
+ }
121
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/dist/x402.d.ts ADDED
@@ -0,0 +1,37 @@
1
+ import { type Account, type Chain, type Transport, type WalletClient } from "viem";
2
+ import type { X402Challenge, X402PaymentOption } from "./types.js";
3
+ /**
4
+ * Parse a 402 response body into a structured challenge.
5
+ */
6
+ export declare function parseChallenge(body: unknown): X402Challenge;
7
+ /**
8
+ * Check if the wallet has enough USDC to cover the payment.
9
+ * Uses a public client for read-only calls.
10
+ */
11
+ export declare function checkBalance(walletClient: WalletClient<Transport, Chain, Account>, amount: bigint): Promise<void>;
12
+ /**
13
+ * Execute USDC transfer on Base to the specified recipient.
14
+ * Returns the transaction hash.
15
+ */
16
+ export declare function executePayment(walletClient: WalletClient<Transport, Chain, Account>, payTo: `0x${string}`, amount: bigint): Promise<`0x${string}`>;
17
+ /**
18
+ * Construct the x402 payment proof from the completed transaction.
19
+ */
20
+ export declare function buildPaymentProof(paymentOption: X402PaymentOption, from: `0x${string}`, txHash: `0x${string}`): string;
21
+ /**
22
+ * Full x402 payment flow:
23
+ * 1. Parse 402 challenge
24
+ * 2. Check USDC balance
25
+ * 3. Execute USDC transfer
26
+ * 4. Build payment proof header
27
+ *
28
+ * Returns the encoded X-Payment header value.
29
+ */
30
+ export declare function handleX402Payment(walletClient: WalletClient<Transport, Chain, Account>, challengeBody: unknown, options?: {
31
+ skipBalanceCheck?: boolean;
32
+ }): Promise<{
33
+ header: string;
34
+ txHash: `0x${string}`;
35
+ amountPaid: bigint;
36
+ }>;
37
+ //# sourceMappingURL=x402.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.d.ts","sourceRoot":"","sources":["../src/x402.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,SAAS,EACd,KAAK,YAAY,EAGlB,MAAM,MAAM,CAAC;AAEd,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AA0BrF;;GAEG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,aAAa,CAM3D;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,EACrD,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,IAAI,CAAC,CAgBf;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,EACrD,KAAK,EAAE,KAAK,MAAM,EAAE,EACpB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,KAAK,MAAM,EAAE,CAAC,CAcxB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,aAAa,EAAE,iBAAiB,EAChC,IAAI,EAAE,KAAK,MAAM,EAAE,EACnB,MAAM,EAAE,KAAK,MAAM,EAAE,GACpB,MAAM,CAmBR;AAED;;;;;;;;GAQG;AACH,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,YAAY,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,EACrD,aAAa,EAAE,OAAO,EACtB,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,GACvC,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,KAAK,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAqBxE"}
package/dist/x402.js ADDED
@@ -0,0 +1,118 @@
1
+ import { createPublicClient, http, } from "viem";
2
+ import { base } from "viem/chains";
3
+ import { PaymentError, InsufficientBalanceError } from "./errors.js";
4
+ // USDC on Base
5
+ const USDC_BASE = "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913";
6
+ const USDC_ABI = [
7
+ {
8
+ inputs: [
9
+ { name: "to", type: "address" },
10
+ { name: "amount", type: "uint256" },
11
+ ],
12
+ name: "transfer",
13
+ outputs: [{ name: "", type: "bool" }],
14
+ stateMutability: "nonpayable",
15
+ type: "function",
16
+ },
17
+ {
18
+ inputs: [{ name: "account", type: "address" }],
19
+ name: "balanceOf",
20
+ outputs: [{ name: "", type: "uint256" }],
21
+ stateMutability: "view",
22
+ type: "function",
23
+ },
24
+ ];
25
+ /**
26
+ * Parse a 402 response body into a structured challenge.
27
+ */
28
+ export function parseChallenge(body) {
29
+ const challenge = body;
30
+ if (!challenge.accepts || !Array.isArray(challenge.accepts) || challenge.accepts.length === 0) {
31
+ throw new PaymentError("Invalid 402 response: missing payment options");
32
+ }
33
+ return challenge;
34
+ }
35
+ /**
36
+ * Check if the wallet has enough USDC to cover the payment.
37
+ * Uses a public client for read-only calls.
38
+ */
39
+ export async function checkBalance(walletClient, amount) {
40
+ const publicClient = createPublicClient({
41
+ chain: walletClient.chain ?? base,
42
+ transport: http(),
43
+ });
44
+ const available = await publicClient.readContract({
45
+ address: USDC_BASE,
46
+ abi: USDC_ABI,
47
+ functionName: "balanceOf",
48
+ args: [walletClient.account.address],
49
+ });
50
+ if (available < amount) {
51
+ throw new InsufficientBalanceError(amount, available);
52
+ }
53
+ }
54
+ /**
55
+ * Execute USDC transfer on Base to the specified recipient.
56
+ * Returns the transaction hash.
57
+ */
58
+ export async function executePayment(walletClient, payTo, amount) {
59
+ try {
60
+ const hash = await walletClient.writeContract({
61
+ address: USDC_BASE,
62
+ abi: USDC_ABI,
63
+ functionName: "transfer",
64
+ args: [payTo, amount],
65
+ });
66
+ return hash;
67
+ }
68
+ catch (error) {
69
+ const msg = error instanceof Error ? error.message : "USDC transfer failed";
70
+ throw new PaymentError(`Payment transaction failed: ${msg}`);
71
+ }
72
+ }
73
+ /**
74
+ * Construct the x402 payment proof from the completed transaction.
75
+ */
76
+ export function buildPaymentProof(paymentOption, from, txHash) {
77
+ const proof = {
78
+ scheme: paymentOption.scheme,
79
+ network: paymentOption.network,
80
+ payload: {
81
+ authorization: {
82
+ from,
83
+ to: paymentOption.payTo,
84
+ value: paymentOption.maxAmountRequired,
85
+ validAfter: "0",
86
+ validBefore: "9999999999",
87
+ nonce: "0",
88
+ },
89
+ signature: "0x",
90
+ txHash,
91
+ },
92
+ };
93
+ return btoa(JSON.stringify(proof));
94
+ }
95
+ /**
96
+ * Full x402 payment flow:
97
+ * 1. Parse 402 challenge
98
+ * 2. Check USDC balance
99
+ * 3. Execute USDC transfer
100
+ * 4. Build payment proof header
101
+ *
102
+ * Returns the encoded X-Payment header value.
103
+ */
104
+ export async function handleX402Payment(walletClient, challengeBody, options) {
105
+ const challenge = parseChallenge(challengeBody);
106
+ const paymentOption = challenge.accepts[0];
107
+ const amount = BigInt(paymentOption.maxAmountRequired);
108
+ // Optionally check balance first to give a better error
109
+ if (!options?.skipBalanceCheck) {
110
+ await checkBalance(walletClient, amount);
111
+ }
112
+ // Execute the USDC transfer
113
+ const txHash = await executePayment(walletClient, paymentOption.payTo, amount);
114
+ // Build the proof header
115
+ const header = buildPaymentProof(paymentOption, walletClient.account.address, txHash);
116
+ return { header, txHash, amountPaid: amount };
117
+ }
118
+ //# sourceMappingURL=x402.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"x402.js","sourceRoot":"","sources":["../src/x402.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,43 @@
1
+ {
2
+ "name": "@opencardsdk/sdk",
3
+ "version": "0.1.0",
4
+ "description": "Client SDK for OpenCard — create virtual cards with USDC payments via x402",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": "./dist/index.js",
11
+ "types": "./dist/index.d.ts"
12
+ }
13
+ },
14
+ "files": [
15
+ "dist",
16
+ "README.md"
17
+ ],
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "dev": "tsc --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "prepublishOnly": "npm run build"
23
+ },
24
+ "keywords": [
25
+ "opencard",
26
+ "x402",
27
+ "usdc",
28
+ "virtual-card",
29
+ "ai-agent",
30
+ "crypto-payments",
31
+ "base"
32
+ ],
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "viem": "^2.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "typescript": "^5.5.0"
39
+ },
40
+ "peerDependencies": {
41
+ "viem": "^2.0.0"
42
+ }
43
+ }