@rozoai/intent-common 0.1.2 → 0.1.4

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.
@@ -1,382 +0,0 @@
1
- import { parseUnits } from "viem";
2
- import {
3
- baseUSDC,
4
- getChainById,
5
- getKnownToken,
6
- isChainSupported,
7
- isTokenSupported,
8
- PaymentResponse,
9
- RozoPayHydratedOrderWithOrg,
10
- RozoPayIntentStatus,
11
- RozoPayOrderMode,
12
- RozoPayOrderStatusDest,
13
- RozoPayOrderStatusSource,
14
- RozoPayUserMetadata,
15
- rozoSolana,
16
- rozoSolanaUSDC,
17
- rozoStellarUSDC,
18
- solana,
19
- validateAddressForChain,
20
- } from ".";
21
-
22
- export interface PaymentBridgeConfig {
23
- toChain: number;
24
- toToken: string;
25
- toAddress: string;
26
- toUnits: string;
27
- preferredChain: number;
28
- preferredTokenAddress: string;
29
- }
30
-
31
- export interface PreferredPaymentConfig {
32
- preferredChain: string;
33
- preferredToken: string;
34
- preferredTokenAddress: string;
35
- }
36
-
37
- export interface DestinationConfig {
38
- destinationAddress?: string;
39
- chainId: string;
40
- amountUnits: string;
41
- tokenSymbol: string;
42
- tokenAddress: string;
43
- }
44
-
45
- interface PaymentBridge {
46
- preferred: PreferredPaymentConfig;
47
- destination: DestinationConfig;
48
- isIntentPayment: boolean;
49
- }
50
-
51
- /**
52
- * Creates payment bridge configuration for cross-chain payment routing
53
- *
54
- * Determines the optimal payment routing based on the destination chain/token
55
- * and the preferred payment method selected by the user. This function handles
56
- * the complexity of multi-chain payments by:
57
- *
58
- * 1. **Preferred Payment Method**: Identifies which chain/token the user will pay from
59
- * - Supports Base USDC, Polygon USDC, Ethereum USDC, Solana USDC, Stellar USDC, Worldchain USDC, and BSC USDT
60
- * - Sets appropriate chain ID and token address for the source transaction
61
- *
62
- * 2. **Destination Configuration**: Determines where funds will be received
63
- * - Supports Base, Solana, Stellar, and Worldchain as destination chains
64
- * - Automatically handles special address formats for Solana and Stellar addresses
65
- * - Configures destination token based on chain type (e.g., Stellar/Solana USDC)
66
- *
67
- * 3. **Intent Payment Detection**: Determines if this is a cross-chain intent payment
68
- * - Returns `isIntentPayment: true` when preferred chain/token differs from destination
69
- * - Returns `isIntentPayment: false` for same-chain, same-token payments
70
- *
71
- * @param config - Payment bridge configuration parameters
72
- * @param config.toChain - Destination chain ID (e.g., 8453 for Base, 900 for Solana, 10001 for Stellar)
73
- * @param config.toToken - Destination token address (must be a supported token on the destination chain)
74
- * @param config.toAddress - Destination address (format validated based on chain type: EVM 0x..., Solana Base58, Stellar G...)
75
- * @param config.toUnits - Amount in human-readable units (e.g., "1" for 1 USDC, "0.5" for half a USDC)
76
- * @param config.preferredChain - Chain ID where the user will pay from (e.g., 137 for Polygon, 8453 for Base)
77
- * @param config.preferredTokenAddress - Token address the user selected to pay with (must be a supported token on preferredChain)
78
- *
79
- * @returns Payment routing configuration object
80
- * @returns preferred - Source payment configuration (chain, token user will pay from)
81
- * @returns preferred.preferredChain - Chain ID as string where payment originates
82
- * @returns preferred.preferredToken - Token symbol (e.g., "USDC", "USDT")
83
- * @returns preferred.preferredTokenAddress - Token contract address
84
- * @returns destination - Destination payment configuration (chain, token user will receive)
85
- * @returns destination.destinationAddress - Address where funds will be received
86
- * @returns destination.chainId - Destination chain ID as string
87
- * @returns destination.amountUnits - Payment amount in token units
88
- * @returns destination.tokenSymbol - Destination token symbol
89
- * @returns destination.tokenAddress - Destination token contract address
90
- * @returns isIntentPayment - Boolean indicating if this is a cross-chain intent payment
91
- *
92
- * @throws {Error} If the destination token is not supported for the destination chain
93
- * @throws {Error} If the destination address format is invalid for the destination chain
94
- * @throws {Error} If the preferred token is not supported for the preferred chain
95
- * @throws {Error} If the destination chain or token is not supported
96
- *
97
- * @example
98
- * ```typescript
99
- * // User wants to pay with Polygon USDC to receive on Base
100
- * import { baseUSDC, polygonUSDCe } from '@rozoai/intent-common';
101
- * import { base, polygon } from '@rozoai/intent-common';
102
- *
103
- * const { preferred, destination, isIntentPayment } = createPaymentBridgeConfig({
104
- * toChain: base.chainId, // 8453
105
- * toToken: baseUSDC.token,
106
- * toAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
107
- * toUnits: '1000000', // 1 USDC (6 decimals)
108
- * preferredChain: polygon.chainId, // 137
109
- * preferredToken: polygonUSDCe.token,
110
- * });
111
- *
112
- * // preferred = { preferredChain: '137', preferredToken: 'USDCe', preferredTokenAddress: '0x2791...' }
113
- * // destination = { destinationAddress: '0x742d...', chainId: '8453', amountUnits: '1000000', tokenSymbol: 'USDC', tokenAddress: '0x8335...' }
114
- * // isIntentPayment = true (different chains)
115
- * ```
116
- *
117
- * @example
118
- * ```typescript
119
- * // User wants to pay to a Stellar address using Base USDC
120
- * import { baseUSDC, rozoStellarUSDC } from '@rozoai/intent-common';
121
- * import { base, rozoStellar } from '@rozoai/intent-common';
122
- *
123
- * const { preferred, destination, isIntentPayment } = createPaymentBridgeConfig({
124
- * toChain: rozoStellar.chainId, // 10001
125
- * toToken: rozoStellarUSDC.token,
126
- * toAddress: 'GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN',
127
- * toUnits: '10000000', // 1 USDC (7 decimals for Stellar)
128
- * preferredChain: base.chainId, // 8453
129
- * preferredToken: baseUSDC.token,
130
- * });
131
- *
132
- * // preferred = { preferredChain: '8453', preferredToken: 'USDC', preferredTokenAddress: '0x8335...' }
133
- * // destination = { destinationAddress: 'GA5Z...', chainId: '10001', amountUnits: '10000000', tokenSymbol: 'USDC', tokenAddress: 'USDC:GA5Z...' }
134
- * // isIntentPayment = true (Base to Stellar)
135
- * ```
136
- *
137
- * @example
138
- * ```typescript
139
- * // Same-chain payment (not an intent payment)
140
- * const { preferred, destination, isIntentPayment } = createPaymentBridgeConfig({
141
- * toChain: base.chainId, // 8453
142
- * toToken: baseUSDC.token,
143
- * toAddress: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
144
- * toUnits: '1000000',
145
- * preferredChain: base.chainId, // 8453
146
- * preferredToken: baseUSDC.token,
147
- * });
148
- *
149
- * // isIntentPayment = false (same chain and token)
150
- * ```
151
- *
152
- * @see PreferredPaymentConfig
153
- * @see DestinationConfig
154
- * @see PaymentBridgeConfig
155
- */
156
- export function createPaymentBridgeConfig({
157
- toChain,
158
- toToken,
159
- toAddress,
160
- toUnits,
161
- preferredChain,
162
- preferredTokenAddress,
163
- }: PaymentBridgeConfig): PaymentBridge {
164
- const chain = getChainById(toChain);
165
- const token = getKnownToken(toChain, toToken);
166
-
167
- if (!token) {
168
- throw new Error(
169
- `Unsupported token ${toToken} for chain ${chain.name} (${toChain})`
170
- );
171
- }
172
-
173
- const addressValid = validateAddressForChain(toChain, toAddress);
174
- if (!addressValid) {
175
- throw new Error(
176
- `Invalid address ${toAddress} for chain ${chain.name} (${toChain})`
177
- );
178
- }
179
-
180
- const preferredChainData = getChainById(preferredChain);
181
- const tokenConfig = getKnownToken(preferredChain, preferredTokenAddress);
182
- if (!tokenConfig) {
183
- throw new Error(
184
- `Unknown token ${preferredTokenAddress} for chain ${preferredChainData.name} (${preferredChain})`
185
- );
186
- }
187
-
188
- let preferred: PreferredPaymentConfig = {
189
- preferredChain: String(preferredChain),
190
- preferredToken: tokenConfig.symbol,
191
- preferredTokenAddress: preferredTokenAddress,
192
- };
193
-
194
- let destination: DestinationConfig = {
195
- destinationAddress: toAddress,
196
- chainId: String(toChain),
197
- amountUnits: toUnits,
198
- tokenSymbol: token.symbol,
199
- tokenAddress: toToken,
200
- };
201
-
202
- if (isChainSupported(toChain) && isTokenSupported(toChain, toToken)) {
203
- preferred = {
204
- preferredChain: String(
205
- tokenConfig.chainId === solana.chainId
206
- ? rozoSolana.chainId
207
- : tokenConfig.chainId
208
- ),
209
- preferredToken: tokenConfig.symbol,
210
- preferredTokenAddress: tokenConfig.token,
211
- };
212
-
213
- // Determine destination based on special address types
214
- if (isChainSupported(toChain, "stellar")) {
215
- destination = {
216
- ...destination,
217
- tokenSymbol: rozoStellarUSDC.symbol,
218
- chainId: String(rozoStellarUSDC.chainId),
219
- tokenAddress: rozoStellarUSDC.token,
220
- };
221
- } else if (isChainSupported(toChain, "solana")) {
222
- destination = {
223
- ...destination,
224
- tokenSymbol: rozoSolanaUSDC.symbol,
225
- chainId: String(rozoSolanaUSDC.chainId),
226
- tokenAddress: rozoSolanaUSDC.token,
227
- };
228
- }
229
- } else {
230
- throw new Error(
231
- `Unsupported chain ${chain.name} (${toChain}) or token ${token.symbol} (${toToken})`
232
- );
233
- }
234
-
235
- // If the preferred chain and token are not the same as the toChain and toToken, then it is an intent payment
236
- const isIntentPayment =
237
- preferred.preferredChain !== String(toChain) &&
238
- preferred.preferredTokenAddress !== toToken;
239
-
240
- return { preferred, destination, isIntentPayment };
241
- }
242
-
243
- /**
244
- * Converts a RozoAI payment API response to a fully hydrated RozoPay order.
245
- *
246
- * This utility transforms the low-level {@link PaymentResponse} object returned by the RozoAI Intent Pay API
247
- * into a {@link RozoPayHydratedOrderWithOrg}, containing all values needed for UI display, order tracking,
248
- * and multi-chain cross-payment logic. Fields are normalized and token metadata is resolved in order to
249
- * standardize data from different chains and token types.
250
- *
251
- * Key steps performed:
252
- *
253
- * 1. **Token Metadata Lookup**: Uses {@link getKnownToken} to identify the correct token
254
- * for the payment, including decimals, symbol, logo, and chain details.
255
- * Special handling is applied for Stellar and Solana tokens based on how they're encoded in the backend.
256
- *
257
- * 2. **Order Hydration**: Generates a unique (random BigInt) internal order ID for frontend usage, sets the
258
- * payment mode as HYDRATED, and resolves all destination call and amount fields from the payment response.
259
- *
260
- * 3. **Status Initialization**: Initializes the payment, source, and destination status fields
261
- * with their correct values based on the payment's progress in the state machine. The returned object is
262
- * ready for status tracking and user notification.
263
- *
264
- * 4. **Metadata Consolidation**: Merges core order metadata, user metadata (if provided by the payer),
265
- * and any external references such as org info. Ensures all details needed for order display and analytics are available.
266
- *
267
- * @param order - Low-level API payment response (from RozoAI Intent Pay backend)
268
- * @param feeType - Optional: Fee deduction mode (ExactIn/ExactOut); determines which side's amount is shown as source. Defaults to ExactIn.
269
- *
270
- * @returns {RozoPayHydratedOrderWithOrg} A normalized, display-ready order representation containing all tracking, status,
271
- * token, org, and routing information for frontend use.
272
- *
273
- * @example
274
- * ```typescript
275
- * const paymentResponse = await getPayment(paymentId);
276
- * const hydratedOrder = formatPaymentResponseToHydratedOrder(paymentResponse.data);
277
- * console.log(hydratedOrder.sourceStatus); // 'WAITING_PAYMENT'
278
- * console.log(hydratedOrder.destFinalCallTokenAmount.token.symbol); // 'USDC'
279
- * console.log(hydratedOrder.usdValue); // 10.00
280
- * ```
281
- *
282
- * @remarks
283
- * - The returned `id` (BigInt) is generated randomly and is client-side only; always use
284
- * `order.orderId` or the API reference for backend/server reconciliation.
285
- * - The expiration timestamp and org info are carried over if present on the API response.
286
- * - Decimals, token symbol, and display metadata for the amount and destination chain
287
- * are resolved so the result is immediately usable for UI.
288
- *
289
- * @see PaymentResponse
290
- * @see RozoPayHydratedOrderWithOrg
291
- * @see getKnownToken
292
- */
293
- export function formatPaymentResponseToHydratedOrder(
294
- order: PaymentResponse
295
- ): RozoPayHydratedOrderWithOrg {
296
- // Source amount is in the same units as the destination amount without fee
297
- const sourceAmountUnits =
298
- order.source?.amount ?? order.destination?.amountUnits ?? "0";
299
-
300
- // Destination Intent Address
301
- const intentAddress =
302
- order.metadata?.receivingAddress ?? order.source?.receiverAddress;
303
-
304
- // Destination Intent Memo
305
- const intentMemo = order.metadata?.memo ?? order.source?.receiverMemo;
306
-
307
- // Destination address is where the payment will be received
308
- const destAddress = order.source?.receiverAddress;
309
-
310
- // Determine the chain from metadata or default to the source chain
311
- const requiredChain = order.source?.chainId || baseUSDC.chainId;
312
-
313
- const token = getKnownToken(
314
- Number(requiredChain),
315
- Number(requiredChain) === rozoStellarUSDC.chainId
316
- ? rozoStellarUSDC.token
317
- : order.source?.tokenAddress || ""
318
- );
319
-
320
- return {
321
- id: BigInt(Math.floor(Math.random() * Number.MAX_SAFE_INTEGER)),
322
- mode: RozoPayOrderMode.HYDRATED,
323
- intentAddr: intentAddress ?? "",
324
- memo: intentMemo ?? null,
325
- preferredChainId: order.source?.chainId ?? null,
326
- preferredTokenAddress: order.source?.tokenAddress ?? null,
327
- destFinalCallTokenAmount: {
328
- token: {
329
- chainId: token ? token.chainId : baseUSDC.chainId,
330
- token: token ? token.token : baseUSDC.token,
331
- symbol: token ? token.symbol : baseUSDC.symbol,
332
- usd: Number(sourceAmountUnits),
333
- priceFromUsd: 1,
334
- decimals: token ? token.decimals : baseUSDC.decimals,
335
- displayDecimals: 2,
336
- logoSourceURI: token ? token.logoSourceURI : baseUSDC.logoSourceURI,
337
- logoURI: token ? token.logoURI : baseUSDC.logoURI,
338
- maxAcceptUsd: 100000,
339
- maxSendUsd: 0,
340
- },
341
- amount: parseUnits(
342
- sourceAmountUnits,
343
- token ? token.decimals : baseUSDC.decimals
344
- ).toString() as `${bigint}`,
345
- usd: Number(sourceAmountUnits),
346
- },
347
- usdValue: Number(sourceAmountUnits),
348
- destFinalCall: {
349
- to: destAddress ?? "",
350
- value: BigInt("0"),
351
- data: "0x",
352
- },
353
- refundAddr: (order.source?.senderAddress as any) || null,
354
- nonce: BigInt(order.nonce ?? 0),
355
- sourceFulfillerAddr: null,
356
- sourceTokenAmount: null,
357
- sourceInitiateTxHash: null,
358
- sourceStatus: RozoPayOrderStatusSource.WAITING_PAYMENT,
359
- destStatus: RozoPayOrderStatusDest.PENDING,
360
- intentStatus: RozoPayIntentStatus.UNPAID,
361
- destFastFinishTxHash: null,
362
- destClaimTxHash: null,
363
- redirectUri: null,
364
- createdAt: Math.floor(new Date(order.createdAt).getTime() / 1000),
365
- lastUpdatedAt: Math.floor(new Date(order.updatedAt).getTime() / 1000),
366
- orgId: order.orgId ?? "",
367
- metadata: {
368
- ...(order?.metadata ?? {}),
369
- receivingAddress: intentAddress ?? "",
370
- memo: intentMemo ?? null,
371
- } as any,
372
- externalId: order.externalId ?? null,
373
- userMetadata: order.userMetadata as RozoPayUserMetadata | null,
374
- expirationTs: BigInt(
375
- Math.floor(new Date(order.expiresAt).getTime() / 1000).toString()
376
- ),
377
- org: {
378
- orgId: order.orgId ?? "",
379
- name: "",
380
- },
381
- };
382
- }
package/src/chain.ts DELETED
@@ -1,257 +0,0 @@
1
- export type Chain = {
2
- type: "evm" | "solana" | "stellar";
3
- chainId: number;
4
- name: string;
5
- cctpDomain: number | null;
6
- };
7
-
8
- export const arbitrum: Chain = {
9
- type: "evm",
10
- chainId: 42161,
11
- name: "Arbitrum",
12
- cctpDomain: 3,
13
- };
14
-
15
- export const base: Chain = {
16
- type: "evm",
17
- chainId: 8453,
18
- name: "Base",
19
- cctpDomain: 6,
20
- };
21
-
22
- export const bsc: Chain = {
23
- type: "evm",
24
- chainId: 56,
25
- name: "BNB",
26
- cctpDomain: null,
27
- };
28
-
29
- export const celo: Chain = {
30
- type: "evm",
31
- chainId: 42220,
32
- name: "Celo",
33
- cctpDomain: null,
34
- };
35
-
36
- export const ethereum: Chain = {
37
- type: "evm",
38
- chainId: 1,
39
- name: "Ethereum",
40
- cctpDomain: 0,
41
- };
42
-
43
- export const linea: Chain = {
44
- type: "evm",
45
- chainId: 59144,
46
- name: "Linea",
47
- cctpDomain: 11,
48
- };
49
-
50
- export const mantle: Chain = {
51
- type: "evm",
52
- chainId: 5000,
53
- name: "Mantle",
54
- cctpDomain: null,
55
- };
56
-
57
- export const optimism: Chain = {
58
- type: "evm",
59
- chainId: 10,
60
- name: "Optimism",
61
- cctpDomain: 2,
62
- };
63
-
64
- export const polygon: Chain = {
65
- type: "evm",
66
- chainId: 137,
67
- name: "Polygon",
68
- cctpDomain: 7,
69
- };
70
-
71
- export const solana: Chain = {
72
- type: "solana",
73
- chainId: 501,
74
- name: "Solana",
75
- cctpDomain: 5,
76
- };
77
-
78
- export const stellar: Chain = {
79
- type: "stellar",
80
- chainId: 10001,
81
- name: "Stellar",
82
- cctpDomain: null,
83
- };
84
-
85
- export const worldchain: Chain = {
86
- type: "evm",
87
- chainId: 480,
88
- name: "Worldchain",
89
- cctpDomain: 14,
90
- };
91
-
92
- /**
93
- * Rozo Solana
94
- * @link https://github.com/RozoAI/rozo-payment-manager/tree/staging?tab=readme-ov-file#supported-chains-and-tokens
95
- */
96
- export const rozoSolana: Chain = {
97
- type: "solana",
98
- chainId: 900,
99
- name: "Solana",
100
- cctpDomain: 5,
101
- };
102
-
103
- export const rozoStellar: Chain = {
104
- type: "stellar",
105
- chainId: 1500,
106
- name: "Stellar",
107
- cctpDomain: null,
108
- };
109
-
110
- export const gnosis: Chain = {
111
- type: "evm",
112
- chainId: 100,
113
- name: "Gnosis",
114
- cctpDomain: null,
115
- };
116
-
117
- export const avalanche: Chain = {
118
- type: "evm",
119
- chainId: 43114,
120
- name: "Avalanche",
121
- cctpDomain: null,
122
- };
123
-
124
- /**
125
- * Supported chains for Near Intents cross-chain swaps
126
- * Based on USDC/USDT support documentation
127
- */
128
- export const supportedChains: Chain[] = [
129
- // Supported for Near Intents (USDC/USDT)
130
- arbitrum, // USDC & USDT
131
- avalanche, // USDC & USDT
132
- base, // USDC only (no USDT)
133
- bsc, // USDC & USDT
134
- ethereum, // USDC & USDT
135
- gnosis, // USDC & USDT
136
- optimism, // USDC & USDT
137
- polygon, // USDC & USDT
138
- worldchain,
139
- solana,
140
- rozoSolana, // USDC & USDT (chainId: 900)
141
- rozoStellar, // USDC only (chainId: 1500, no USDT)
142
-
143
- // Not supported for Near Intents - kept for other features
144
- // celo, // Not in Near Intents docs
145
- // linea, // Not in Near Intents docs
146
- // mantle, // Not in Near Intents docs
147
- // solana, // Use rozoSolana (900) instead of solana (501)
148
- // stellar, // Use rozoStellar (1500) instead of stellar (10001)
149
- ];
150
-
151
- // https://developers.circle.com/stablecoins/supported-domains
152
- const cctpV1Chains = [
153
- arbitrum,
154
- base,
155
- ethereum,
156
- optimism,
157
- polygon,
158
- solana,
159
- rozoSolana,
160
- stellar,
161
- rozoStellar,
162
- ];
163
- const cctpV2Chains = [arbitrum, base, ethereum, linea, worldchain];
164
-
165
- /** Given a chainId, return the chain. */
166
- export function getChainById(chainId: number): Chain {
167
- const ret = supportedChains.find((c) => c.chainId === chainId);
168
- if (ret == null) throw new Error(`Unknown chainId ${chainId}`);
169
- return ret;
170
- }
171
-
172
- /** Returns the chain name for the given chainId. */
173
- export function getChainName(chainId: number): string {
174
- return getChainById(chainId).name;
175
- }
176
-
177
- /** Returns the CCTP domain for the given chainId. */
178
- export function getCCTPDomain(chainId: number): number | null {
179
- return getChainById(chainId).cctpDomain;
180
- }
181
-
182
- /** Returns true if the chain is a CCTP v1 chain. */
183
- export function isCCTPV1Chain(chainId: number): boolean {
184
- return cctpV1Chains.some((c) => c.chainId === chainId);
185
- }
186
-
187
- /** Returns true if the chain is a CCTP v2 chain. */
188
- export function isCCTPV2Chain(chainId: number): boolean {
189
- return cctpV2Chains.some((c) => c.chainId === chainId);
190
- }
191
-
192
- /**
193
- * Get block explorer URL for chain ID
194
- */
195
- export function getChainExplorerByChainId(chainId: number): string | undefined {
196
- switch (chainId) {
197
- case arbitrum.chainId:
198
- return "https://arbiscan.io";
199
- case base.chainId:
200
- return "https://basescan.org";
201
- case bsc.chainId:
202
- return "https://bscscan.com";
203
- case celo.chainId:
204
- return "https://celoscan.io";
205
- case ethereum.chainId:
206
- return "https://etherscan.io";
207
- case linea.chainId:
208
- return "https://lineascan.build";
209
- case mantle.chainId:
210
- return "https://mantlescan.xyz";
211
- case optimism.chainId:
212
- return "https://optimistic.etherscan.io";
213
- case polygon.chainId:
214
- return "https://polygonscan.com";
215
- case gnosis.chainId:
216
- return "https://gnosisscan.io";
217
- case avalanche.chainId:
218
- return "https://snowtrace.io";
219
- case solana.chainId:
220
- case rozoSolana.chainId:
221
- return "https://solscan.io";
222
- case stellar.chainId:
223
- case rozoStellar.chainId:
224
- return "https://stellar.expert/explorer/public/search?term=";
225
- case worldchain.chainId:
226
- return "https://worldscan.org";
227
- default:
228
- return undefined;
229
- }
230
- }
231
-
232
- /**
233
- * Get block explorer address URL for chain ID and address.
234
- */
235
- export function getChainExplorerAddressUrl(chainId: number, address: string) {
236
- const explorer = getChainExplorerByChainId(chainId);
237
- if (!explorer) {
238
- return undefined;
239
- }
240
- return `${explorer}/address/${address}`;
241
- }
242
-
243
- /**
244
- * Get block explorer transaction URL for chain ID and transaction hash.
245
- */
246
- export function getChainExplorerTxUrl(chainId: number, txHash: string) {
247
- const explorer = getChainExplorerByChainId(chainId);
248
- if (!explorer) {
249
- return undefined;
250
- }
251
-
252
- if ([stellar.chainId, rozoStellar.chainId].includes(chainId)) {
253
- return `${explorer}${txHash}`;
254
- }
255
-
256
- return `${explorer}/tx/${txHash}`;
257
- }
package/src/debug.ts DELETED
@@ -1,14 +0,0 @@
1
- /** Return compact JSON, 10000 chars max. Never throws. */
2
- export function debugJson(obj: any) {
3
- try {
4
- let serialized = JSON.stringify(obj, (_, value) =>
5
- typeof value === "bigint" ? value.toString() : value,
6
- );
7
- if (typeof serialized !== "string") {
8
- serialized = "" + obj;
9
- }
10
- return serialized.slice(0, 10000);
11
- } catch (e: any) {
12
- return `<JSON error: ${e.message}>`;
13
- }
14
- }