@rozoai/intent-common 0.1.3 → 0.1.5

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/src/rozoPay.ts DELETED
@@ -1,638 +0,0 @@
1
- // TODO: this file defines types that shouldn't be exposed to the client.
2
- // Clean this up to only expose the types that are needed by the client.
3
-
4
- import { base58 } from "@scure/base";
5
- import {
6
- Address,
7
- bytesToBigInt,
8
- formatUnits,
9
- getAddress,
10
- Hex,
11
- numberToBytes,
12
- zeroAddress,
13
- } from "viem";
14
- import z from "zod";
15
- import { Token } from "./token";
16
-
17
- import { assertNotNull } from "./assert";
18
- import {
19
- BigIntStr,
20
- SolanaPublicKey,
21
- StellarPublicKey,
22
- zAddress,
23
- zBigIntStr,
24
- } from "./primitiveTypes";
25
-
26
- // lifecycle: waiting payment -> pending processing -> start submitted -> processed (onchain tx was successful)
27
- export enum RozoPayOrderStatusSource {
28
- WAITING_PAYMENT = "waiting_payment",
29
- PENDING_PROCESSING = "pending_processing",
30
- START_SUBMITTED = "start_submitted",
31
- /* Start transaction receipt confirmed. */
32
- PROCESSED = "processed",
33
- }
34
-
35
- // lifecycle: pending -> fast-finish-submitted (onchain tx submitted) -> fast-finished (onchain tx was successful) -> claimed (onchain tx was successful)
36
- export enum RozoPayOrderStatusDest {
37
- PENDING = "pending",
38
- FAST_FINISH_SUBMITTED = "fast_finish_submitted",
39
- /* Fast finish transaction receipt confirmed. */
40
- FAST_FINISHED = "fast_finished",
41
- CLAIM_SUCCESSFUL = "claimed",
42
- }
43
-
44
- export enum RozoPayOrderMode {
45
- SALE = "sale", // product or item sale
46
- CHOOSE_AMOUNT = "choose_amount", // let the user specify the amount to pay
47
- HYDRATED = "hydrated", // once hydrated, the order is final and all parameters are known and immutable
48
- }
49
-
50
- /**
51
- * Status values:
52
- * - `payment_unpaid` - the user has not paid yet
53
- * - `payment_started` - the user has paid & payment is in progress. This status
54
- * typically lasts a few seconds.
55
- * - `payment_completed` - the final call or transfer succeeded
56
- * - `payment_bounced` - the final call or transfer reverted. Funds were sent
57
- * to the payment's configured refund address on the destination chain.
58
- */
59
- export enum RozoPayIntentStatus {
60
- UNPAID = "payment_unpaid",
61
- STARTED = "payment_started",
62
- COMPLETED = "payment_completed",
63
- BOUNCED = "payment_bounced",
64
- PAYOUT_COMPLETED = "payout_completed",
65
- }
66
-
67
- export interface RozoPayOrderItem {
68
- name: string;
69
- description: string;
70
- image?: string;
71
- }
72
-
73
- export const zBridgeTokenOutOptions = z.array(
74
- z.object({
75
- token: zAddress,
76
- amount: zBigIntStr.transform((a) => BigInt(a)),
77
- })
78
- );
79
-
80
- export type BridgeTokenOutOptions = z.infer<typeof zBridgeTokenOutOptions>;
81
-
82
- // NOTE: be careful to modify this type only in backward-compatible ways.
83
- // Add OPTIONAL fields, etc. Anything else requires a migration.
84
- export const zRozoPayOrderMetadata = z.object({
85
- style: z
86
- .object({
87
- background: z.string().optional().describe("Background color."),
88
- })
89
- .optional()
90
- .describe("Style of the checkout page."),
91
- orgLogo: z.string().optional().describe("Logo of the organization."),
92
- intent: z
93
- .string()
94
- .describe("Title verb, eg 'Preorder', 'Check out', 'Deposit'."),
95
- items: z
96
- .array(
97
- z.object({
98
- name: z.string(),
99
- description: z.string(),
100
- image: z.string().optional(),
101
- price: z.string().optional(),
102
- priceDetails: z.string().optional(),
103
- })
104
- )
105
- .describe("Details about what's being ordered, donated, deposited, etc."),
106
- payer: z
107
- .object({
108
- preferredChains: z
109
- .array(z.number())
110
- .optional()
111
- .describe(
112
- "Preferred chain IDs, in descending order. Any assets the user owns on preferred chains will appear first. Defaults to destination chain."
113
- ),
114
- preferredTokens: z
115
- .array(
116
- z.object({
117
- chain: z.number(),
118
- address: zAddress.transform((a) => getAddress(a)),
119
- })
120
- )
121
- .optional()
122
- .describe(
123
- "Preferred tokens, in descending order. Any preferred assets the user owns will appear first. Defaults to destination token."
124
- ),
125
- // Filter to only allow payments on these chains. Keep this
126
- // parameter undocumented. Only for specific customers.
127
- evmChains: z
128
- .array(z.number())
129
- .optional()
130
- .describe(
131
- "Filter to only allow payments on these EVM chains. Defaults to all chains."
132
- ),
133
- paymentOptions: z
134
- .array(z.string())
135
- .optional()
136
- .describe(
137
- "Payment options like Coinbase, Binance, etc. Defaults to all available options."
138
- ),
139
- })
140
- .optional()
141
- .describe(""),
142
- memo: z.string().optional().describe("Memo for the payment."),
143
- customDeeplinkUrl: z
144
- .string()
145
- .optional()
146
- .describe("Custom deeplink URL for the payment."),
147
- });
148
-
149
- export type RozoPayOrderMetadata = z.infer<typeof zRozoPayOrderMetadata>;
150
-
151
- /**
152
- * The user-passed metadata must meet these criteria:
153
- * - All keys must be strings
154
- * - All values must be strings
155
- * - At most 50 key-value pairs
156
- * - Maximum of 40 characters per key
157
- * - Maximum of 500 characters per value
158
- */
159
- export const zRozoPayUserMetadata = z
160
- .record(
161
- z.string().max(40, "Metadata keys cannot be longer than 40 characters"),
162
- z.string().max(500, "Metadata values cannot be longer than 500 characters")
163
- )
164
- .nullable()
165
- .refine(
166
- (obj) => !obj || Object.keys(obj).length <= 50,
167
- "Metadata cannot have more than 50 key-value pairs"
168
- );
169
-
170
- export type RozoPayUserMetadata = z.infer<typeof zRozoPayUserMetadata>;
171
-
172
- export type RozoPayDehydratedOrder = {
173
- mode: RozoPayOrderMode.SALE | RozoPayOrderMode.CHOOSE_AMOUNT;
174
- id: bigint;
175
- destFinalCallTokenAmount: RozoPayTokenAmount;
176
- destFinalCall: OnChainCall;
177
- nonce: bigint;
178
- redirectUri: string | null;
179
- orgId: string | null;
180
- createdAt: number | null;
181
- lastUpdatedAt: number | null;
182
- intentStatus: RozoPayIntentStatus;
183
- metadata: RozoPayOrderMetadata;
184
- externalId: string | null;
185
- userMetadata: RozoPayUserMetadata | null;
186
- refundAddr: string | null;
187
- preferredChainId: number | null;
188
- preferredTokenAddress: string | null;
189
- memo?: string | null;
190
- };
191
-
192
- export type RozoPayHydratedOrder = {
193
- mode: RozoPayOrderMode.HYDRATED;
194
- id: bigint;
195
- intentAddr: string;
196
- /** Nullable because old intents don't record escrow address. */
197
- // escrowContractAddress: string | null;
198
- /** Nullable because old intents don't record bridger address. */
199
- // bridgerContractAddress: string | null;
200
- destFinalCallTokenAmount: RozoPayTokenAmount;
201
- destFinalCall: OnChainCall;
202
- usdValue: number;
203
- refundAddr: string;
204
- nonce: bigint;
205
- sourceFulfillerAddr: string | null;
206
- sourceTokenAmount: RozoPayTokenAmount | null;
207
- sourceInitiateTxHash: Hex | null;
208
- // sourceStartTxHash: Hex | null;
209
- sourceStatus: RozoPayOrderStatusSource;
210
- destStatus: RozoPayOrderStatusDest;
211
- destFastFinishTxHash: Hex | null;
212
- destClaimTxHash: Hex | null;
213
- redirectUri: string | null;
214
- orgId: string | null;
215
- createdAt: number | null;
216
- lastUpdatedAt: number | null;
217
- intentStatus: RozoPayIntentStatus;
218
- metadata: RozoPayOrderMetadata;
219
- externalId: string | null;
220
- userMetadata: RozoPayUserMetadata | null;
221
- /** Nullable because old intents don't have expiration time. */
222
- expirationTs: bigint | null;
223
- memo?: string | null;
224
- preferredChainId: number | null;
225
- preferredTokenAddress: string | null;
226
- payoutTransactionHash?: string | null;
227
- /** @deprecated included for backcompat with old versions. Remove soon. */
228
- // handoffAddr: string;
229
- // bridgeTokenOutOptions: RozoPayTokenAmount[];
230
- // selectedBridgeTokenOutAddr: string | null;
231
- // selectedBridgeTokenOutAmount: bigint | null;
232
- };
233
-
234
- export type RozoPayOrderWithOrg = RozoPayOrder & {
235
- org: RozoPayOrgPublicInfo;
236
- };
237
-
238
- export type RozoPayHydratedOrderWithOrg = RozoPayHydratedOrder & {
239
- org: RozoPayOrgPublicInfo;
240
- };
241
-
242
- export type RozoPayOrgPublicInfo = {
243
- orgId: string;
244
- name: string;
245
- logoURI?: string;
246
- };
247
-
248
- export type RozoPayHydratedOrderWithoutIntentAddr = Omit<
249
- RozoPayHydratedOrder,
250
- "intentAddr" | "handoffAddr"
251
- >;
252
-
253
- export type RozoPayOrder = RozoPayDehydratedOrder | RozoPayHydratedOrder;
254
-
255
- export function isHydrated(order: RozoPayOrder): order is RozoPayHydratedOrder {
256
- return order.mode === RozoPayOrderMode.HYDRATED;
257
- }
258
-
259
- type RozoAddress = Address | SolanaPublicKey | StellarPublicKey;
260
-
261
- export type RozoPayOrderView = {
262
- id: RozoPayOrderID;
263
- status: RozoPayIntentStatus;
264
- createdAt: string;
265
- display: {
266
- intent: string;
267
- paymentValue: string;
268
- currency: "USD";
269
- };
270
- source: {
271
- payerAddress: RozoAddress | null;
272
- txHash: Hex | string | null;
273
- chainId: string;
274
- amountUnits: string;
275
- tokenSymbol: string;
276
- tokenAddress: RozoAddress | string;
277
- } | null;
278
- destination: {
279
- destinationAddress: RozoAddress;
280
- txHash: Hex | null;
281
- chainId: string;
282
- amountUnits: string;
283
- tokenSymbol: string;
284
- tokenAddress: RozoAddress;
285
- callData: Hex | null;
286
- };
287
- externalId: string | null;
288
- metadata: RozoPayUserMetadata | null;
289
- };
290
-
291
- export function getOrderSourceChainId(
292
- order: RozoPayHydratedOrder
293
- ): number | null {
294
- if (order.sourceTokenAmount == null) {
295
- return null;
296
- }
297
- return order.sourceTokenAmount.token.chainId;
298
- }
299
-
300
- export function getOrderDestChainId(
301
- order: RozoPayOrder | RozoPayHydratedOrderWithoutIntentAddr
302
- ): number {
303
- return order.destFinalCallTokenAmount.token.chainId;
304
- }
305
-
306
- export function mergedMetadata(data: Record<string, any>): Record<string, any> {
307
- // Ignore this metadata
308
- delete data.payintokenaddress;
309
- delete data.preferredChain;
310
- delete data.preferredToken;
311
- delete data.provider;
312
- delete data.receivingAddress;
313
-
314
- return data;
315
- }
316
-
317
- export function getRozoPayOrderView(order: RozoPayOrder): RozoPayOrderView {
318
- return {
319
- id: writeRozoPayOrderID(order.id),
320
- status: order.intentStatus,
321
- createdAt: assertNotNull(
322
- order.createdAt,
323
- `createdAt is null for order with id: ${order.id}`
324
- ).toString(),
325
- display: {
326
- intent: order.metadata.intent,
327
- // Show 2 decimal places for USD
328
- paymentValue: order.destFinalCallTokenAmount.usd.toFixed(2),
329
- currency: "USD",
330
- },
331
- source:
332
- order.mode === RozoPayOrderMode.HYDRATED &&
333
- order.sourceTokenAmount != null
334
- ? {
335
- payerAddress: order.sourceFulfillerAddr,
336
- txHash: order.sourceInitiateTxHash,
337
- chainId: assertNotNull(
338
- getOrderSourceChainId(order),
339
- `source chain id is null for order with source token: ${order.id}`
340
- ).toString(),
341
- amountUnits: formatUnits(
342
- BigInt(order.sourceTokenAmount.amount),
343
- order.sourceTokenAmount.token.decimals
344
- ),
345
- tokenSymbol: order.sourceTokenAmount.token.symbol,
346
- tokenAddress: order.sourceTokenAmount.token.token,
347
- }
348
- : null,
349
- destination: {
350
- destinationAddress: order.destFinalCall.to,
351
- txHash:
352
- order.mode === RozoPayOrderMode.HYDRATED
353
- ? order.destFastFinishTxHash ?? order.destClaimTxHash
354
- : null,
355
- chainId: getOrderDestChainId(order).toString(),
356
- amountUnits: formatUnits(
357
- BigInt(order.destFinalCallTokenAmount.amount),
358
- order.destFinalCallTokenAmount.token.decimals
359
- ),
360
- tokenSymbol: order.destFinalCallTokenAmount.token.symbol,
361
- tokenAddress: order.destFinalCallTokenAmount.token.token,
362
- callData: order.destFinalCall.data,
363
- },
364
- externalId: order.externalId,
365
- metadata: mergedMetadata({
366
- ...order.metadata,
367
- ...order.userMetadata,
368
- }),
369
- };
370
- }
371
-
372
- export type WalletPaymentOption = {
373
- balance: RozoPayTokenAmount;
374
-
375
- // TODO: deprecate, replace with requiredUsd / minRequiredUsd / feesUsd
376
- // These are overly large objects that duplicate RozoPayToken
377
- required: RozoPayTokenAmount;
378
- minimumRequired: RozoPayTokenAmount;
379
- fees: RozoPayTokenAmount;
380
-
381
- disabledReason?: string;
382
- };
383
-
384
- export type ExternalPaymentOptionMetadata = {
385
- id: ExternalPaymentOptions;
386
- optionType: "external" | "zkp2p" | "exchange" | "stellar";
387
- cta: string;
388
- logoURI: string;
389
- logoShape: "circle" | "squircle";
390
- paymentToken: RozoPayToken;
391
- disabled: boolean;
392
- message?: string;
393
- minimumUsd?: number;
394
- };
395
-
396
- export enum ExternalPaymentOptions {
397
- Rozo = "Rozo",
398
- RampNetwork = "RampNetwork",
399
- Solana = "Solana",
400
- ExternalChains = "ExternalChains",
401
- Stellar = "Stellar",
402
- // All exchanges
403
- AllExchanges = "AllExchanges",
404
- Coinbase = "Coinbase",
405
- Binance = "Binance",
406
- Lemon = "Lemon",
407
- // All available payment apps
408
- AllPaymentApps = "AllPaymentApps",
409
- Venmo = "Venmo",
410
- CashApp = "CashApp",
411
- MercadoPago = "MercadoPago",
412
- Revolut = "Revolut",
413
- Wise = "Wise",
414
- Ethereum = "Ethereum",
415
- }
416
-
417
- export type ExternalPaymentOptionsString = `${ExternalPaymentOptions}`;
418
-
419
- export type ExternalPaymentOptionData = {
420
- url: string;
421
- waitingMessage: string;
422
- };
423
-
424
- export enum DepositAddressPaymentOptions {
425
- TRON_USDT = "USDT on Tron",
426
- BASE = "Base",
427
- BSC = "BSC",
428
- ARBITRUM = "Arbitrum",
429
- OP_MAINNET = "Optimism",
430
- POLYGON = "Polygon",
431
- ETH_L1 = "Ethereum",
432
- SOLANA = "Solana",
433
- STELLAR = "Stellar",
434
- WORLD = "Worldchain",
435
-
436
- SOLANA_USDT = "USDT on Solana",
437
- SOLANA_USDC = "USDC on Solana",
438
- BASE_USDC = "USDC on Base",
439
- ETHEREUM_USDT = "USDT on Ethereum",
440
- ETHEREUM_USDC = "USDC on Ethereum",
441
-
442
- /** @deprecated */
443
- BITCOIN = "Bitcoin",
444
- /** @deprecated */
445
- TON = "TON",
446
- /** @deprecated */
447
- MONERO = "Monero",
448
- /** @deprecated */
449
- DOGE = "Doge",
450
- /** @deprecated */
451
- LITECOIN = "Litecoin",
452
- /** @deprecated */
453
- ZCASH = "Zcash",
454
- /** @deprecated */
455
- DASH = "Dash",
456
- }
457
-
458
- export type DepositAddressPaymentOptionMetadata = {
459
- id: DepositAddressPaymentOptions;
460
- logoURI: string;
461
- minimumUsd: number;
462
- chainId: number;
463
- token: Token;
464
- };
465
-
466
- export type DepositAddressPaymentOptionData = {
467
- address: string;
468
- uri: string;
469
- amount: string;
470
- suffix: string;
471
- expirationS: number;
472
- };
473
-
474
- export interface RozoPayToken extends Token {
475
- token: string;
476
- /** Price to convert 1.0 of this token to a USD stablecoin. */
477
- usd: number;
478
- /** Price to convert $1 to this token T. If 2.00, then we receive 0.5 T. */
479
- priceFromUsd: number;
480
- /** Max payment accepted in this token, based on liquidity & mode. */
481
- maxAcceptUsd: number;
482
- /** Max payment we can send from this token, based on liquidity & mode. */
483
- maxSendUsd: number;
484
- /** Display decimals, separate from token decimals. Eg: 2 for USDC. */
485
- displayDecimals: number;
486
- /** Symbol for fiat currency, eg: "$" */
487
- fiatSymbol?: string;
488
- }
489
-
490
- export interface RozoPayTokenAmount {
491
- token: RozoPayToken;
492
- amount: BigIntStr;
493
- usd: number; // amount in dollars
494
- }
495
-
496
- export type OnChainCall = {
497
- to: string;
498
- data: Hex;
499
- value: bigint;
500
- };
501
-
502
- export const emptyOnChainCall: OnChainCall = {
503
- to: zeroAddress,
504
- data: "0x",
505
- value: 0n,
506
- };
507
-
508
- // base58 encoded bigint
509
- const zRozoPayOrderID = z.string().regex(/^[1-9A-HJ-NP-Za-km-z]+$/);
510
-
511
- export type RozoPayOrderID = z.infer<typeof zRozoPayOrderID>;
512
-
513
- /**
514
- * Read a base58-encoded id into a bigint.
515
- */
516
- export function readRozoPayOrderID(id: string): bigint {
517
- return bytesToBigInt(base58.decode(id));
518
- }
519
-
520
- /**
521
- * Write a bigint into a base58-encoded id.
522
- */
523
- export function writeRozoPayOrderID(id: bigint): string {
524
- return base58.encode(numberToBytes(id));
525
- }
526
-
527
- export const zUUID = z.string().uuid();
528
-
529
- export type UUID = z.infer<typeof zUUID>;
530
-
531
- export enum RozoPayEventType {
532
- PaymentStarted = "payment_started",
533
- PaymentCompleted = "payment_completed",
534
- PaymentBounced = "payment_bounced",
535
- PaymentRefunded = "payment_refunded",
536
- PaymentPayoutCompleted = "payment_payout_completed",
537
- }
538
-
539
- export type PaymentStartedEvent = {
540
- type: RozoPayEventType.PaymentStarted;
541
- isTestEvent?: boolean;
542
- paymentId: RozoPayOrderID;
543
- chainId: number;
544
- txHash: Hex | string | null;
545
- payment: RozoPayOrderView;
546
- };
547
-
548
- export type PaymentCompletedEvent = {
549
- type: RozoPayEventType.PaymentCompleted;
550
- isTestEvent?: boolean;
551
- paymentId: RozoPayOrderID;
552
- chainId: number;
553
- txHash: string;
554
- payment: RozoPayOrderView;
555
- rozoPaymentId?: string;
556
- };
557
-
558
- export type PaymentPayoutCompletedEvent = {
559
- type: RozoPayEventType.PaymentPayoutCompleted;
560
- isTestEvent?: boolean;
561
- paymentId: RozoPayOrderID;
562
- paymentTx: {
563
- hash: string;
564
- chainId: number;
565
- url: string;
566
- };
567
- payoutTx: {
568
- hash: string;
569
- chainId: number;
570
- url: string;
571
- };
572
- payment: RozoPayOrderView;
573
- rozoPaymentId?: string;
574
- };
575
-
576
- export type PaymentBouncedEvent = {
577
- type: RozoPayEventType.PaymentBounced;
578
- isTestEvent?: boolean;
579
- paymentId: RozoPayOrderID;
580
- chainId: number;
581
- txHash: string;
582
- payment: RozoPayOrderView;
583
- rozoPaymentId?: string;
584
- };
585
-
586
- export type PaymentRefundedEvent = {
587
- type: RozoPayEventType.PaymentRefunded;
588
- isTestEvent?: boolean;
589
- paymentId: RozoPayOrderID;
590
- refundAddress: string;
591
- chainId: number;
592
- tokenAddress: string;
593
- txHash: string;
594
- amountUnits: string;
595
- payment: RozoPayOrderView;
596
- };
597
-
598
- export type RozoPayEvent =
599
- | PaymentStartedEvent
600
- | PaymentCompletedEvent
601
- | PaymentBouncedEvent
602
- | PaymentRefundedEvent
603
- | PaymentPayoutCompletedEvent;
604
-
605
- export interface WebhookEndpoint {
606
- id: UUID;
607
- orgId: UUID;
608
- url: string;
609
- token: string;
610
- createdAt: Date;
611
- deletedAt: Date | null;
612
- }
613
-
614
- // Lifecycle: Pending (just created) -> (if failing) Retrying (exponential backoff) -> Successful or Failed
615
- export enum WebhookEventStatus {
616
- PENDING = "pending", // waiting to be delivered
617
- RETRYING = "retrying", // currently in exponential backoff queue
618
- SUCCESSFUL = "successful", // successfully delivered
619
- FAILED = "failed", // gave up after retrying
620
- }
621
-
622
- export interface WebhookEvent {
623
- id: UUID;
624
- endpoint: WebhookEndpoint;
625
- isTestEvent: boolean;
626
- body: RozoPayEvent;
627
- status: WebhookEventStatus;
628
- deliveries: WebhookDelivery[];
629
- createdAt: Date;
630
- }
631
-
632
- export interface WebhookDelivery {
633
- id: UUID;
634
- eventId: UUID;
635
- httpStatus: number | null;
636
- body: string | null;
637
- createdAt: Date;
638
- }