@rozoai/intent-common 0.0.31 → 0.0.32-beta.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.
@@ -0,0 +1,433 @@
1
+ import { createPaymentBridgeConfig } from "../bridge";
2
+ import { getChainById } from "../chain";
3
+ import { getKnownToken } from "../token";
4
+ import { apiClient, ApiResponse } from "./base";
5
+
6
+ /**
7
+ * FeeType, Fee calculation type:
8
+ * - exactIn (default): Fee deducted from input, recipient receives amount - fee
9
+ * - exactOut: Fee added to input, recipient receives exact amount
10
+ */
11
+ export enum FeeType {
12
+ ExactIn = "exactIn",
13
+ ExactOut = "exactOut",
14
+ }
15
+
16
+ /**
17
+ * PaymentStatus, Payment status
18
+ */
19
+ export enum PaymentStatus {
20
+ PaymentBounced = "payment_bounced",
21
+ PaymentCompleted = "payment_completed",
22
+ PaymentExpired = "payment_expired",
23
+ PaymentPayinCompleted = "payment_payin_completed",
24
+ PaymentPayoutCompleted = "payment_payout_completed",
25
+ PaymentRefunded = "payment_refunded",
26
+ PaymentStarted = "payment_started",
27
+ PaymentUnpaid = "payment_unpaid",
28
+ }
29
+
30
+ /**
31
+ * PaymentErrorCode, Error code (only present when status is payment_bounced)
32
+ */
33
+ export enum PaymentErrorCode {
34
+ AmountTooHigh = "amountTooHigh",
35
+ AmountTooLow = "amountTooLow",
36
+ ChainUnavailable = "chainUnavailable",
37
+ InsufficientLiquidity = "insufficientLiquidity",
38
+ InvalidRecipient = "invalidRecipient",
39
+ MissingTrustline = "missingTrustline",
40
+ NetworkError = "networkError",
41
+ ProviderError = "providerError",
42
+ ServiceMaintenance = "serviceMaintenance",
43
+ }
44
+
45
+ /**
46
+ * DestinationRequest
47
+ */
48
+ export interface DestinationRequest {
49
+ /**
50
+ * Receive amount (required for type=exactOut).
51
+ * For exactIn, this field is omitted in request and calculated in response.
52
+ */
53
+ amount?: string;
54
+ chainId: number;
55
+ /**
56
+ * Final recipient's wallet address
57
+ */
58
+ receiverAddress: string;
59
+ /**
60
+ * Memo for Stellar/Solana destinations
61
+ */
62
+ receiverMemo?: string;
63
+ /**
64
+ * Override default token address
65
+ */
66
+ tokenAddress?: string;
67
+ tokenSymbol: string;
68
+ [property: string]: any;
69
+ }
70
+
71
+ /**
72
+ * DisplayInfo
73
+ */
74
+ export interface DisplayInfo {
75
+ /**
76
+ * Display currency
77
+ */
78
+ currency: string;
79
+ /**
80
+ * Detailed description
81
+ */
82
+ description?: string;
83
+ /**
84
+ * Short title
85
+ */
86
+ title: string;
87
+ [property: string]: any;
88
+ }
89
+
90
+ /**
91
+ * SourceRequest
92
+ */
93
+ export interface SourceRequest {
94
+ /**
95
+ * Pay-in amount (required for type=exactIn).
96
+ * For exactOut, this field is omitted in request and calculated in response.
97
+ */
98
+ amount?: string;
99
+ chainId: number;
100
+ /**
101
+ * Override default token address
102
+ */
103
+ tokenAddress?: string;
104
+ tokenSymbol: string;
105
+ [property: string]: any;
106
+ }
107
+
108
+ /**
109
+ * PaymentRequest
110
+ */
111
+ export interface CreatePaymentRequest {
112
+ /**
113
+ * Your application ID
114
+ */
115
+ appId: string;
116
+ destination: DestinationRequest;
117
+ display: DisplayInfo;
118
+ /**
119
+ * Custom metadata (max 4 KB recommended)
120
+ */
121
+ metadata?: { [key: string]: any };
122
+ /**
123
+ * Your order reference ID (for idempotency)
124
+ */
125
+ orderId?: string;
126
+ source: SourceRequest;
127
+ type?: FeeType;
128
+ /**
129
+ * Secret for HMAC-SHA256 signature verification.
130
+ * If not provided, a unique secret is auto-generated.
131
+ * The secret is returned in the response for you to store and use for verification.
132
+ */
133
+ webhookSecret?: string;
134
+ /**
135
+ * URL to receive payment status updates
136
+ */
137
+ webhookUrl?: string;
138
+ [property: string]: any;
139
+ }
140
+
141
+ /**
142
+ * DestinationResponse
143
+ */
144
+ export interface DestinationResponse {
145
+ /**
146
+ * Amount to be sent to recipient
147
+ */
148
+ amount?: string;
149
+ chainId?: number;
150
+ /**
151
+ * Withdrawal confirmation time
152
+ */
153
+ confirmedAt?: Date;
154
+ /**
155
+ * Final recipient's wallet
156
+ */
157
+ receiverAddress?: string;
158
+ /**
159
+ * Memo for Stellar/Solana
160
+ */
161
+ receiverMemo?: string;
162
+ /**
163
+ * Token contract address
164
+ */
165
+ tokenAddress?: string;
166
+ tokenSymbol?: string;
167
+ /**
168
+ * Withdrawal transaction hash
169
+ */
170
+ txHash?: string;
171
+ [property: string]: any;
172
+ }
173
+
174
+ /**
175
+ * SourceResponse
176
+ */
177
+ export interface SourceResponse {
178
+ /**
179
+ * Amount payer must send
180
+ */
181
+ amount?: string;
182
+ /**
183
+ * Actual amount received
184
+ */
185
+ amountReceived?: string;
186
+ chainId?: number;
187
+ /**
188
+ * Deposit confirmation time
189
+ */
190
+ confirmedAt?: Date;
191
+ /**
192
+ * Fee amount
193
+ */
194
+ fee?: string;
195
+ /**
196
+ * Deposit address (where payer sends funds)
197
+ */
198
+ receiverAddress?: string;
199
+ /**
200
+ * Memo for Stellar/Solana deposits
201
+ */
202
+ receiverMemo?: string;
203
+ /**
204
+ * Payer's wallet address (populated after deposit)
205
+ */
206
+ senderAddress?: string;
207
+ /**
208
+ * Token contract address
209
+ */
210
+ tokenAddress?: string;
211
+ tokenSymbol?: string;
212
+ /**
213
+ * Deposit transaction hash
214
+ */
215
+ txHash?: string;
216
+ [property: string]: any;
217
+ }
218
+
219
+ /**
220
+ * PaymentResponse
221
+ */
222
+ export interface PaymentResponse {
223
+ /**
224
+ * Your application ID
225
+ */
226
+ appId?: string;
227
+ /**
228
+ * ISO 8601 timestamp
229
+ */
230
+ createdAt?: Date;
231
+ destination?: DestinationResponse;
232
+ display?: DisplayInfo;
233
+ errorCode?: PaymentErrorCode;
234
+ /**
235
+ * ISO 8601 timestamp (when payment expires)
236
+ */
237
+ expiresAt?: Date;
238
+ /**
239
+ * Payment ID
240
+ */
241
+ id?: string;
242
+ metadata?: { [key: string]: any };
243
+ /**
244
+ * Your order reference ID
245
+ */
246
+ orderId?: string;
247
+ source?: SourceResponse;
248
+ status?: PaymentStatus;
249
+ type?: FeeType;
250
+ /**
251
+ * ISO 8601 timestamp
252
+ */
253
+ updatedAt?: Date;
254
+ /**
255
+ * Secret for webhook signature verification.
256
+ * Only present when webhookUrl was provided in the request.
257
+ * Store this securely to verify incoming webhook signatures.
258
+ */
259
+ webhookSecret?: string;
260
+ [property: string]: any;
261
+ }
262
+
263
+ /**
264
+ * Parameters for creating a new payment using the new backend interface
265
+ */
266
+ export interface CreateNewPaymentParams {
267
+ /** App ID for authentication */
268
+ appId: string;
269
+ // Destination (where funds will be received)
270
+ /** Destination chain ID (e.g., 8453 for Base, 900 for Solana, 1500 for Stellar) */
271
+ toChain: number;
272
+ /** Destination token address */
273
+ toToken: string;
274
+ /** Destination address - Can be EVM, Solana, or Stellar address */
275
+ toAddress: string;
276
+
277
+ // Preferred payment method (what user will pay with)
278
+ /** Chain ID where user will pay from (e.g., 137 for Polygon, 8453 for Base) */
279
+ preferredChain: number;
280
+ /** Token address user will pay with */
281
+ preferredTokenAddress: string;
282
+
283
+ // Payment details
284
+ /** Amount in human-readable units (e.g., "1" for 1 USDC, "0.5" for half a USDC) */
285
+ toUnits?: string;
286
+
287
+ // Optional fields
288
+ /** Additional metadata to include */
289
+ metadata?: Record<string, unknown>;
290
+ /** Display title for the payment */
291
+ title?: string;
292
+ /** Display description for the payment */
293
+ description?: string;
294
+ /** Order reference ID (for idempotency) */
295
+ orderId?: string;
296
+ /** Fee calculation type (exactIn or exactOut) */
297
+ type?: FeeType;
298
+ /** Webhook URL to receive payment status updates */
299
+ webhookUrl?: string;
300
+ /** Secret for HMAC-SHA256 signature verification */
301
+ webhookSecret?: string;
302
+ /** Memo for Stellar/Solana destinations */
303
+ receiverMemo?: string;
304
+ }
305
+
306
+ /**
307
+ * Creates a payment using the new backend interface
308
+ *
309
+ * This function creates a payment using the new backend API structure with
310
+ * separate source and destination objects, enum-based chain IDs and token symbols.
311
+ *
312
+ * @param params - Payment creation parameters
313
+ * @returns Promise resolving to the payment response data
314
+ * @throws Error if payment creation fails or required parameters are missing
315
+ *
316
+ * @example
317
+ * ```typescript
318
+ * // Simple same-chain payment
319
+ * const payment = await createNewPayment({
320
+ * toChain: 8453, // Base
321
+ * toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
322
+ * toAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
323
+ * preferredChain: 8453, // User pays from Base
324
+ * preferredTokenAddress: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
325
+ * toUnits: "1", // 1 USDC
326
+ * appId: "my-app-id",
327
+ * title: "Payment",
328
+ * });
329
+ * ```
330
+ */
331
+ export async function createNewPayment(
332
+ params: CreateNewPaymentParams
333
+ ): Promise<PaymentResponse> {
334
+ const {
335
+ toChain,
336
+ toToken,
337
+ toAddress,
338
+ preferredChain,
339
+ preferredTokenAddress,
340
+ toUnits,
341
+ appId,
342
+ metadata,
343
+ title,
344
+ description,
345
+ orderId,
346
+ type,
347
+ webhookUrl,
348
+ webhookSecret,
349
+ receiverMemo,
350
+ } = params;
351
+
352
+ // Create payment bridge configuration
353
+ const { preferred, destination } = createPaymentBridgeConfig({
354
+ toChain,
355
+ toToken,
356
+ toAddress,
357
+ toUnits: toUnits ?? "0",
358
+ // Preferred payment method (what user will pay with)
359
+ preferredChain,
360
+ preferredTokenAddress,
361
+ });
362
+
363
+ const sourceChain = getChainById(Number(preferred.preferredChain));
364
+ const sourceToken = getKnownToken(
365
+ Number(preferred.preferredChain),
366
+ preferred.preferredToken
367
+ );
368
+ const destinationChain = getChainById(Number(destination.chainId));
369
+ const destinationToken = getKnownToken(
370
+ Number(destination.chainId),
371
+ destination.tokenSymbol
372
+ );
373
+
374
+ if (!sourceToken || !destinationToken) {
375
+ throw new Error("Source or destination token not found");
376
+ }
377
+
378
+ // Build payment request data matching new backend interface
379
+ const paymentData: CreatePaymentRequest = {
380
+ appId,
381
+ destination: {
382
+ chainId: destinationChain.chainId,
383
+ receiverAddress: destination.destinationAddress ?? toAddress,
384
+ tokenSymbol: destinationToken.symbol,
385
+ amount: destination.amountUnits,
386
+ ...(destination.tokenAddress
387
+ ? { tokenAddress: destination.tokenAddress }
388
+ : {}),
389
+ ...(receiverMemo ? { receiverMemo } : {}),
390
+ },
391
+ source: {
392
+ chainId: sourceChain.chainId,
393
+ tokenSymbol: sourceToken.symbol,
394
+ amount: destination.amountUnits, // Use same amount for source
395
+ ...(preferred.preferredTokenAddress
396
+ ? { tokenAddress: preferred.preferredTokenAddress }
397
+ : {}),
398
+ },
399
+ display: {
400
+ currency: "USD",
401
+ title: title ?? "Payment",
402
+ ...(description ? { description } : {}),
403
+ },
404
+ ...(metadata ? { metadata } : {}),
405
+ ...(orderId ? { orderId } : {}),
406
+ ...(type ? { type } : {}),
407
+ ...(webhookUrl ? { webhookUrl } : {}),
408
+ ...(webhookSecret ? { webhookSecret } : {}),
409
+ };
410
+
411
+ // Create payment via API
412
+ const response = await apiClient.post<PaymentResponse>(
413
+ "/payment-api",
414
+ paymentData
415
+ );
416
+
417
+ if (!response?.data?.id) {
418
+ throw new Error(response?.error?.message ?? "Payment creation failed");
419
+ }
420
+
421
+ return response.data;
422
+ }
423
+
424
+ /**
425
+ * Gets payment details by ID using the new backend API
426
+ * @param paymentId - Payment ID
427
+ * @returns Promise with payment response
428
+ */
429
+ export const getNewPayment = (
430
+ paymentId: string
431
+ ): Promise<ApiResponse<PaymentResponse>> => {
432
+ return apiClient.get<PaymentResponse>(`/payment-api/${paymentId}`);
433
+ };
@@ -1,3 +1,4 @@
1
+ import { createPaymentBridgeConfig } from "../bridge";
1
2
  import { apiClient, ApiResponse } from "./base";
2
3
 
3
4
  /**
@@ -86,15 +87,33 @@ export interface PaymentResponseData {
86
87
  }
87
88
 
88
89
  /**
89
- * Creates a new payment
90
- * @param paymentData - Payment data to send
91
- * @returns Promise with payment response
90
+ * Simplified interface for creating a payment bridge
92
91
  */
93
- export const createRozoPayment = (
94
- paymentData: PaymentRequestData
95
- ): Promise<ApiResponse<PaymentResponseData>> => {
96
- return apiClient.post<PaymentResponseData>("/payment-api", paymentData);
97
- };
92
+ export interface CreatePaymentBridgeParams {
93
+ /** App ID for authentication */
94
+ appId: string;
95
+ // Destination (where funds will be received)
96
+ /** Destination chain ID (e.g., 8453 for Base, 900 for Solana, 10001 for Stellar) */
97
+ toChain: number;
98
+ /** Destination token address */
99
+ toToken: string;
100
+ /** Destination address - Can be EVM, Solana, or Stellar address */
101
+ toAddress: string;
102
+
103
+ // Preferred payment method (what user will pay with)
104
+ /** Chain ID where user will pay from (e.g., 137 for Polygon, 8453 for Base) */
105
+ preferredChain: number;
106
+ /** Token address user will pay with */
107
+ preferredTokenAddress: string;
108
+
109
+ // Payment details
110
+ /** Amount in human-readable units (e.g., "1" for 1 USDC, "0.5" for half a USDC) */
111
+ toUnits?: string;
112
+
113
+ // Optional metadata
114
+ /** Additional metadata to include */
115
+ metadata?: Record<string, unknown>;
116
+ }
98
117
 
99
118
  /**
100
119
  * Gets payment details by ID
@@ -110,3 +129,138 @@ export const getRozoPayment = (
110
129
  : `payment/id/${paymentId}`;
111
130
  return apiClient.get<PaymentResponseData>(endpoint);
112
131
  };
132
+
133
+ /**
134
+ * Creates a payment bridge configuration and initiates a Rozo payment
135
+ *
136
+ * This function combines the payment bridge configuration logic with payment creation,
137
+ * handling cross-chain payment routing and metadata merging. It provides a simplified
138
+ * API that doesn't require understanding internal types like WalletPaymentOption.
139
+ *
140
+ * @param params - Payment bridge creation parameters
141
+ * @returns Promise resolving to the payment response data
142
+ * @throws Error if payment creation fails or required parameters are missing
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * // Simple same-chain payment
147
+ * const payment = await createPaymentBridge({
148
+ * toChain: 8453, // Base
149
+ * toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
150
+ * toAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
151
+ * preferredChainId: 8453, // User pays from Base
152
+ * preferredToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
153
+ * toUnits: "1", // 1 USDC
154
+ * appId: "my-app-id",
155
+ * intent: "Pay",
156
+ * });
157
+ * ```
158
+ *
159
+ * @example
160
+ * ```typescript
161
+ * // Cross-chain payment: Polygon to Base
162
+ * const payment = await createPaymentBridge({
163
+ * toChain: 8453, // Base (destination)
164
+ * toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
165
+ * toAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb",
166
+ * preferredChainId: 137, // Polygon (user pays from)
167
+ * preferredToken: "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174", // Polygon USDC
168
+ * toUnits: "1",
169
+ * appId: "my-app-id",
170
+ * });
171
+ * ```
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Payment to Solana address (payout → Solana)
176
+ * const payment = await createPaymentBridge({
177
+ * toChain: 900, // Solana
178
+ * toToken: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // Solana USDC
179
+ * toAddress: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU", // Solana address
180
+ * preferredChainId: 8453, // User pays from Base
181
+ * preferredToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
182
+ * toUnits: "1",
183
+ * appId: "my-app-id",
184
+ * });
185
+ * ```
186
+ *
187
+ * @example
188
+ * ```typescript
189
+ * // Payment paid in from Stellar account
190
+ * const payment = await createPaymentBridge({
191
+ * toChain: 8453, // Payout on Base
192
+ * toToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
193
+ * toAddress: "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb", // EVM address
194
+ * preferredChainId: 1500, // Pay in from Stellar
195
+ * preferredToken: "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Stellar USDC (token format: code:issuer)
196
+ * toUnits: "10",
197
+ * appId: "my-app-id",
198
+ * });
199
+ * ```
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // Payment paying out to Stellar address (payout → Stellar)
204
+ * const payment = await createPaymentBridge({
205
+ * toChain: 1500, // Stellar
206
+ * toToken: "USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN", // Stellar USDC (token format: code:issuer)
207
+ * toAddress: "GA5ZSEPRY3STUGUUXZGHV5CDEQ2AJGEAAUUMSZK2QIPICFL2JVP4X6T4", // Stellar address
208
+ * preferredChainId: 8453, // User pays from Base
209
+ * preferredToken: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", // Base USDC
210
+ * toUnits: "1",
211
+ * appId: "my-app-id",
212
+ * });
213
+ * ```
214
+ */
215
+ export async function createRozoPayment(
216
+ params: CreatePaymentBridgeParams
217
+ ): Promise<PaymentResponseData> {
218
+ const {
219
+ toChain,
220
+ toToken,
221
+ toAddress,
222
+ preferredChain,
223
+ preferredTokenAddress,
224
+ toUnits,
225
+ appId,
226
+ metadata,
227
+ } = params;
228
+ // Create payment bridge configuration
229
+ const { preferred, destination, isIntentPayment } = createPaymentBridgeConfig(
230
+ {
231
+ toChain,
232
+ toToken,
233
+ toAddress,
234
+ toUnits: toUnits ?? "0",
235
+ // Preferred payment method (what user will pay with)
236
+ preferredChain,
237
+ preferredTokenAddress,
238
+ }
239
+ );
240
+
241
+ // Build payment request data
242
+ const paymentData: PaymentRequestData = {
243
+ appId,
244
+ display: {
245
+ intent: "",
246
+ paymentValue: String(toUnits ?? ""),
247
+ currency: "USD",
248
+ },
249
+ destination,
250
+ ...preferred,
251
+ ...(metadata ?? {}),
252
+ ...(isIntentPayment ? { intents: true } : {}),
253
+ };
254
+
255
+ // Create payment via API
256
+ const response = await apiClient.post<PaymentResponseData>(
257
+ "/payment-api",
258
+ paymentData
259
+ );
260
+
261
+ if (!response?.data?.id) {
262
+ throw new Error(response?.error?.message ?? "Payment creation failed");
263
+ }
264
+
265
+ return response.data;
266
+ }