@onchaindb/sdk 0.4.0 → 0.4.2
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/.DS_Store +0 -0
- package/.claude/settings.local.json +8 -0
- package/.gitignore +5 -0
- package/.idea/.gitignore +5 -0
- package/.idea/compiler.xml +6 -0
- package/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/.idea/jsLinters/eslint.xml +6 -0
- package/.idea/modules.xml +8 -0
- package/.idea/prettier.xml +7 -0
- package/.idea/sdk.iml +12 -0
- package/.idea/vcs.xml +6 -0
- package/.idea/workspace.xml +257 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +11 -3
- package/dist/client.js.map +1 -1
- package/dist/database.d.ts +0 -20
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +0 -40
- package/dist/database.js.map +1 -1
- package/dist/query-sdk/tests/setup.d.ts +16 -0
- package/dist/query-sdk/tests/setup.d.ts.map +1 -0
- package/dist/query-sdk/tests/setup.js +49 -0
- package/dist/query-sdk/tests/setup.js.map +1 -0
- package/examples/basic-usage.ts +136 -0
- package/examples/blob-upload-example.ts +140 -0
- package/examples/collection-schema-example.ts +304 -0
- package/examples/server-side-joins.ts +201 -0
- package/examples/tweet-self-joins-example.ts +352 -0
- package/package-lock.json +3823 -0
- package/package.json +1 -1
- package/skills.md +1096 -0
- package/src/.env +1 -0
- package/src/batch.d.ts +121 -0
- package/src/batch.js +205 -0
- package/src/batch.ts +257 -0
- package/src/client.ts +1856 -0
- package/src/database.d.ts +268 -0
- package/src/database.js +294 -0
- package/src/database.ts +695 -0
- package/src/index.d.ts +160 -0
- package/src/index.js +186 -0
- package/src/index.ts +253 -0
- package/src/query-sdk/ConditionBuilder.ts +103 -0
- package/src/query-sdk/FieldConditionBuilder.ts +2 -0
- package/src/query-sdk/NestedBuilders.ts +186 -0
- package/src/query-sdk/OnChainDB.ts +294 -0
- package/src/query-sdk/QueryBuilder.ts +1191 -0
- package/src/query-sdk/QueryResult.ts +375 -0
- package/src/query-sdk/README.md +866 -0
- package/src/query-sdk/SelectionBuilder.ts +94 -0
- package/src/query-sdk/adapters/HttpClientAdapter.ts +249 -0
- package/src/query-sdk/dist/ConditionBuilder.d.ts +22 -0
- package/src/query-sdk/dist/ConditionBuilder.js +90 -0
- package/src/query-sdk/dist/FieldConditionBuilder.d.ts +1 -0
- package/src/query-sdk/dist/FieldConditionBuilder.js +6 -0
- package/src/query-sdk/dist/NestedBuilders.d.ts +43 -0
- package/src/query-sdk/dist/NestedBuilders.js +144 -0
- package/src/query-sdk/dist/OnChainDB.d.ts +19 -0
- package/src/query-sdk/dist/OnChainDB.js +123 -0
- package/src/query-sdk/dist/QueryBuilder.d.ts +70 -0
- package/src/query-sdk/dist/QueryBuilder.js +295 -0
- package/src/query-sdk/dist/QueryResult.d.ts +52 -0
- package/src/query-sdk/dist/QueryResult.js +293 -0
- package/src/query-sdk/dist/SelectionBuilder.d.ts +20 -0
- package/src/query-sdk/dist/SelectionBuilder.js +80 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.d.ts +27 -0
- package/src/query-sdk/dist/adapters/HttpClientAdapter.js +170 -0
- package/src/query-sdk/dist/index.d.ts +36 -0
- package/src/query-sdk/dist/index.js +27 -0
- package/src/query-sdk/dist/operators.d.ts +56 -0
- package/src/query-sdk/dist/operators.js +289 -0
- package/src/query-sdk/dist/tests/setup.d.ts +15 -0
- package/src/query-sdk/dist/tests/setup.js +46 -0
- package/src/query-sdk/index.ts +59 -0
- package/src/query-sdk/jest.config.js +25 -0
- package/src/query-sdk/operators.ts +335 -0
- package/src/query-sdk/package.json +46 -0
- package/src/query-sdk/tests/FieldConditionBuilder.test.ts +84 -0
- package/src/query-sdk/tests/LogicalOperator.test.ts +85 -0
- package/src/query-sdk/tests/NestedBuilders.test.ts +321 -0
- package/src/query-sdk/tests/QueryBuilder.test.ts +348 -0
- package/src/query-sdk/tests/QueryResult.test.ts +464 -0
- package/src/query-sdk/tests/aggregations.test.ts +653 -0
- package/src/query-sdk/tests/comprehensive.test.ts +279 -0
- package/src/query-sdk/tests/integration.test.ts +608 -0
- package/src/query-sdk/tests/operators.test.ts +327 -0
- package/src/query-sdk/tests/setup.ts +59 -0
- package/src/query-sdk/tests/unit.test.ts +794 -0
- package/src/query-sdk/tsconfig.json +26 -0
- package/src/query-sdk/yarn.lock +3092 -0
- package/src/types.d.ts +131 -0
- package/src/types.js +46 -0
- package/src/types.ts +534 -0
- package/src/x402/index.ts +12 -0
- package/src/x402/types.ts +250 -0
- package/src/x402/utils.ts +332 -0
- package/tsconfig.json +20 -0
- package/yarn.lock +2309 -0
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 Protocol Module
|
|
3
|
+
*
|
|
4
|
+
* Exports types and utilities for x402 payment protocol support.
|
|
5
|
+
*
|
|
6
|
+
* Two payment flows are supported:
|
|
7
|
+
* 1. Celestia native: User broadcasts tx, sends txHash to server
|
|
8
|
+
* 2. Facilitator (EVM/Solana): User signs authorization, server sends to facilitator
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export * from './types';
|
|
12
|
+
export * from './utils';
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 Protocol Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions for the x402 payment protocol specification.
|
|
5
|
+
* See: https://github.com/coinbase/x402/blob/main/specs/x402-specification.md
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Payment scheme - currently only "exact" is supported per spec
|
|
10
|
+
*/
|
|
11
|
+
export type PaymentScheme = 'exact';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Chain type for payment processing
|
|
15
|
+
*/
|
|
16
|
+
export type ChainType = 'cosmos' | 'evm' | 'solana';
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Payment method
|
|
20
|
+
*/
|
|
21
|
+
export type PaymentMethod = 'native' | 'x402-facilitator';
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* x402 Payment requirement from server
|
|
25
|
+
*/
|
|
26
|
+
export interface X402PaymentRequirement {
|
|
27
|
+
/** Payment scheme - must be "exact" */
|
|
28
|
+
scheme: PaymentScheme;
|
|
29
|
+
/** Network identifier (e.g., "mocha-4", "base", "solana") */
|
|
30
|
+
network: string;
|
|
31
|
+
/** Maximum amount required in smallest units as string */
|
|
32
|
+
maxAmountRequired: string;
|
|
33
|
+
/** Recipient address */
|
|
34
|
+
payTo: string;
|
|
35
|
+
/** Asset identifier (e.g., "utia", USDC address) */
|
|
36
|
+
asset: string;
|
|
37
|
+
/** Resource URL being accessed */
|
|
38
|
+
resource: string;
|
|
39
|
+
/** Human-readable description */
|
|
40
|
+
description: string;
|
|
41
|
+
/** Content type of the resource */
|
|
42
|
+
mimeType: string;
|
|
43
|
+
/** Maximum timeout for payment in seconds */
|
|
44
|
+
maxTimeoutSeconds: number;
|
|
45
|
+
/** Extra extension data */
|
|
46
|
+
extra?: X402Extra;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* x402 Extra field with OnChainDB extensions
|
|
51
|
+
*/
|
|
52
|
+
export interface X402Extra {
|
|
53
|
+
/** Extension identifier */
|
|
54
|
+
x402Extension?: string;
|
|
55
|
+
/** Quote ID for this payment */
|
|
56
|
+
quoteId?: string;
|
|
57
|
+
/** Chain type (cosmos, evm, solana) */
|
|
58
|
+
chainType?: ChainType;
|
|
59
|
+
/** Chain ID for EVM chains */
|
|
60
|
+
chainId?: number;
|
|
61
|
+
/** Payment method */
|
|
62
|
+
paymentMethod?: PaymentMethod;
|
|
63
|
+
/** x402 facilitator URL */
|
|
64
|
+
facilitator?: string;
|
|
65
|
+
/** Token symbol */
|
|
66
|
+
tokenSymbol?: string;
|
|
67
|
+
/** Token decimals */
|
|
68
|
+
tokenDecimals?: number;
|
|
69
|
+
/** Cost breakdown */
|
|
70
|
+
costBreakdown?: Record<string, number>;
|
|
71
|
+
/** Pricing information */
|
|
72
|
+
pricing?: {
|
|
73
|
+
baseAmount: string;
|
|
74
|
+
baseAsset: string;
|
|
75
|
+
premiumPercent?: number;
|
|
76
|
+
expiresAt?: number;
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* x402 Payment Required Response (402 status)
|
|
82
|
+
*/
|
|
83
|
+
export interface X402PaymentRequiredResponse {
|
|
84
|
+
/** Protocol version - must be 1 */
|
|
85
|
+
x402Version: 1;
|
|
86
|
+
/** Error message explaining why payment is required */
|
|
87
|
+
error: string;
|
|
88
|
+
/** Array of accepted payment options */
|
|
89
|
+
accepts: X402PaymentRequirement[];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* x402 Payment Payload sent in X-PAYMENT header
|
|
94
|
+
*/
|
|
95
|
+
export interface X402PaymentPayload {
|
|
96
|
+
/** Protocol version */
|
|
97
|
+
x402Version: 1;
|
|
98
|
+
/** Payment scheme */
|
|
99
|
+
scheme: PaymentScheme;
|
|
100
|
+
/** Network used for payment */
|
|
101
|
+
network: string;
|
|
102
|
+
/** Quote ID from server */
|
|
103
|
+
quoteId: string;
|
|
104
|
+
/** Payment-specific payload */
|
|
105
|
+
payload: X402NativePayload | X402EvmPayload | X402SolanaPayload;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Native Celestia payment payload
|
|
110
|
+
*/
|
|
111
|
+
export interface X402NativePayload {
|
|
112
|
+
/** Transaction hash */
|
|
113
|
+
txHash: string;
|
|
114
|
+
/** Sender address */
|
|
115
|
+
sender: string;
|
|
116
|
+
/** Payment timestamp */
|
|
117
|
+
timestamp: number;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* EVM payment payload (for x402 facilitator)
|
|
122
|
+
*/
|
|
123
|
+
export interface X402EvmPayload {
|
|
124
|
+
/** EIP-712 signature */
|
|
125
|
+
signature: string;
|
|
126
|
+
/** ERC-3009 authorization */
|
|
127
|
+
authorization: {
|
|
128
|
+
from: string;
|
|
129
|
+
to: string;
|
|
130
|
+
value: string;
|
|
131
|
+
validAfter: number;
|
|
132
|
+
validBefore: number;
|
|
133
|
+
nonce: string;
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* Solana payment payload (for x402 facilitator)
|
|
139
|
+
*/
|
|
140
|
+
export interface X402SolanaPayload {
|
|
141
|
+
/** Signed transaction (base64) */
|
|
142
|
+
transaction: string;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* x402 Payment Response header value
|
|
147
|
+
*/
|
|
148
|
+
export interface X402PaymentResponse {
|
|
149
|
+
/** Transaction hash */
|
|
150
|
+
txHash: string;
|
|
151
|
+
/** Network where payment was made */
|
|
152
|
+
network: string;
|
|
153
|
+
/** Block height of confirmation */
|
|
154
|
+
blockHeight: number;
|
|
155
|
+
/** Amount paid */
|
|
156
|
+
amount: string;
|
|
157
|
+
/** Confirmation timestamp */
|
|
158
|
+
confirmedAt: number;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Quote format for payment callback
|
|
163
|
+
*/
|
|
164
|
+
export interface X402Quote {
|
|
165
|
+
/** Quote ID */
|
|
166
|
+
quoteId: string;
|
|
167
|
+
/** Total cost in TIA */
|
|
168
|
+
totalCostTia: number;
|
|
169
|
+
/** Amount in smallest units */
|
|
170
|
+
amountRaw: string;
|
|
171
|
+
/** Broker/recipient address */
|
|
172
|
+
brokerAddress: string;
|
|
173
|
+
/** Payment description */
|
|
174
|
+
description: string;
|
|
175
|
+
/** Quote expiration timestamp */
|
|
176
|
+
expiresAt: number;
|
|
177
|
+
/** Chain type */
|
|
178
|
+
chainType: ChainType;
|
|
179
|
+
/** Network name */
|
|
180
|
+
network: string;
|
|
181
|
+
/** Asset address/identifier */
|
|
182
|
+
asset: string;
|
|
183
|
+
/** Token symbol */
|
|
184
|
+
tokenSymbol: string;
|
|
185
|
+
/** Token decimals */
|
|
186
|
+
tokenDecimals: number;
|
|
187
|
+
/** Payment method */
|
|
188
|
+
paymentMethod: PaymentMethod;
|
|
189
|
+
/** Facilitator URL (if applicable) */
|
|
190
|
+
facilitator?: string;
|
|
191
|
+
/** All available payment options */
|
|
192
|
+
allOptions: X402PaymentRequirement[];
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Payment result from callback - supports both native and facilitator flows
|
|
197
|
+
*/
|
|
198
|
+
export interface X402PaymentResult {
|
|
199
|
+
/** Transaction hash (required for Celestia native, optional for facilitator) */
|
|
200
|
+
txHash: string;
|
|
201
|
+
/** Network used */
|
|
202
|
+
network: string;
|
|
203
|
+
/** Sender address */
|
|
204
|
+
sender: string;
|
|
205
|
+
/** Chain type */
|
|
206
|
+
chainType: ChainType;
|
|
207
|
+
/** Payment method used */
|
|
208
|
+
paymentMethod: PaymentMethod;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Facilitator payment result - used for EVM/Solana payments via x402 facilitator
|
|
213
|
+
* User provides authorization, facilitator executes the payment
|
|
214
|
+
*/
|
|
215
|
+
export interface X402FacilitatorPaymentResult {
|
|
216
|
+
/** Network used */
|
|
217
|
+
network: string;
|
|
218
|
+
/** Chain type */
|
|
219
|
+
chainType: 'evm' | 'solana';
|
|
220
|
+
/** Payment method - always x402-facilitator */
|
|
221
|
+
paymentMethod: 'x402-facilitator';
|
|
222
|
+
/** EVM authorization (for EVM chains) */
|
|
223
|
+
evmAuthorization?: {
|
|
224
|
+
signature: string;
|
|
225
|
+
authorization: {
|
|
226
|
+
from: string;
|
|
227
|
+
to: string;
|
|
228
|
+
value: string;
|
|
229
|
+
validAfter: number;
|
|
230
|
+
validBefore: number;
|
|
231
|
+
nonce: string;
|
|
232
|
+
};
|
|
233
|
+
};
|
|
234
|
+
/** Solana authorization (for Solana) */
|
|
235
|
+
solanaAuthorization?: {
|
|
236
|
+
transaction: string;
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Union type for all payment callback results
|
|
242
|
+
*/
|
|
243
|
+
export type X402PaymentCallbackResult = X402PaymentResult | X402FacilitatorPaymentResult;
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Type guard to check if result is a facilitator payment
|
|
247
|
+
*/
|
|
248
|
+
export function isFacilitatorPaymentResult(result: X402PaymentCallbackResult): result is X402FacilitatorPaymentResult {
|
|
249
|
+
return result.paymentMethod === 'x402-facilitator' && !('txHash' in result && result.txHash);
|
|
250
|
+
}
|
|
@@ -0,0 +1,332 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* x402 Protocol Utilities
|
|
3
|
+
*
|
|
4
|
+
* Helper functions for parsing and building x402 protocol messages.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
X402PaymentRequiredResponse,
|
|
9
|
+
X402PaymentRequirement,
|
|
10
|
+
X402Quote,
|
|
11
|
+
X402PaymentPayload,
|
|
12
|
+
X402PaymentResult,
|
|
13
|
+
ChainType,
|
|
14
|
+
PaymentMethod,
|
|
15
|
+
} from './types';
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Parse a 402 response into typed x402 format
|
|
19
|
+
*/
|
|
20
|
+
export function parseX402Response(data: any): X402PaymentRequiredResponse {
|
|
21
|
+
if (!data || typeof data !== 'object') {
|
|
22
|
+
throw new Error('Invalid x402 response: not an object');
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (data.x402Version !== 1) {
|
|
26
|
+
throw new Error(`Unsupported x402 version: ${data.x402Version}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!Array.isArray(data.accepts) || data.accepts.length === 0) {
|
|
30
|
+
throw new Error('Invalid x402 response: no payment options');
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
return {
|
|
34
|
+
x402Version: 1,
|
|
35
|
+
error: data.error || 'Payment required',
|
|
36
|
+
accepts: data.accepts.map(parsePaymentRequirement),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse a single payment requirement
|
|
42
|
+
*/
|
|
43
|
+
function parsePaymentRequirement(req: any): X402PaymentRequirement {
|
|
44
|
+
if (req.scheme !== 'exact') {
|
|
45
|
+
console.warn(`Non-standard scheme "${req.scheme}", treating as exact`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
scheme: 'exact',
|
|
50
|
+
network: req.network,
|
|
51
|
+
maxAmountRequired: req.maxAmountRequired,
|
|
52
|
+
payTo: req.payTo,
|
|
53
|
+
asset: req.asset,
|
|
54
|
+
resource: req.resource,
|
|
55
|
+
description: req.description,
|
|
56
|
+
mimeType: req.mimeType || 'application/json',
|
|
57
|
+
maxTimeoutSeconds: req.maxTimeoutSeconds || 300,
|
|
58
|
+
extra: req.extra,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Convert x402 payment requirement to quote format for callbacks
|
|
64
|
+
*/
|
|
65
|
+
export function requirementToQuote(
|
|
66
|
+
requirement: X402PaymentRequirement,
|
|
67
|
+
allOptions: X402PaymentRequirement[]
|
|
68
|
+
): X402Quote {
|
|
69
|
+
const extra = requirement.extra || {};
|
|
70
|
+
const amountRaw = requirement.maxAmountRequired;
|
|
71
|
+
|
|
72
|
+
// Determine chain type from extra or network
|
|
73
|
+
let chainType: ChainType = 'cosmos';
|
|
74
|
+
if (extra.chainType) {
|
|
75
|
+
chainType = extra.chainType;
|
|
76
|
+
} else if (isEvmNetwork(requirement.network)) {
|
|
77
|
+
chainType = 'evm';
|
|
78
|
+
} else if (isSolanaNetwork(requirement.network)) {
|
|
79
|
+
chainType = 'solana';
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Calculate TIA amount (for display purposes)
|
|
83
|
+
const decimals = extra.tokenDecimals || 6;
|
|
84
|
+
const totalCostTia = parseInt(amountRaw) / Math.pow(10, decimals);
|
|
85
|
+
|
|
86
|
+
// Calculate expiration
|
|
87
|
+
const expiresAt = extra.pricing?.expiresAt ||
|
|
88
|
+
Math.floor(Date.now() / 1000) + requirement.maxTimeoutSeconds;
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
quoteId: extra.quoteId || '',
|
|
92
|
+
totalCostTia,
|
|
93
|
+
amountRaw,
|
|
94
|
+
brokerAddress: requirement.payTo,
|
|
95
|
+
description: requirement.description,
|
|
96
|
+
expiresAt,
|
|
97
|
+
chainType,
|
|
98
|
+
network: requirement.network,
|
|
99
|
+
asset: requirement.asset,
|
|
100
|
+
tokenSymbol: extra.tokenSymbol || getTokenSymbol(requirement.asset),
|
|
101
|
+
tokenDecimals: decimals,
|
|
102
|
+
paymentMethod: (extra.paymentMethod || 'native') as PaymentMethod,
|
|
103
|
+
facilitator: extra.facilitator,
|
|
104
|
+
allOptions,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Build X-PAYMENT header payload for Celestia native payments
|
|
110
|
+
* For EVM/Solana facilitator payments, use buildFacilitatorPaymentPayload instead
|
|
111
|
+
*/
|
|
112
|
+
export function buildPaymentPayload(
|
|
113
|
+
requirement: X402PaymentRequirement,
|
|
114
|
+
payment: X402PaymentResult
|
|
115
|
+
): X402PaymentPayload {
|
|
116
|
+
const extra = requirement.extra || {};
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
x402Version: 1,
|
|
120
|
+
scheme: 'exact',
|
|
121
|
+
network: payment.network,
|
|
122
|
+
quoteId: extra.quoteId || '',
|
|
123
|
+
payload: {
|
|
124
|
+
txHash: payment.txHash.toLowerCase(),
|
|
125
|
+
sender: payment.sender,
|
|
126
|
+
timestamp: Math.floor(Date.now() / 1000),
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Build X-PAYMENT header payload for facilitator networks (EVM/Solana)
|
|
133
|
+
* These payments don't have a txHash upfront - the facilitator executes the payment
|
|
134
|
+
*/
|
|
135
|
+
export function buildFacilitatorPaymentPayload(
|
|
136
|
+
requirement: X402PaymentRequirement,
|
|
137
|
+
authorization: FacilitatorAuthorization
|
|
138
|
+
): X402PaymentPayload {
|
|
139
|
+
const extra = requirement.extra || {};
|
|
140
|
+
|
|
141
|
+
if (authorization.type === 'evm') {
|
|
142
|
+
return {
|
|
143
|
+
x402Version: 1,
|
|
144
|
+
scheme: 'exact',
|
|
145
|
+
network: requirement.network,
|
|
146
|
+
quoteId: extra.quoteId || '',
|
|
147
|
+
payload: {
|
|
148
|
+
signature: authorization.signature,
|
|
149
|
+
authorization: authorization.authorization,
|
|
150
|
+
} as any,
|
|
151
|
+
};
|
|
152
|
+
} else if (authorization.type === 'solana') {
|
|
153
|
+
return {
|
|
154
|
+
x402Version: 1,
|
|
155
|
+
scheme: 'exact',
|
|
156
|
+
network: requirement.network,
|
|
157
|
+
quoteId: extra.quoteId || '',
|
|
158
|
+
payload: {
|
|
159
|
+
transaction: authorization.transaction,
|
|
160
|
+
} as any,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
throw new Error(`Unsupported facilitator authorization type: ${(authorization as any).type}`);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* EVM authorization for facilitator (ERC-3009 / EIP-712)
|
|
169
|
+
*/
|
|
170
|
+
export interface EvmFacilitatorAuthorization {
|
|
171
|
+
type: 'evm';
|
|
172
|
+
/** EIP-712 signature */
|
|
173
|
+
signature: string;
|
|
174
|
+
/** ERC-3009 authorization details */
|
|
175
|
+
authorization: {
|
|
176
|
+
from: string;
|
|
177
|
+
to: string;
|
|
178
|
+
value: string;
|
|
179
|
+
validAfter: number;
|
|
180
|
+
validBefore: number;
|
|
181
|
+
nonce: string;
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Solana authorization for facilitator
|
|
187
|
+
*/
|
|
188
|
+
export interface SolanaFacilitatorAuthorization {
|
|
189
|
+
type: 'solana';
|
|
190
|
+
/** Signed transaction (base64) */
|
|
191
|
+
transaction: string;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
export type FacilitatorAuthorization = EvmFacilitatorAuthorization | SolanaFacilitatorAuthorization;
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Check if a network requires the x402 facilitator
|
|
198
|
+
*/
|
|
199
|
+
export function isFacilitatorNetwork(network: string): boolean {
|
|
200
|
+
return isEvmNetwork(network) || isSolanaNetwork(network);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Encode payment payload to base64 for X-PAYMENT header
|
|
205
|
+
*/
|
|
206
|
+
export function encodePaymentHeader(payload: X402PaymentPayload): string {
|
|
207
|
+
const json = JSON.stringify(payload);
|
|
208
|
+
if (typeof Buffer !== 'undefined') {
|
|
209
|
+
return Buffer.from(json).toString('base64');
|
|
210
|
+
} else {
|
|
211
|
+
return btoa(json);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Decode X-PAYMENT-RESPONSE header
|
|
217
|
+
*/
|
|
218
|
+
export function decodePaymentResponse(header: string): any {
|
|
219
|
+
try {
|
|
220
|
+
if (typeof Buffer !== 'undefined') {
|
|
221
|
+
return JSON.parse(Buffer.from(header, 'base64').toString());
|
|
222
|
+
} else {
|
|
223
|
+
return JSON.parse(atob(header));
|
|
224
|
+
}
|
|
225
|
+
} catch {
|
|
226
|
+
// Try parsing as direct JSON (some servers don't base64 encode)
|
|
227
|
+
return JSON.parse(header);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Check if network is EVM-based
|
|
233
|
+
*/
|
|
234
|
+
function isEvmNetwork(network: string): boolean {
|
|
235
|
+
const evmNetworks = [
|
|
236
|
+
'ethereum', 'ethereum-sepolia',
|
|
237
|
+
'base', 'base-sepolia',
|
|
238
|
+
'polygon', 'polygon-amoy',
|
|
239
|
+
'arbitrum', 'arbitrum-sepolia',
|
|
240
|
+
'avalanche', 'avalanche-fuji',
|
|
241
|
+
];
|
|
242
|
+
return evmNetworks.includes(network.toLowerCase());
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/**
|
|
246
|
+
* Check if network is Solana-based
|
|
247
|
+
*/
|
|
248
|
+
function isSolanaNetwork(network: string): boolean {
|
|
249
|
+
return network.toLowerCase() === 'solana' || network.toLowerCase() === 'solana-devnet';
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
/**
|
|
253
|
+
* Get token symbol from asset address
|
|
254
|
+
*/
|
|
255
|
+
function getTokenSymbol(asset: string): string {
|
|
256
|
+
// Common asset mappings
|
|
257
|
+
const assetSymbols: Record<string, string> = {
|
|
258
|
+
'utia': 'TIA',
|
|
259
|
+
'native': 'ETH',
|
|
260
|
+
// USDC addresses on various chains
|
|
261
|
+
'0x833589fcd6edb6e08f4c7c32d4f71b54bda02913': 'USDC', // Base
|
|
262
|
+
'0x036cbd53842c5426634e7929541ec2318f3dcf7e': 'USDC', // Base Sepolia
|
|
263
|
+
'0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48': 'USDC', // Ethereum
|
|
264
|
+
'epjfwdd5aufqssqem2qn1xzybapC8g4weggkzwyTdt1v': 'USDC', // Solana
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
const normalized = asset.toLowerCase();
|
|
268
|
+
return assetSymbols[normalized] || 'TOKEN';
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/**
|
|
272
|
+
* Select best payment option based on user preference
|
|
273
|
+
*/
|
|
274
|
+
export function selectPaymentOption(
|
|
275
|
+
options: X402PaymentRequirement[],
|
|
276
|
+
preferredChainType?: ChainType,
|
|
277
|
+
preferredNetwork?: string
|
|
278
|
+
): X402PaymentRequirement {
|
|
279
|
+
// If specific network requested, find it
|
|
280
|
+
if (preferredNetwork) {
|
|
281
|
+
const match = options.find(o =>
|
|
282
|
+
o.network.toLowerCase() === preferredNetwork.toLowerCase()
|
|
283
|
+
);
|
|
284
|
+
if (match) return match;
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// If chain type requested, find first match
|
|
288
|
+
if (preferredChainType) {
|
|
289
|
+
const match = options.find(o => {
|
|
290
|
+
const extra = o.extra || {};
|
|
291
|
+
if (extra.chainType === preferredChainType) return true;
|
|
292
|
+
if (preferredChainType === 'evm' && isEvmNetwork(o.network)) return true;
|
|
293
|
+
if (preferredChainType === 'solana' && isSolanaNetwork(o.network)) return true;
|
|
294
|
+
if (preferredChainType === 'cosmos' && o.asset === 'utia') return true;
|
|
295
|
+
return false;
|
|
296
|
+
});
|
|
297
|
+
if (match) return match;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Default to first option (typically native TIA)
|
|
301
|
+
return options[0];
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
/**
|
|
305
|
+
* Group payment options by chain type
|
|
306
|
+
*/
|
|
307
|
+
export function groupPaymentOptions(
|
|
308
|
+
options: X402PaymentRequirement[]
|
|
309
|
+
): Record<ChainType, X402PaymentRequirement[]> {
|
|
310
|
+
const groups: Record<ChainType, X402PaymentRequirement[]> = {
|
|
311
|
+
cosmos: [],
|
|
312
|
+
evm: [],
|
|
313
|
+
solana: [],
|
|
314
|
+
};
|
|
315
|
+
|
|
316
|
+
for (const option of options) {
|
|
317
|
+
const extra = option.extra || {};
|
|
318
|
+
let chainType: ChainType = 'cosmos';
|
|
319
|
+
|
|
320
|
+
if (extra.chainType) {
|
|
321
|
+
chainType = extra.chainType;
|
|
322
|
+
} else if (isEvmNetwork(option.network)) {
|
|
323
|
+
chainType = 'evm';
|
|
324
|
+
} else if (isSolanaNetwork(option.network)) {
|
|
325
|
+
chainType = 'solana';
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
groups[chainType].push(option);
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return groups;
|
|
332
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": ["ES2020"],
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"declaration": true,
|
|
13
|
+
"declarationMap": true,
|
|
14
|
+
"sourceMap": true,
|
|
15
|
+
"removeComments": true,
|
|
16
|
+
"resolveJsonModule": true
|
|
17
|
+
},
|
|
18
|
+
"include": ["src/**/*"],
|
|
19
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
|
20
|
+
}
|