@t402/wdk-protocol 2.4.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/dist/cjs/index.d.ts +193 -0
- package/dist/cjs/index.js +244 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/esm/index.d.mts +193 -0
- package/dist/esm/index.mjs +214 -0
- package/dist/esm/index.mjs.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { t402HTTPClient } from '@t402/core/http';
|
|
2
|
+
import { PaymentRequired, PaymentPayload } from '@t402/core/types';
|
|
3
|
+
import { T402WDK } from '@t402/wdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Type definitions for @t402/wdk-protocol
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for the T402 protocol module
|
|
10
|
+
*/
|
|
11
|
+
interface T402ProtocolConfig {
|
|
12
|
+
/** Facilitator URL for payment verification/settlement (default: https://facilitator.t402.io) */
|
|
13
|
+
facilitator?: string;
|
|
14
|
+
/** CAIP-2 networks or chain names to support */
|
|
15
|
+
chains?: string[];
|
|
16
|
+
/** WDK account index to use (default: 0) */
|
|
17
|
+
accountIndex?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of a successful payment
|
|
21
|
+
*/
|
|
22
|
+
interface PaymentReceipt {
|
|
23
|
+
/** Whether payment was successful */
|
|
24
|
+
success: boolean;
|
|
25
|
+
/** The payment network used */
|
|
26
|
+
network: string;
|
|
27
|
+
/** The payment scheme used */
|
|
28
|
+
scheme: string;
|
|
29
|
+
/** Amount paid */
|
|
30
|
+
amount: string;
|
|
31
|
+
/** Address paid to */
|
|
32
|
+
payTo: string;
|
|
33
|
+
/** Settlement transaction hash (if settled) */
|
|
34
|
+
transaction?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result from T402Protocol.fetch()
|
|
38
|
+
*/
|
|
39
|
+
interface T402FetchResult {
|
|
40
|
+
/** The HTTP response */
|
|
41
|
+
response: Response;
|
|
42
|
+
/** Payment receipt if a 402 was handled */
|
|
43
|
+
receipt?: PaymentReceipt;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* T402Protocol - Main class for WDK apps to add T402 payment capability
|
|
48
|
+
*
|
|
49
|
+
* Uses the real t402 client infrastructure (t402Client + mechanism-specific
|
|
50
|
+
* scheme clients) for proper payment payload creation and signing.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import { T402Protocol } from '@t402/wdk-protocol';
|
|
55
|
+
* import { T402WDK } from '@t402/wdk';
|
|
56
|
+
*
|
|
57
|
+
* const wdk = new T402WDK(seedPhrase, { arbitrum: rpcUrl });
|
|
58
|
+
* const t402 = await T402Protocol.create(wdk, {
|
|
59
|
+
* chains: ['ethereum', 'arbitrum'],
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Auto-pay for HTTP 402 resources
|
|
63
|
+
* const { response, receipt } = await t402.fetch('https://api.example.com/premium');
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* T402Protocol enables any WDK wallet app to handle HTTP 402 payments.
|
|
69
|
+
*
|
|
70
|
+
* Uses the real t402 protocol client infrastructure with EVM mechanism support.
|
|
71
|
+
* Payment payloads are properly signed using EIP-3009 authorization.
|
|
72
|
+
*/
|
|
73
|
+
declare class T402Protocol {
|
|
74
|
+
private httpClient;
|
|
75
|
+
private wdk;
|
|
76
|
+
private facilitator;
|
|
77
|
+
private chains;
|
|
78
|
+
private constructor();
|
|
79
|
+
/**
|
|
80
|
+
* Create a new T402Protocol instance.
|
|
81
|
+
*
|
|
82
|
+
* This is async because it needs to initialize the WDK signer.
|
|
83
|
+
*
|
|
84
|
+
* @param wdk - An initialized T402WDK instance
|
|
85
|
+
* @param config - Protocol configuration
|
|
86
|
+
* @returns A configured T402Protocol instance
|
|
87
|
+
*/
|
|
88
|
+
static create(wdk: T402WDK, config?: T402ProtocolConfig): Promise<T402Protocol>;
|
|
89
|
+
/**
|
|
90
|
+
* Fetch a URL with automatic 402 payment handling.
|
|
91
|
+
*
|
|
92
|
+
* 1. Makes the initial request
|
|
93
|
+
* 2. If 402, extracts payment requirements
|
|
94
|
+
* 3. Creates a properly signed payment payload (EIP-3009 for EVM)
|
|
95
|
+
* 4. Retries the request with the signed payment header
|
|
96
|
+
*
|
|
97
|
+
* @param url - URL to fetch
|
|
98
|
+
* @param init - Standard fetch RequestInit options
|
|
99
|
+
* @returns The final response and optional payment receipt
|
|
100
|
+
*/
|
|
101
|
+
fetch(url: string | URL, init?: RequestInit): Promise<T402FetchResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Extract payment requirements from a URL
|
|
104
|
+
*
|
|
105
|
+
* @param url - URL to check for payment requirements
|
|
106
|
+
* @param init - Standard fetch RequestInit options
|
|
107
|
+
* @returns The PaymentRequired object from the 402 response
|
|
108
|
+
* @throws Error if the response is not 402
|
|
109
|
+
*/
|
|
110
|
+
getRequirements(url: string | URL, init?: RequestInit): Promise<PaymentRequired>;
|
|
111
|
+
/**
|
|
112
|
+
* Sign a payment for specific requirements using the t402 client infrastructure
|
|
113
|
+
*
|
|
114
|
+
* @param paymentRequired - The full PaymentRequired context
|
|
115
|
+
* @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)
|
|
116
|
+
*/
|
|
117
|
+
signPayment(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
|
|
118
|
+
/**
|
|
119
|
+
* Submit a request with a pre-signed payment payload
|
|
120
|
+
*
|
|
121
|
+
* @param url - URL to request
|
|
122
|
+
* @param paymentPayload - The signed payment payload
|
|
123
|
+
* @param init - Standard fetch RequestInit options
|
|
124
|
+
* @returns The HTTP response
|
|
125
|
+
*/
|
|
126
|
+
submitPayment(url: string | URL, paymentPayload: PaymentPayload, init?: RequestInit): Promise<Response>;
|
|
127
|
+
/**
|
|
128
|
+
* Get the underlying t402 HTTP client for advanced usage
|
|
129
|
+
*/
|
|
130
|
+
getHttpClient(): t402HTTPClient;
|
|
131
|
+
/**
|
|
132
|
+
* Get the underlying WDK instance
|
|
133
|
+
*/
|
|
134
|
+
getWdk(): T402WDK;
|
|
135
|
+
/**
|
|
136
|
+
* Get the facilitator URL
|
|
137
|
+
*/
|
|
138
|
+
getFacilitator(): string;
|
|
139
|
+
/**
|
|
140
|
+
* Get the configured chains
|
|
141
|
+
*/
|
|
142
|
+
getChains(): string[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Chain detection utilities for CAIP-2 network identifiers
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* Chain family detected from CAIP-2 network identifier
|
|
150
|
+
*/
|
|
151
|
+
type ChainFamily = 'evm' | 'ton' | 'solana' | 'tron' | 'near' | 'aptos' | 'tezos' | 'polkadot' | 'stacks' | 'cosmos';
|
|
152
|
+
/**
|
|
153
|
+
* Detect chain family from a CAIP-2 network identifier
|
|
154
|
+
*
|
|
155
|
+
* @param network - CAIP-2 network identifier (e.g., "eip155:1", "ton:mainnet")
|
|
156
|
+
* @returns The chain family
|
|
157
|
+
* @throws Error if network prefix is not recognized
|
|
158
|
+
*/
|
|
159
|
+
declare function detectChainFamily(network: string): ChainFamily;
|
|
160
|
+
/**
|
|
161
|
+
* Map of EVM chain names to CAIP-2 identifiers
|
|
162
|
+
*/
|
|
163
|
+
declare const EVM_CHAIN_MAP: Record<string, string>;
|
|
164
|
+
/**
|
|
165
|
+
* Get EVM chain name from CAIP-2 network identifier
|
|
166
|
+
*
|
|
167
|
+
* @param network - CAIP-2 network (e.g., "eip155:42161")
|
|
168
|
+
* @returns Chain name (e.g., "arbitrum") or undefined
|
|
169
|
+
*/
|
|
170
|
+
declare function getEvmChainName(network: string): string | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Check if a network is an EVM chain
|
|
173
|
+
*
|
|
174
|
+
* @param network - CAIP-2 network identifier
|
|
175
|
+
* @returns True if the network is an EVM chain
|
|
176
|
+
*/
|
|
177
|
+
declare function isEvmNetwork(network: string): boolean;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* HTTP client utilities for 402 payment handling
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Extract PaymentRequired from a 402 response.
|
|
185
|
+
* Tries V2 header first, then falls back to V1.
|
|
186
|
+
*
|
|
187
|
+
* @param response - The HTTP response with status 402
|
|
188
|
+
* @returns The parsed PaymentRequired object
|
|
189
|
+
* @throws Error if no valid payment header is found
|
|
190
|
+
*/
|
|
191
|
+
declare function extractPaymentRequired(response: Response): PaymentRequired;
|
|
192
|
+
|
|
193
|
+
export { type ChainFamily, EVM_CHAIN_MAP, type PaymentReceipt, type T402FetchResult, T402Protocol, type T402ProtocolConfig, detectChainFamily, extractPaymentRequired, getEvmChainName, isEvmNetwork };
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
21
|
+
|
|
22
|
+
// src/index.ts
|
|
23
|
+
var src_exports = {};
|
|
24
|
+
__export(src_exports, {
|
|
25
|
+
EVM_CHAIN_MAP: () => EVM_CHAIN_MAP,
|
|
26
|
+
T402Protocol: () => T402Protocol,
|
|
27
|
+
detectChainFamily: () => detectChainFamily,
|
|
28
|
+
extractPaymentRequired: () => extractPaymentRequired,
|
|
29
|
+
getEvmChainName: () => getEvmChainName,
|
|
30
|
+
isEvmNetwork: () => isEvmNetwork
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(src_exports);
|
|
33
|
+
|
|
34
|
+
// src/protocol.ts
|
|
35
|
+
var import_client = require("@t402/core/client");
|
|
36
|
+
var import_http2 = require("@t402/core/http");
|
|
37
|
+
var import_client2 = require("@t402/evm/exact/client");
|
|
38
|
+
|
|
39
|
+
// src/http-client.ts
|
|
40
|
+
var import_http = require("@t402/core/http");
|
|
41
|
+
var HEADER_PAYMENT_REQUIRED = "payment-required";
|
|
42
|
+
var HEADER_X_PAYMENT = "x-payment";
|
|
43
|
+
function extractPaymentRequired(response) {
|
|
44
|
+
const v2Header = response.headers.get(HEADER_PAYMENT_REQUIRED);
|
|
45
|
+
if (v2Header) {
|
|
46
|
+
return (0, import_http.decodePaymentRequiredHeader)(v2Header);
|
|
47
|
+
}
|
|
48
|
+
const v1Header = response.headers.get(HEADER_X_PAYMENT);
|
|
49
|
+
if (v1Header) {
|
|
50
|
+
return (0, import_http.decodePaymentRequiredHeader)(v1Header);
|
|
51
|
+
}
|
|
52
|
+
throw new Error(
|
|
53
|
+
`No payment requirements found in 402 response. Expected "${HEADER_PAYMENT_REQUIRED}" or "${HEADER_X_PAYMENT}" header.`
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/protocol.ts
|
|
58
|
+
var DEFAULT_FACILITATOR = "https://facilitator.t402.io";
|
|
59
|
+
var T402Protocol = class _T402Protocol {
|
|
60
|
+
constructor(wdk, httpClient, config) {
|
|
61
|
+
__publicField(this, "httpClient");
|
|
62
|
+
__publicField(this, "wdk");
|
|
63
|
+
__publicField(this, "facilitator");
|
|
64
|
+
__publicField(this, "chains");
|
|
65
|
+
this.wdk = wdk;
|
|
66
|
+
this.httpClient = httpClient;
|
|
67
|
+
this.facilitator = config.facilitator ?? DEFAULT_FACILITATOR;
|
|
68
|
+
this.chains = config.chains ?? [];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Create a new T402Protocol instance.
|
|
72
|
+
*
|
|
73
|
+
* This is async because it needs to initialize the WDK signer.
|
|
74
|
+
*
|
|
75
|
+
* @param wdk - An initialized T402WDK instance
|
|
76
|
+
* @param config - Protocol configuration
|
|
77
|
+
* @returns A configured T402Protocol instance
|
|
78
|
+
*/
|
|
79
|
+
static async create(wdk, config = {}) {
|
|
80
|
+
const chainName = config.chains?.[0] ?? "ethereum";
|
|
81
|
+
const signer = await wdk.getSigner(chainName);
|
|
82
|
+
const client = new import_client.t402Client();
|
|
83
|
+
(0, import_client2.registerExactEvmScheme)(client, { signer });
|
|
84
|
+
const httpClient = new import_http2.t402HTTPClient(client);
|
|
85
|
+
return new _T402Protocol(wdk, httpClient, config);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Fetch a URL with automatic 402 payment handling.
|
|
89
|
+
*
|
|
90
|
+
* 1. Makes the initial request
|
|
91
|
+
* 2. If 402, extracts payment requirements
|
|
92
|
+
* 3. Creates a properly signed payment payload (EIP-3009 for EVM)
|
|
93
|
+
* 4. Retries the request with the signed payment header
|
|
94
|
+
*
|
|
95
|
+
* @param url - URL to fetch
|
|
96
|
+
* @param init - Standard fetch RequestInit options
|
|
97
|
+
* @returns The final response and optional payment receipt
|
|
98
|
+
*/
|
|
99
|
+
async fetch(url, init) {
|
|
100
|
+
const response = await fetch(url, init);
|
|
101
|
+
if (response.status !== 402) {
|
|
102
|
+
return { response };
|
|
103
|
+
}
|
|
104
|
+
const paymentRequired = this.httpClient.getPaymentRequiredResponse(
|
|
105
|
+
(name) => response.headers.get(name)
|
|
106
|
+
);
|
|
107
|
+
const paymentPayload = await this.httpClient.createPaymentPayload(paymentRequired);
|
|
108
|
+
const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload);
|
|
109
|
+
const headers = new Headers(init?.headers);
|
|
110
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
111
|
+
headers.set(key, value);
|
|
112
|
+
}
|
|
113
|
+
const retryResponse = await fetch(url, { ...init, headers });
|
|
114
|
+
const receipt = {
|
|
115
|
+
success: retryResponse.status !== 402,
|
|
116
|
+
network: paymentPayload.accepted.network,
|
|
117
|
+
scheme: paymentPayload.accepted.scheme,
|
|
118
|
+
amount: paymentPayload.accepted.amount,
|
|
119
|
+
payTo: paymentPayload.accepted.payTo
|
|
120
|
+
};
|
|
121
|
+
return { response: retryResponse, receipt };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Extract payment requirements from a URL
|
|
125
|
+
*
|
|
126
|
+
* @param url - URL to check for payment requirements
|
|
127
|
+
* @param init - Standard fetch RequestInit options
|
|
128
|
+
* @returns The PaymentRequired object from the 402 response
|
|
129
|
+
* @throws Error if the response is not 402
|
|
130
|
+
*/
|
|
131
|
+
async getRequirements(url, init) {
|
|
132
|
+
const response = await fetch(url, init);
|
|
133
|
+
if (response.status !== 402) {
|
|
134
|
+
throw new Error(`Expected 402 response, got ${response.status}`);
|
|
135
|
+
}
|
|
136
|
+
return extractPaymentRequired(response);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Sign a payment for specific requirements using the t402 client infrastructure
|
|
140
|
+
*
|
|
141
|
+
* @param paymentRequired - The full PaymentRequired context
|
|
142
|
+
* @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)
|
|
143
|
+
*/
|
|
144
|
+
async signPayment(paymentRequired) {
|
|
145
|
+
return this.httpClient.createPaymentPayload(paymentRequired);
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Submit a request with a pre-signed payment payload
|
|
149
|
+
*
|
|
150
|
+
* @param url - URL to request
|
|
151
|
+
* @param paymentPayload - The signed payment payload
|
|
152
|
+
* @param init - Standard fetch RequestInit options
|
|
153
|
+
* @returns The HTTP response
|
|
154
|
+
*/
|
|
155
|
+
async submitPayment(url, paymentPayload, init) {
|
|
156
|
+
const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload);
|
|
157
|
+
const headers = new Headers(init?.headers);
|
|
158
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
159
|
+
headers.set(key, value);
|
|
160
|
+
}
|
|
161
|
+
return fetch(url, { ...init, headers });
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Get the underlying t402 HTTP client for advanced usage
|
|
165
|
+
*/
|
|
166
|
+
getHttpClient() {
|
|
167
|
+
return this.httpClient;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Get the underlying WDK instance
|
|
171
|
+
*/
|
|
172
|
+
getWdk() {
|
|
173
|
+
return this.wdk;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Get the facilitator URL
|
|
177
|
+
*/
|
|
178
|
+
getFacilitator() {
|
|
179
|
+
return this.facilitator;
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Get the configured chains
|
|
183
|
+
*/
|
|
184
|
+
getChains() {
|
|
185
|
+
return [...this.chains];
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// src/signer-factory.ts
|
|
190
|
+
var CAIP2_EVM = "eip155:";
|
|
191
|
+
var CAIP2_TON = "ton:";
|
|
192
|
+
var CAIP2_SOLANA = "solana:";
|
|
193
|
+
var CAIP2_TRON = "tron:";
|
|
194
|
+
var CAIP2_NEAR = "near:";
|
|
195
|
+
var CAIP2_APTOS = "aptos:";
|
|
196
|
+
var CAIP2_TEZOS = "tezos:";
|
|
197
|
+
var CAIP2_POLKADOT = "polkadot:";
|
|
198
|
+
var CAIP2_STACKS = "stacks:";
|
|
199
|
+
var CAIP2_COSMOS = "cosmos:";
|
|
200
|
+
function detectChainFamily(network) {
|
|
201
|
+
if (network.startsWith(CAIP2_EVM)) return "evm";
|
|
202
|
+
if (network.startsWith(CAIP2_TON)) return "ton";
|
|
203
|
+
if (network.startsWith(CAIP2_SOLANA)) return "solana";
|
|
204
|
+
if (network.startsWith(CAIP2_TRON)) return "tron";
|
|
205
|
+
if (network.startsWith(CAIP2_NEAR)) return "near";
|
|
206
|
+
if (network.startsWith(CAIP2_APTOS)) return "aptos";
|
|
207
|
+
if (network.startsWith(CAIP2_TEZOS)) return "tezos";
|
|
208
|
+
if (network.startsWith(CAIP2_POLKADOT)) return "polkadot";
|
|
209
|
+
if (network.startsWith(CAIP2_STACKS)) return "stacks";
|
|
210
|
+
if (network.startsWith(CAIP2_COSMOS)) return "cosmos";
|
|
211
|
+
throw new Error(
|
|
212
|
+
`Unsupported network: ${network}. Cannot detect chain family from CAIP-2 prefix.`
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
var EVM_CHAIN_MAP = {
|
|
216
|
+
ethereum: "eip155:1",
|
|
217
|
+
base: "eip155:8453",
|
|
218
|
+
arbitrum: "eip155:42161",
|
|
219
|
+
optimism: "eip155:10",
|
|
220
|
+
polygon: "eip155:137",
|
|
221
|
+
avalanche: "eip155:43114",
|
|
222
|
+
ink: "eip155:57073",
|
|
223
|
+
berachain: "eip155:80094",
|
|
224
|
+
unichain: "eip155:130"
|
|
225
|
+
};
|
|
226
|
+
function getEvmChainName(network) {
|
|
227
|
+
for (const [name, caip2] of Object.entries(EVM_CHAIN_MAP)) {
|
|
228
|
+
if (caip2 === network) return name;
|
|
229
|
+
}
|
|
230
|
+
return void 0;
|
|
231
|
+
}
|
|
232
|
+
function isEvmNetwork(network) {
|
|
233
|
+
return network.startsWith(CAIP2_EVM);
|
|
234
|
+
}
|
|
235
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
236
|
+
0 && (module.exports = {
|
|
237
|
+
EVM_CHAIN_MAP,
|
|
238
|
+
T402Protocol,
|
|
239
|
+
detectChainFamily,
|
|
240
|
+
extractPaymentRequired,
|
|
241
|
+
getEvmChainName,
|
|
242
|
+
isEvmNetwork
|
|
243
|
+
});
|
|
244
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/index.ts","../../src/protocol.ts","../../src/http-client.ts","../../src/signer-factory.ts"],"sourcesContent":["/**\n * @module @t402/wdk-protocol\n *\n * T402 payment protocol for Tether WDK wallet apps.\n *\n * Enables any WDK-based wallet to handle HTTP 402 payments:\n *\n * @example\n * ```typescript\n * import { T402Protocol } from '@t402/wdk-protocol';\n * import { T402WDK } from '@t402/wdk';\n *\n * const wdk = new T402WDK(seedPhrase, { arbitrum: rpcUrl });\n * const t402 = await T402Protocol.create(wdk, {\n * chains: ['ethereum', 'arbitrum'],\n * });\n *\n * // Auto-pay for 402 resources\n * const { response, receipt } = await t402.fetch('https://api.example.com/premium');\n * ```\n */\n\n// Main class\nexport { T402Protocol } from './protocol.js'\n\n// Chain detection utilities\nexport {\n detectChainFamily,\n isEvmNetwork,\n getEvmChainName,\n EVM_CHAIN_MAP,\n type ChainFamily,\n} from './signer-factory.js'\n\n// HTTP client utilities\nexport { extractPaymentRequired } from './http-client.js'\n\n// Types\nexport type { T402ProtocolConfig, PaymentReceipt, T402FetchResult } from './types.js'\n","/**\n * T402Protocol - Main class for WDK apps to add T402 payment capability\n *\n * Uses the real t402 client infrastructure (t402Client + mechanism-specific\n * scheme clients) for proper payment payload creation and signing.\n *\n * @example\n * ```typescript\n * import { T402Protocol } from '@t402/wdk-protocol';\n * import { T402WDK } from '@t402/wdk';\n *\n * const wdk = new T402WDK(seedPhrase, { arbitrum: rpcUrl });\n * const t402 = await T402Protocol.create(wdk, {\n * chains: ['ethereum', 'arbitrum'],\n * });\n *\n * // Auto-pay for HTTP 402 resources\n * const { response, receipt } = await t402.fetch('https://api.example.com/premium');\n * ```\n */\n\nimport { t402Client } from '@t402/core/client'\nimport { t402HTTPClient } from '@t402/core/http'\nimport type { PaymentRequired, PaymentPayload } from '@t402/core/types'\nimport { registerExactEvmScheme } from '@t402/evm/exact/client'\nimport type { T402WDK } from '@t402/wdk'\n\nimport { extractPaymentRequired } from './http-client.js'\nimport type { T402ProtocolConfig, T402FetchResult, PaymentReceipt } from './types.js'\n\nconst DEFAULT_FACILITATOR = 'https://facilitator.t402.io'\n\n/**\n * T402Protocol enables any WDK wallet app to handle HTTP 402 payments.\n *\n * Uses the real t402 protocol client infrastructure with EVM mechanism support.\n * Payment payloads are properly signed using EIP-3009 authorization.\n */\nexport class T402Protocol {\n private httpClient: t402HTTPClient\n private wdk: T402WDK\n private facilitator: string\n private chains: string[]\n\n private constructor(\n wdk: T402WDK,\n httpClient: t402HTTPClient,\n config: T402ProtocolConfig,\n ) {\n this.wdk = wdk\n this.httpClient = httpClient\n this.facilitator = config.facilitator ?? DEFAULT_FACILITATOR\n this.chains = config.chains ?? []\n }\n\n /**\n * Create a new T402Protocol instance.\n *\n * This is async because it needs to initialize the WDK signer.\n *\n * @param wdk - An initialized T402WDK instance\n * @param config - Protocol configuration\n * @returns A configured T402Protocol instance\n */\n static async create(wdk: T402WDK, config: T402ProtocolConfig = {}): Promise<T402Protocol> {\n // Get an EVM signer from WDK for the first available chain\n const chainName = config.chains?.[0] ?? 'ethereum'\n const signer = await wdk.getSigner(chainName)\n\n // Create t402 client with EVM exact scheme\n const client = new t402Client()\n registerExactEvmScheme(client, { signer })\n\n const httpClient = new t402HTTPClient(client)\n\n return new T402Protocol(wdk, httpClient, config)\n }\n\n /**\n * Fetch a URL with automatic 402 payment handling.\n *\n * 1. Makes the initial request\n * 2. If 402, extracts payment requirements\n * 3. Creates a properly signed payment payload (EIP-3009 for EVM)\n * 4. Retries the request with the signed payment header\n *\n * @param url - URL to fetch\n * @param init - Standard fetch RequestInit options\n * @returns The final response and optional payment receipt\n */\n async fetch(url: string | URL, init?: RequestInit): Promise<T402FetchResult> {\n // Make initial request\n const response = await fetch(url, init)\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return { response }\n }\n\n // Extract payment requirements from 402 response\n const paymentRequired = this.httpClient.getPaymentRequiredResponse(\n (name: string) => response.headers.get(name),\n )\n\n // Create signed payment payload using mechanism-specific logic\n const paymentPayload = await this.httpClient.createPaymentPayload(paymentRequired)\n\n // Build retry headers\n const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload)\n const headers = new Headers(init?.headers)\n for (const [key, value] of Object.entries(paymentHeaders)) {\n headers.set(key, value)\n }\n\n // Retry with payment\n const retryResponse = await fetch(url, { ...init, headers })\n\n const receipt: PaymentReceipt = {\n success: retryResponse.status !== 402,\n network: paymentPayload.accepted.network,\n scheme: paymentPayload.accepted.scheme,\n amount: paymentPayload.accepted.amount,\n payTo: paymentPayload.accepted.payTo,\n }\n\n return { response: retryResponse, receipt }\n }\n\n /**\n * Extract payment requirements from a URL\n *\n * @param url - URL to check for payment requirements\n * @param init - Standard fetch RequestInit options\n * @returns The PaymentRequired object from the 402 response\n * @throws Error if the response is not 402\n */\n async getRequirements(url: string | URL, init?: RequestInit): Promise<PaymentRequired> {\n const response = await fetch(url, init)\n if (response.status !== 402) {\n throw new Error(`Expected 402 response, got ${response.status}`)\n }\n return extractPaymentRequired(response)\n }\n\n /**\n * Sign a payment for specific requirements using the t402 client infrastructure\n *\n * @param paymentRequired - The full PaymentRequired context\n * @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)\n */\n async signPayment(paymentRequired: PaymentRequired): Promise<PaymentPayload> {\n return this.httpClient.createPaymentPayload(paymentRequired)\n }\n\n /**\n * Submit a request with a pre-signed payment payload\n *\n * @param url - URL to request\n * @param paymentPayload - The signed payment payload\n * @param init - Standard fetch RequestInit options\n * @returns The HTTP response\n */\n async submitPayment(\n url: string | URL,\n paymentPayload: PaymentPayload,\n init?: RequestInit,\n ): Promise<Response> {\n const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload)\n const headers = new Headers(init?.headers)\n for (const [key, value] of Object.entries(paymentHeaders)) {\n headers.set(key, value)\n }\n\n return fetch(url, { ...init, headers })\n }\n\n /**\n * Get the underlying t402 HTTP client for advanced usage\n */\n getHttpClient(): t402HTTPClient {\n return this.httpClient\n }\n\n /**\n * Get the underlying WDK instance\n */\n getWdk(): T402WDK {\n return this.wdk\n }\n\n /**\n * Get the facilitator URL\n */\n getFacilitator(): string {\n return this.facilitator\n }\n\n /**\n * Get the configured chains\n */\n getChains(): string[] {\n return [...this.chains]\n }\n}\n","/**\n * HTTP client utilities for 402 payment handling\n */\n\nimport { decodePaymentRequiredHeader } from '@t402/core/http'\nimport type { PaymentRequired } from '@t402/core/types'\n\n/** V2 header names */\nconst HEADER_PAYMENT_REQUIRED = 'payment-required'\n\n/** V1 header names (fallback) */\nconst HEADER_X_PAYMENT = 'x-payment'\n\n/**\n * Extract PaymentRequired from a 402 response.\n * Tries V2 header first, then falls back to V1.\n *\n * @param response - The HTTP response with status 402\n * @returns The parsed PaymentRequired object\n * @throws Error if no valid payment header is found\n */\nexport function extractPaymentRequired(response: Response): PaymentRequired {\n // Try V2 header\n const v2Header = response.headers.get(HEADER_PAYMENT_REQUIRED)\n if (v2Header) {\n return decodePaymentRequiredHeader(v2Header)\n }\n\n // Try V1 header\n const v1Header = response.headers.get(HEADER_X_PAYMENT)\n if (v1Header) {\n return decodePaymentRequiredHeader(v1Header)\n }\n\n throw new Error(\n 'No payment requirements found in 402 response. ' +\n `Expected \"${HEADER_PAYMENT_REQUIRED}\" or \"${HEADER_X_PAYMENT}\" header.`,\n )\n}\n","/**\n * Chain detection utilities for CAIP-2 network identifiers\n */\n\n/**\n * CAIP-2 namespace prefixes\n */\nconst CAIP2_EVM = 'eip155:'\nconst CAIP2_TON = 'ton:'\nconst CAIP2_SOLANA = 'solana:'\nconst CAIP2_TRON = 'tron:'\nconst CAIP2_NEAR = 'near:'\nconst CAIP2_APTOS = 'aptos:'\nconst CAIP2_TEZOS = 'tezos:'\nconst CAIP2_POLKADOT = 'polkadot:'\nconst CAIP2_STACKS = 'stacks:'\nconst CAIP2_COSMOS = 'cosmos:'\n\n/**\n * Chain family detected from CAIP-2 network identifier\n */\nexport type ChainFamily =\n | 'evm'\n | 'ton'\n | 'solana'\n | 'tron'\n | 'near'\n | 'aptos'\n | 'tezos'\n | 'polkadot'\n | 'stacks'\n | 'cosmos'\n\n/**\n * Detect chain family from a CAIP-2 network identifier\n *\n * @param network - CAIP-2 network identifier (e.g., \"eip155:1\", \"ton:mainnet\")\n * @returns The chain family\n * @throws Error if network prefix is not recognized\n */\nexport function detectChainFamily(network: string): ChainFamily {\n if (network.startsWith(CAIP2_EVM)) return 'evm'\n if (network.startsWith(CAIP2_TON)) return 'ton'\n if (network.startsWith(CAIP2_SOLANA)) return 'solana'\n if (network.startsWith(CAIP2_TRON)) return 'tron'\n if (network.startsWith(CAIP2_NEAR)) return 'near'\n if (network.startsWith(CAIP2_APTOS)) return 'aptos'\n if (network.startsWith(CAIP2_TEZOS)) return 'tezos'\n if (network.startsWith(CAIP2_POLKADOT)) return 'polkadot'\n if (network.startsWith(CAIP2_STACKS)) return 'stacks'\n if (network.startsWith(CAIP2_COSMOS)) return 'cosmos'\n\n throw new Error(\n `Unsupported network: ${network}. Cannot detect chain family from CAIP-2 prefix.`,\n )\n}\n\n/**\n * Map of EVM chain names to CAIP-2 identifiers\n */\nexport const EVM_CHAIN_MAP: Record<string, string> = {\n ethereum: 'eip155:1',\n base: 'eip155:8453',\n arbitrum: 'eip155:42161',\n optimism: 'eip155:10',\n polygon: 'eip155:137',\n avalanche: 'eip155:43114',\n ink: 'eip155:57073',\n berachain: 'eip155:80094',\n unichain: 'eip155:130',\n}\n\n/**\n * Get EVM chain name from CAIP-2 network identifier\n *\n * @param network - CAIP-2 network (e.g., \"eip155:42161\")\n * @returns Chain name (e.g., \"arbitrum\") or undefined\n */\nexport function getEvmChainName(network: string): string | undefined {\n for (const [name, caip2] of Object.entries(EVM_CHAIN_MAP)) {\n if (caip2 === network) return name\n }\n return undefined\n}\n\n/**\n * Check if a network is an EVM chain\n *\n * @param network - CAIP-2 network identifier\n * @returns True if the network is an EVM chain\n */\nexport function isEvmNetwork(network: string): boolean {\n return network.startsWith(CAIP2_EVM)\n}\n"],"mappings":"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","names":["import_http","import_client"]}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { t402HTTPClient } from '@t402/core/http';
|
|
2
|
+
import { PaymentRequired, PaymentPayload } from '@t402/core/types';
|
|
3
|
+
import { T402WDK } from '@t402/wdk';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Type definitions for @t402/wdk-protocol
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for the T402 protocol module
|
|
10
|
+
*/
|
|
11
|
+
interface T402ProtocolConfig {
|
|
12
|
+
/** Facilitator URL for payment verification/settlement (default: https://facilitator.t402.io) */
|
|
13
|
+
facilitator?: string;
|
|
14
|
+
/** CAIP-2 networks or chain names to support */
|
|
15
|
+
chains?: string[];
|
|
16
|
+
/** WDK account index to use (default: 0) */
|
|
17
|
+
accountIndex?: number;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Result of a successful payment
|
|
21
|
+
*/
|
|
22
|
+
interface PaymentReceipt {
|
|
23
|
+
/** Whether payment was successful */
|
|
24
|
+
success: boolean;
|
|
25
|
+
/** The payment network used */
|
|
26
|
+
network: string;
|
|
27
|
+
/** The payment scheme used */
|
|
28
|
+
scheme: string;
|
|
29
|
+
/** Amount paid */
|
|
30
|
+
amount: string;
|
|
31
|
+
/** Address paid to */
|
|
32
|
+
payTo: string;
|
|
33
|
+
/** Settlement transaction hash (if settled) */
|
|
34
|
+
transaction?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Result from T402Protocol.fetch()
|
|
38
|
+
*/
|
|
39
|
+
interface T402FetchResult {
|
|
40
|
+
/** The HTTP response */
|
|
41
|
+
response: Response;
|
|
42
|
+
/** Payment receipt if a 402 was handled */
|
|
43
|
+
receipt?: PaymentReceipt;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* T402Protocol - Main class for WDK apps to add T402 payment capability
|
|
48
|
+
*
|
|
49
|
+
* Uses the real t402 client infrastructure (t402Client + mechanism-specific
|
|
50
|
+
* scheme clients) for proper payment payload creation and signing.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* import { T402Protocol } from '@t402/wdk-protocol';
|
|
55
|
+
* import { T402WDK } from '@t402/wdk';
|
|
56
|
+
*
|
|
57
|
+
* const wdk = new T402WDK(seedPhrase, { arbitrum: rpcUrl });
|
|
58
|
+
* const t402 = await T402Protocol.create(wdk, {
|
|
59
|
+
* chains: ['ethereum', 'arbitrum'],
|
|
60
|
+
* });
|
|
61
|
+
*
|
|
62
|
+
* // Auto-pay for HTTP 402 resources
|
|
63
|
+
* const { response, receipt } = await t402.fetch('https://api.example.com/premium');
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* T402Protocol enables any WDK wallet app to handle HTTP 402 payments.
|
|
69
|
+
*
|
|
70
|
+
* Uses the real t402 protocol client infrastructure with EVM mechanism support.
|
|
71
|
+
* Payment payloads are properly signed using EIP-3009 authorization.
|
|
72
|
+
*/
|
|
73
|
+
declare class T402Protocol {
|
|
74
|
+
private httpClient;
|
|
75
|
+
private wdk;
|
|
76
|
+
private facilitator;
|
|
77
|
+
private chains;
|
|
78
|
+
private constructor();
|
|
79
|
+
/**
|
|
80
|
+
* Create a new T402Protocol instance.
|
|
81
|
+
*
|
|
82
|
+
* This is async because it needs to initialize the WDK signer.
|
|
83
|
+
*
|
|
84
|
+
* @param wdk - An initialized T402WDK instance
|
|
85
|
+
* @param config - Protocol configuration
|
|
86
|
+
* @returns A configured T402Protocol instance
|
|
87
|
+
*/
|
|
88
|
+
static create(wdk: T402WDK, config?: T402ProtocolConfig): Promise<T402Protocol>;
|
|
89
|
+
/**
|
|
90
|
+
* Fetch a URL with automatic 402 payment handling.
|
|
91
|
+
*
|
|
92
|
+
* 1. Makes the initial request
|
|
93
|
+
* 2. If 402, extracts payment requirements
|
|
94
|
+
* 3. Creates a properly signed payment payload (EIP-3009 for EVM)
|
|
95
|
+
* 4. Retries the request with the signed payment header
|
|
96
|
+
*
|
|
97
|
+
* @param url - URL to fetch
|
|
98
|
+
* @param init - Standard fetch RequestInit options
|
|
99
|
+
* @returns The final response and optional payment receipt
|
|
100
|
+
*/
|
|
101
|
+
fetch(url: string | URL, init?: RequestInit): Promise<T402FetchResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Extract payment requirements from a URL
|
|
104
|
+
*
|
|
105
|
+
* @param url - URL to check for payment requirements
|
|
106
|
+
* @param init - Standard fetch RequestInit options
|
|
107
|
+
* @returns The PaymentRequired object from the 402 response
|
|
108
|
+
* @throws Error if the response is not 402
|
|
109
|
+
*/
|
|
110
|
+
getRequirements(url: string | URL, init?: RequestInit): Promise<PaymentRequired>;
|
|
111
|
+
/**
|
|
112
|
+
* Sign a payment for specific requirements using the t402 client infrastructure
|
|
113
|
+
*
|
|
114
|
+
* @param paymentRequired - The full PaymentRequired context
|
|
115
|
+
* @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)
|
|
116
|
+
*/
|
|
117
|
+
signPayment(paymentRequired: PaymentRequired): Promise<PaymentPayload>;
|
|
118
|
+
/**
|
|
119
|
+
* Submit a request with a pre-signed payment payload
|
|
120
|
+
*
|
|
121
|
+
* @param url - URL to request
|
|
122
|
+
* @param paymentPayload - The signed payment payload
|
|
123
|
+
* @param init - Standard fetch RequestInit options
|
|
124
|
+
* @returns The HTTP response
|
|
125
|
+
*/
|
|
126
|
+
submitPayment(url: string | URL, paymentPayload: PaymentPayload, init?: RequestInit): Promise<Response>;
|
|
127
|
+
/**
|
|
128
|
+
* Get the underlying t402 HTTP client for advanced usage
|
|
129
|
+
*/
|
|
130
|
+
getHttpClient(): t402HTTPClient;
|
|
131
|
+
/**
|
|
132
|
+
* Get the underlying WDK instance
|
|
133
|
+
*/
|
|
134
|
+
getWdk(): T402WDK;
|
|
135
|
+
/**
|
|
136
|
+
* Get the facilitator URL
|
|
137
|
+
*/
|
|
138
|
+
getFacilitator(): string;
|
|
139
|
+
/**
|
|
140
|
+
* Get the configured chains
|
|
141
|
+
*/
|
|
142
|
+
getChains(): string[];
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Chain detection utilities for CAIP-2 network identifiers
|
|
147
|
+
*/
|
|
148
|
+
/**
|
|
149
|
+
* Chain family detected from CAIP-2 network identifier
|
|
150
|
+
*/
|
|
151
|
+
type ChainFamily = 'evm' | 'ton' | 'solana' | 'tron' | 'near' | 'aptos' | 'tezos' | 'polkadot' | 'stacks' | 'cosmos';
|
|
152
|
+
/**
|
|
153
|
+
* Detect chain family from a CAIP-2 network identifier
|
|
154
|
+
*
|
|
155
|
+
* @param network - CAIP-2 network identifier (e.g., "eip155:1", "ton:mainnet")
|
|
156
|
+
* @returns The chain family
|
|
157
|
+
* @throws Error if network prefix is not recognized
|
|
158
|
+
*/
|
|
159
|
+
declare function detectChainFamily(network: string): ChainFamily;
|
|
160
|
+
/**
|
|
161
|
+
* Map of EVM chain names to CAIP-2 identifiers
|
|
162
|
+
*/
|
|
163
|
+
declare const EVM_CHAIN_MAP: Record<string, string>;
|
|
164
|
+
/**
|
|
165
|
+
* Get EVM chain name from CAIP-2 network identifier
|
|
166
|
+
*
|
|
167
|
+
* @param network - CAIP-2 network (e.g., "eip155:42161")
|
|
168
|
+
* @returns Chain name (e.g., "arbitrum") or undefined
|
|
169
|
+
*/
|
|
170
|
+
declare function getEvmChainName(network: string): string | undefined;
|
|
171
|
+
/**
|
|
172
|
+
* Check if a network is an EVM chain
|
|
173
|
+
*
|
|
174
|
+
* @param network - CAIP-2 network identifier
|
|
175
|
+
* @returns True if the network is an EVM chain
|
|
176
|
+
*/
|
|
177
|
+
declare function isEvmNetwork(network: string): boolean;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* HTTP client utilities for 402 payment handling
|
|
181
|
+
*/
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Extract PaymentRequired from a 402 response.
|
|
185
|
+
* Tries V2 header first, then falls back to V1.
|
|
186
|
+
*
|
|
187
|
+
* @param response - The HTTP response with status 402
|
|
188
|
+
* @returns The parsed PaymentRequired object
|
|
189
|
+
* @throws Error if no valid payment header is found
|
|
190
|
+
*/
|
|
191
|
+
declare function extractPaymentRequired(response: Response): PaymentRequired;
|
|
192
|
+
|
|
193
|
+
export { type ChainFamily, EVM_CHAIN_MAP, type PaymentReceipt, type T402FetchResult, T402Protocol, type T402ProtocolConfig, detectChainFamily, extractPaymentRequired, getEvmChainName, isEvmNetwork };
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
|
|
5
|
+
// src/protocol.ts
|
|
6
|
+
import { t402Client } from "@t402/core/client";
|
|
7
|
+
import { t402HTTPClient } from "@t402/core/http";
|
|
8
|
+
import { registerExactEvmScheme } from "@t402/evm/exact/client";
|
|
9
|
+
|
|
10
|
+
// src/http-client.ts
|
|
11
|
+
import { decodePaymentRequiredHeader } from "@t402/core/http";
|
|
12
|
+
var HEADER_PAYMENT_REQUIRED = "payment-required";
|
|
13
|
+
var HEADER_X_PAYMENT = "x-payment";
|
|
14
|
+
function extractPaymentRequired(response) {
|
|
15
|
+
const v2Header = response.headers.get(HEADER_PAYMENT_REQUIRED);
|
|
16
|
+
if (v2Header) {
|
|
17
|
+
return decodePaymentRequiredHeader(v2Header);
|
|
18
|
+
}
|
|
19
|
+
const v1Header = response.headers.get(HEADER_X_PAYMENT);
|
|
20
|
+
if (v1Header) {
|
|
21
|
+
return decodePaymentRequiredHeader(v1Header);
|
|
22
|
+
}
|
|
23
|
+
throw new Error(
|
|
24
|
+
`No payment requirements found in 402 response. Expected "${HEADER_PAYMENT_REQUIRED}" or "${HEADER_X_PAYMENT}" header.`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/protocol.ts
|
|
29
|
+
var DEFAULT_FACILITATOR = "https://facilitator.t402.io";
|
|
30
|
+
var T402Protocol = class _T402Protocol {
|
|
31
|
+
constructor(wdk, httpClient, config) {
|
|
32
|
+
__publicField(this, "httpClient");
|
|
33
|
+
__publicField(this, "wdk");
|
|
34
|
+
__publicField(this, "facilitator");
|
|
35
|
+
__publicField(this, "chains");
|
|
36
|
+
this.wdk = wdk;
|
|
37
|
+
this.httpClient = httpClient;
|
|
38
|
+
this.facilitator = config.facilitator ?? DEFAULT_FACILITATOR;
|
|
39
|
+
this.chains = config.chains ?? [];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Create a new T402Protocol instance.
|
|
43
|
+
*
|
|
44
|
+
* This is async because it needs to initialize the WDK signer.
|
|
45
|
+
*
|
|
46
|
+
* @param wdk - An initialized T402WDK instance
|
|
47
|
+
* @param config - Protocol configuration
|
|
48
|
+
* @returns A configured T402Protocol instance
|
|
49
|
+
*/
|
|
50
|
+
static async create(wdk, config = {}) {
|
|
51
|
+
const chainName = config.chains?.[0] ?? "ethereum";
|
|
52
|
+
const signer = await wdk.getSigner(chainName);
|
|
53
|
+
const client = new t402Client();
|
|
54
|
+
registerExactEvmScheme(client, { signer });
|
|
55
|
+
const httpClient = new t402HTTPClient(client);
|
|
56
|
+
return new _T402Protocol(wdk, httpClient, config);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Fetch a URL with automatic 402 payment handling.
|
|
60
|
+
*
|
|
61
|
+
* 1. Makes the initial request
|
|
62
|
+
* 2. If 402, extracts payment requirements
|
|
63
|
+
* 3. Creates a properly signed payment payload (EIP-3009 for EVM)
|
|
64
|
+
* 4. Retries the request with the signed payment header
|
|
65
|
+
*
|
|
66
|
+
* @param url - URL to fetch
|
|
67
|
+
* @param init - Standard fetch RequestInit options
|
|
68
|
+
* @returns The final response and optional payment receipt
|
|
69
|
+
*/
|
|
70
|
+
async fetch(url, init) {
|
|
71
|
+
const response = await fetch(url, init);
|
|
72
|
+
if (response.status !== 402) {
|
|
73
|
+
return { response };
|
|
74
|
+
}
|
|
75
|
+
const paymentRequired = this.httpClient.getPaymentRequiredResponse(
|
|
76
|
+
(name) => response.headers.get(name)
|
|
77
|
+
);
|
|
78
|
+
const paymentPayload = await this.httpClient.createPaymentPayload(paymentRequired);
|
|
79
|
+
const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload);
|
|
80
|
+
const headers = new Headers(init?.headers);
|
|
81
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
82
|
+
headers.set(key, value);
|
|
83
|
+
}
|
|
84
|
+
const retryResponse = await fetch(url, { ...init, headers });
|
|
85
|
+
const receipt = {
|
|
86
|
+
success: retryResponse.status !== 402,
|
|
87
|
+
network: paymentPayload.accepted.network,
|
|
88
|
+
scheme: paymentPayload.accepted.scheme,
|
|
89
|
+
amount: paymentPayload.accepted.amount,
|
|
90
|
+
payTo: paymentPayload.accepted.payTo
|
|
91
|
+
};
|
|
92
|
+
return { response: retryResponse, receipt };
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Extract payment requirements from a URL
|
|
96
|
+
*
|
|
97
|
+
* @param url - URL to check for payment requirements
|
|
98
|
+
* @param init - Standard fetch RequestInit options
|
|
99
|
+
* @returns The PaymentRequired object from the 402 response
|
|
100
|
+
* @throws Error if the response is not 402
|
|
101
|
+
*/
|
|
102
|
+
async getRequirements(url, init) {
|
|
103
|
+
const response = await fetch(url, init);
|
|
104
|
+
if (response.status !== 402) {
|
|
105
|
+
throw new Error(`Expected 402 response, got ${response.status}`);
|
|
106
|
+
}
|
|
107
|
+
return extractPaymentRequired(response);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Sign a payment for specific requirements using the t402 client infrastructure
|
|
111
|
+
*
|
|
112
|
+
* @param paymentRequired - The full PaymentRequired context
|
|
113
|
+
* @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)
|
|
114
|
+
*/
|
|
115
|
+
async signPayment(paymentRequired) {
|
|
116
|
+
return this.httpClient.createPaymentPayload(paymentRequired);
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Submit a request with a pre-signed payment payload
|
|
120
|
+
*
|
|
121
|
+
* @param url - URL to request
|
|
122
|
+
* @param paymentPayload - The signed payment payload
|
|
123
|
+
* @param init - Standard fetch RequestInit options
|
|
124
|
+
* @returns The HTTP response
|
|
125
|
+
*/
|
|
126
|
+
async submitPayment(url, paymentPayload, init) {
|
|
127
|
+
const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload);
|
|
128
|
+
const headers = new Headers(init?.headers);
|
|
129
|
+
for (const [key, value] of Object.entries(paymentHeaders)) {
|
|
130
|
+
headers.set(key, value);
|
|
131
|
+
}
|
|
132
|
+
return fetch(url, { ...init, headers });
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get the underlying t402 HTTP client for advanced usage
|
|
136
|
+
*/
|
|
137
|
+
getHttpClient() {
|
|
138
|
+
return this.httpClient;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get the underlying WDK instance
|
|
142
|
+
*/
|
|
143
|
+
getWdk() {
|
|
144
|
+
return this.wdk;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Get the facilitator URL
|
|
148
|
+
*/
|
|
149
|
+
getFacilitator() {
|
|
150
|
+
return this.facilitator;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Get the configured chains
|
|
154
|
+
*/
|
|
155
|
+
getChains() {
|
|
156
|
+
return [...this.chains];
|
|
157
|
+
}
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
// src/signer-factory.ts
|
|
161
|
+
var CAIP2_EVM = "eip155:";
|
|
162
|
+
var CAIP2_TON = "ton:";
|
|
163
|
+
var CAIP2_SOLANA = "solana:";
|
|
164
|
+
var CAIP2_TRON = "tron:";
|
|
165
|
+
var CAIP2_NEAR = "near:";
|
|
166
|
+
var CAIP2_APTOS = "aptos:";
|
|
167
|
+
var CAIP2_TEZOS = "tezos:";
|
|
168
|
+
var CAIP2_POLKADOT = "polkadot:";
|
|
169
|
+
var CAIP2_STACKS = "stacks:";
|
|
170
|
+
var CAIP2_COSMOS = "cosmos:";
|
|
171
|
+
function detectChainFamily(network) {
|
|
172
|
+
if (network.startsWith(CAIP2_EVM)) return "evm";
|
|
173
|
+
if (network.startsWith(CAIP2_TON)) return "ton";
|
|
174
|
+
if (network.startsWith(CAIP2_SOLANA)) return "solana";
|
|
175
|
+
if (network.startsWith(CAIP2_TRON)) return "tron";
|
|
176
|
+
if (network.startsWith(CAIP2_NEAR)) return "near";
|
|
177
|
+
if (network.startsWith(CAIP2_APTOS)) return "aptos";
|
|
178
|
+
if (network.startsWith(CAIP2_TEZOS)) return "tezos";
|
|
179
|
+
if (network.startsWith(CAIP2_POLKADOT)) return "polkadot";
|
|
180
|
+
if (network.startsWith(CAIP2_STACKS)) return "stacks";
|
|
181
|
+
if (network.startsWith(CAIP2_COSMOS)) return "cosmos";
|
|
182
|
+
throw new Error(
|
|
183
|
+
`Unsupported network: ${network}. Cannot detect chain family from CAIP-2 prefix.`
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
var EVM_CHAIN_MAP = {
|
|
187
|
+
ethereum: "eip155:1",
|
|
188
|
+
base: "eip155:8453",
|
|
189
|
+
arbitrum: "eip155:42161",
|
|
190
|
+
optimism: "eip155:10",
|
|
191
|
+
polygon: "eip155:137",
|
|
192
|
+
avalanche: "eip155:43114",
|
|
193
|
+
ink: "eip155:57073",
|
|
194
|
+
berachain: "eip155:80094",
|
|
195
|
+
unichain: "eip155:130"
|
|
196
|
+
};
|
|
197
|
+
function getEvmChainName(network) {
|
|
198
|
+
for (const [name, caip2] of Object.entries(EVM_CHAIN_MAP)) {
|
|
199
|
+
if (caip2 === network) return name;
|
|
200
|
+
}
|
|
201
|
+
return void 0;
|
|
202
|
+
}
|
|
203
|
+
function isEvmNetwork(network) {
|
|
204
|
+
return network.startsWith(CAIP2_EVM);
|
|
205
|
+
}
|
|
206
|
+
export {
|
|
207
|
+
EVM_CHAIN_MAP,
|
|
208
|
+
T402Protocol,
|
|
209
|
+
detectChainFamily,
|
|
210
|
+
extractPaymentRequired,
|
|
211
|
+
getEvmChainName,
|
|
212
|
+
isEvmNetwork
|
|
213
|
+
};
|
|
214
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/protocol.ts","../../src/http-client.ts","../../src/signer-factory.ts"],"sourcesContent":["/**\n * T402Protocol - Main class for WDK apps to add T402 payment capability\n *\n * Uses the real t402 client infrastructure (t402Client + mechanism-specific\n * scheme clients) for proper payment payload creation and signing.\n *\n * @example\n * ```typescript\n * import { T402Protocol } from '@t402/wdk-protocol';\n * import { T402WDK } from '@t402/wdk';\n *\n * const wdk = new T402WDK(seedPhrase, { arbitrum: rpcUrl });\n * const t402 = await T402Protocol.create(wdk, {\n * chains: ['ethereum', 'arbitrum'],\n * });\n *\n * // Auto-pay for HTTP 402 resources\n * const { response, receipt } = await t402.fetch('https://api.example.com/premium');\n * ```\n */\n\nimport { t402Client } from '@t402/core/client'\nimport { t402HTTPClient } from '@t402/core/http'\nimport type { PaymentRequired, PaymentPayload } from '@t402/core/types'\nimport { registerExactEvmScheme } from '@t402/evm/exact/client'\nimport type { T402WDK } from '@t402/wdk'\n\nimport { extractPaymentRequired } from './http-client.js'\nimport type { T402ProtocolConfig, T402FetchResult, PaymentReceipt } from './types.js'\n\nconst DEFAULT_FACILITATOR = 'https://facilitator.t402.io'\n\n/**\n * T402Protocol enables any WDK wallet app to handle HTTP 402 payments.\n *\n * Uses the real t402 protocol client infrastructure with EVM mechanism support.\n * Payment payloads are properly signed using EIP-3009 authorization.\n */\nexport class T402Protocol {\n private httpClient: t402HTTPClient\n private wdk: T402WDK\n private facilitator: string\n private chains: string[]\n\n private constructor(\n wdk: T402WDK,\n httpClient: t402HTTPClient,\n config: T402ProtocolConfig,\n ) {\n this.wdk = wdk\n this.httpClient = httpClient\n this.facilitator = config.facilitator ?? DEFAULT_FACILITATOR\n this.chains = config.chains ?? []\n }\n\n /**\n * Create a new T402Protocol instance.\n *\n * This is async because it needs to initialize the WDK signer.\n *\n * @param wdk - An initialized T402WDK instance\n * @param config - Protocol configuration\n * @returns A configured T402Protocol instance\n */\n static async create(wdk: T402WDK, config: T402ProtocolConfig = {}): Promise<T402Protocol> {\n // Get an EVM signer from WDK for the first available chain\n const chainName = config.chains?.[0] ?? 'ethereum'\n const signer = await wdk.getSigner(chainName)\n\n // Create t402 client with EVM exact scheme\n const client = new t402Client()\n registerExactEvmScheme(client, { signer })\n\n const httpClient = new t402HTTPClient(client)\n\n return new T402Protocol(wdk, httpClient, config)\n }\n\n /**\n * Fetch a URL with automatic 402 payment handling.\n *\n * 1. Makes the initial request\n * 2. If 402, extracts payment requirements\n * 3. Creates a properly signed payment payload (EIP-3009 for EVM)\n * 4. Retries the request with the signed payment header\n *\n * @param url - URL to fetch\n * @param init - Standard fetch RequestInit options\n * @returns The final response and optional payment receipt\n */\n async fetch(url: string | URL, init?: RequestInit): Promise<T402FetchResult> {\n // Make initial request\n const response = await fetch(url, init)\n\n // If not 402, return as-is\n if (response.status !== 402) {\n return { response }\n }\n\n // Extract payment requirements from 402 response\n const paymentRequired = this.httpClient.getPaymentRequiredResponse(\n (name: string) => response.headers.get(name),\n )\n\n // Create signed payment payload using mechanism-specific logic\n const paymentPayload = await this.httpClient.createPaymentPayload(paymentRequired)\n\n // Build retry headers\n const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload)\n const headers = new Headers(init?.headers)\n for (const [key, value] of Object.entries(paymentHeaders)) {\n headers.set(key, value)\n }\n\n // Retry with payment\n const retryResponse = await fetch(url, { ...init, headers })\n\n const receipt: PaymentReceipt = {\n success: retryResponse.status !== 402,\n network: paymentPayload.accepted.network,\n scheme: paymentPayload.accepted.scheme,\n amount: paymentPayload.accepted.amount,\n payTo: paymentPayload.accepted.payTo,\n }\n\n return { response: retryResponse, receipt }\n }\n\n /**\n * Extract payment requirements from a URL\n *\n * @param url - URL to check for payment requirements\n * @param init - Standard fetch RequestInit options\n * @returns The PaymentRequired object from the 402 response\n * @throws Error if the response is not 402\n */\n async getRequirements(url: string | URL, init?: RequestInit): Promise<PaymentRequired> {\n const response = await fetch(url, init)\n if (response.status !== 402) {\n throw new Error(`Expected 402 response, got ${response.status}`)\n }\n return extractPaymentRequired(response)\n }\n\n /**\n * Sign a payment for specific requirements using the t402 client infrastructure\n *\n * @param paymentRequired - The full PaymentRequired context\n * @returns A properly signed PaymentPayload (e.g., EIP-3009 for EVM)\n */\n async signPayment(paymentRequired: PaymentRequired): Promise<PaymentPayload> {\n return this.httpClient.createPaymentPayload(paymentRequired)\n }\n\n /**\n * Submit a request with a pre-signed payment payload\n *\n * @param url - URL to request\n * @param paymentPayload - The signed payment payload\n * @param init - Standard fetch RequestInit options\n * @returns The HTTP response\n */\n async submitPayment(\n url: string | URL,\n paymentPayload: PaymentPayload,\n init?: RequestInit,\n ): Promise<Response> {\n const paymentHeaders = this.httpClient.encodePaymentSignatureHeader(paymentPayload)\n const headers = new Headers(init?.headers)\n for (const [key, value] of Object.entries(paymentHeaders)) {\n headers.set(key, value)\n }\n\n return fetch(url, { ...init, headers })\n }\n\n /**\n * Get the underlying t402 HTTP client for advanced usage\n */\n getHttpClient(): t402HTTPClient {\n return this.httpClient\n }\n\n /**\n * Get the underlying WDK instance\n */\n getWdk(): T402WDK {\n return this.wdk\n }\n\n /**\n * Get the facilitator URL\n */\n getFacilitator(): string {\n return this.facilitator\n }\n\n /**\n * Get the configured chains\n */\n getChains(): string[] {\n return [...this.chains]\n }\n}\n","/**\n * HTTP client utilities for 402 payment handling\n */\n\nimport { decodePaymentRequiredHeader } from '@t402/core/http'\nimport type { PaymentRequired } from '@t402/core/types'\n\n/** V2 header names */\nconst HEADER_PAYMENT_REQUIRED = 'payment-required'\n\n/** V1 header names (fallback) */\nconst HEADER_X_PAYMENT = 'x-payment'\n\n/**\n * Extract PaymentRequired from a 402 response.\n * Tries V2 header first, then falls back to V1.\n *\n * @param response - The HTTP response with status 402\n * @returns The parsed PaymentRequired object\n * @throws Error if no valid payment header is found\n */\nexport function extractPaymentRequired(response: Response): PaymentRequired {\n // Try V2 header\n const v2Header = response.headers.get(HEADER_PAYMENT_REQUIRED)\n if (v2Header) {\n return decodePaymentRequiredHeader(v2Header)\n }\n\n // Try V1 header\n const v1Header = response.headers.get(HEADER_X_PAYMENT)\n if (v1Header) {\n return decodePaymentRequiredHeader(v1Header)\n }\n\n throw new Error(\n 'No payment requirements found in 402 response. ' +\n `Expected \"${HEADER_PAYMENT_REQUIRED}\" or \"${HEADER_X_PAYMENT}\" header.`,\n )\n}\n","/**\n * Chain detection utilities for CAIP-2 network identifiers\n */\n\n/**\n * CAIP-2 namespace prefixes\n */\nconst CAIP2_EVM = 'eip155:'\nconst CAIP2_TON = 'ton:'\nconst CAIP2_SOLANA = 'solana:'\nconst CAIP2_TRON = 'tron:'\nconst CAIP2_NEAR = 'near:'\nconst CAIP2_APTOS = 'aptos:'\nconst CAIP2_TEZOS = 'tezos:'\nconst CAIP2_POLKADOT = 'polkadot:'\nconst CAIP2_STACKS = 'stacks:'\nconst CAIP2_COSMOS = 'cosmos:'\n\n/**\n * Chain family detected from CAIP-2 network identifier\n */\nexport type ChainFamily =\n | 'evm'\n | 'ton'\n | 'solana'\n | 'tron'\n | 'near'\n | 'aptos'\n | 'tezos'\n | 'polkadot'\n | 'stacks'\n | 'cosmos'\n\n/**\n * Detect chain family from a CAIP-2 network identifier\n *\n * @param network - CAIP-2 network identifier (e.g., \"eip155:1\", \"ton:mainnet\")\n * @returns The chain family\n * @throws Error if network prefix is not recognized\n */\nexport function detectChainFamily(network: string): ChainFamily {\n if (network.startsWith(CAIP2_EVM)) return 'evm'\n if (network.startsWith(CAIP2_TON)) return 'ton'\n if (network.startsWith(CAIP2_SOLANA)) return 'solana'\n if (network.startsWith(CAIP2_TRON)) return 'tron'\n if (network.startsWith(CAIP2_NEAR)) return 'near'\n if (network.startsWith(CAIP2_APTOS)) return 'aptos'\n if (network.startsWith(CAIP2_TEZOS)) return 'tezos'\n if (network.startsWith(CAIP2_POLKADOT)) return 'polkadot'\n if (network.startsWith(CAIP2_STACKS)) return 'stacks'\n if (network.startsWith(CAIP2_COSMOS)) return 'cosmos'\n\n throw new Error(\n `Unsupported network: ${network}. Cannot detect chain family from CAIP-2 prefix.`,\n )\n}\n\n/**\n * Map of EVM chain names to CAIP-2 identifiers\n */\nexport const EVM_CHAIN_MAP: Record<string, string> = {\n ethereum: 'eip155:1',\n base: 'eip155:8453',\n arbitrum: 'eip155:42161',\n optimism: 'eip155:10',\n polygon: 'eip155:137',\n avalanche: 'eip155:43114',\n ink: 'eip155:57073',\n berachain: 'eip155:80094',\n unichain: 'eip155:130',\n}\n\n/**\n * Get EVM chain name from CAIP-2 network identifier\n *\n * @param network - CAIP-2 network (e.g., \"eip155:42161\")\n * @returns Chain name (e.g., \"arbitrum\") or undefined\n */\nexport function getEvmChainName(network: string): string | undefined {\n for (const [name, caip2] of Object.entries(EVM_CHAIN_MAP)) {\n if (caip2 === network) return name\n }\n return undefined\n}\n\n/**\n * Check if a network is an EVM chain\n *\n * @param network - CAIP-2 network identifier\n * @returns True if the network is an EVM chain\n */\nexport function isEvmNetwork(network: string): boolean {\n return network.startsWith(CAIP2_EVM)\n}\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@t402/wdk-protocol",
|
|
3
|
+
"version": "2.4.0",
|
|
4
|
+
"description": "T402 payment protocol for Tether WDK wallet apps",
|
|
5
|
+
"main": "./dist/cjs/index.js",
|
|
6
|
+
"module": "./dist/esm/index.mjs",
|
|
7
|
+
"types": "./dist/cjs/index.d.ts",
|
|
8
|
+
"keywords": [
|
|
9
|
+
"t402",
|
|
10
|
+
"wdk",
|
|
11
|
+
"tether",
|
|
12
|
+
"payment",
|
|
13
|
+
"402",
|
|
14
|
+
"http",
|
|
15
|
+
"wallet"
|
|
16
|
+
],
|
|
17
|
+
"license": "Apache-2.0",
|
|
18
|
+
"author": "T402 Team",
|
|
19
|
+
"repository": "https://github.com/t402-io/t402",
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"@t402/evm": "2.4.0",
|
|
22
|
+
"@t402/core": "2.4.0",
|
|
23
|
+
"@t402/wdk": "2.4.0"
|
|
24
|
+
},
|
|
25
|
+
"peerDependencies": {
|
|
26
|
+
"@tetherto/wdk": ">=1.0.0-beta.0",
|
|
27
|
+
"viem": "^2.0.0"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^25.2.2",
|
|
31
|
+
"prettier": "3.8.1",
|
|
32
|
+
"tsup": "^8.5.1",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"vite-tsconfig-paths": "^6.1.0",
|
|
35
|
+
"vitest": "^3.2.4"
|
|
36
|
+
},
|
|
37
|
+
"exports": {
|
|
38
|
+
".": {
|
|
39
|
+
"import": {
|
|
40
|
+
"types": "./dist/esm/index.d.mts",
|
|
41
|
+
"default": "./dist/esm/index.mjs"
|
|
42
|
+
},
|
|
43
|
+
"require": {
|
|
44
|
+
"types": "./dist/cjs/index.d.ts",
|
|
45
|
+
"default": "./dist/cjs/index.js"
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"files": [
|
|
50
|
+
"dist"
|
|
51
|
+
],
|
|
52
|
+
"scripts": {
|
|
53
|
+
"build": "tsup",
|
|
54
|
+
"test": "vitest run",
|
|
55
|
+
"test:watch": "vitest",
|
|
56
|
+
"format": "prettier -c .prettierrc --write \"**/*.{ts,js,cjs,json,md}\"",
|
|
57
|
+
"format:check": "prettier -c .prettierrc --check \"**/*.{ts,js,cjs,json,md}\"",
|
|
58
|
+
"lint": "eslint . --ext .ts --fix",
|
|
59
|
+
"lint:check": "eslint . --ext .ts"
|
|
60
|
+
}
|
|
61
|
+
}
|