@xswap-link/sdk 0.10.8 → 0.10.10

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.
Files changed (69) hide show
  1. package/.eslintrc.json +10 -1
  2. package/CHANGELOG.md +12 -0
  3. package/dist/index.global.js +331 -331
  4. package/dist/index.js +9 -9
  5. package/dist/index.mjs +9 -9
  6. package/package.json +6 -3
  7. package/src/components/Swap/SwapView/ConfirmationView/TxOverview/index.tsx +106 -9
  8. package/src/components/Swap/SwapView/SwapButton/index.tsx +11 -11
  9. package/src/constants/index.ts +18 -0
  10. package/src/context/SwapProvider.tsx +7 -3
  11. package/src/services/api.ts +1 -0
  12. package/src/services/svm/README.md +483 -0
  13. package/src/services/svm/bindings/accounts/AllowedOfframp.ts +73 -0
  14. package/src/services/svm/bindings/accounts/Config.ts +153 -0
  15. package/src/services/svm/bindings/accounts/DestChain.ts +113 -0
  16. package/src/services/svm/bindings/accounts/Nonce.ts +97 -0
  17. package/src/services/svm/bindings/accounts/index.ts +15 -0
  18. package/src/services/svm/bindings/accounts/tokenAdminRegistry.ts +128 -0
  19. package/src/services/svm/bindings/errors/anchor.ts +773 -0
  20. package/src/services/svm/bindings/errors/custom.ts +375 -0
  21. package/src/services/svm/bindings/errors/index.ts +62 -0
  22. package/src/services/svm/bindings/instructions/ccipSend.ts +112 -0
  23. package/src/services/svm/bindings/instructions/getFee.ts +73 -0
  24. package/src/services/svm/bindings/instructions/index.ts +4 -0
  25. package/src/services/svm/bindings/programId.ts +6 -0
  26. package/src/services/svm/bindings/types/BaseChain.ts +92 -0
  27. package/src/services/svm/bindings/types/BaseConfig.ts +184 -0
  28. package/src/services/svm/bindings/types/CodeVersion.ts +88 -0
  29. package/src/services/svm/bindings/types/CrossChainAmount.ts +53 -0
  30. package/src/services/svm/bindings/types/DestChainConfig.ts +76 -0
  31. package/src/services/svm/bindings/types/DestChainState.ts +76 -0
  32. package/src/services/svm/bindings/types/GetFeeResult.ts +72 -0
  33. package/src/services/svm/bindings/types/LockOrBurnInV1.ts +102 -0
  34. package/src/services/svm/bindings/types/LockOrBurnOutV1.ts +79 -0
  35. package/src/services/svm/bindings/types/RampMessageHeader.ts +94 -0
  36. package/src/services/svm/bindings/types/RateLimitConfig.ts +72 -0
  37. package/src/services/svm/bindings/types/RateLimitTokenBucket.ts +76 -0
  38. package/src/services/svm/bindings/types/ReleaseOrMintInV1.ts +156 -0
  39. package/src/services/svm/bindings/types/ReleaseOrMintOutV1.ts +53 -0
  40. package/src/services/svm/bindings/types/RemoteAddress.ts +61 -0
  41. package/src/services/svm/bindings/types/RemoteConfig.ts +86 -0
  42. package/src/services/svm/bindings/types/RestoreOnAction.ts +120 -0
  43. package/src/services/svm/bindings/types/SVM2AnyMessage.ts +128 -0
  44. package/src/services/svm/bindings/types/SVM2AnyRampMessage.ts +166 -0
  45. package/src/services/svm/bindings/types/SVM2AnyTokenTransfer.ts +118 -0
  46. package/src/services/svm/bindings/types/SVMTokenAmount.ts +64 -0
  47. package/src/services/svm/bindings/types/index.ts +78 -0
  48. package/src/services/svm/core/client/accounts.ts +97 -0
  49. package/src/services/svm/core/client/events.ts +95 -0
  50. package/src/services/svm/core/client/fee.ts +279 -0
  51. package/src/services/svm/core/client/index.ts +150 -0
  52. package/src/services/svm/core/client/send.ts +607 -0
  53. package/src/services/svm/core/client/utils.ts +131 -0
  54. package/src/services/svm/core/models.ts +236 -0
  55. package/src/services/svm/index.ts +32 -0
  56. package/src/services/svm/utils/conversion.ts +62 -0
  57. package/src/services/svm/utils/errors.ts +51 -0
  58. package/src/services/svm/utils/keypair.ts +19 -0
  59. package/src/services/svm/utils/logger.ts +171 -0
  60. package/src/services/svm/utils/pdas/common.ts +15 -0
  61. package/src/services/svm/utils/pdas/feeQuoter.ts +68 -0
  62. package/src/services/svm/utils/pdas/index.ts +12 -0
  63. package/src/services/svm/utils/pdas/receiver.ts +58 -0
  64. package/src/services/svm/utils/pdas/rmnRemote.ts +23 -0
  65. package/src/services/svm/utils/pdas/router.ts +328 -0
  66. package/src/services/svm/utils/pdas/tokenpool.ts +161 -0
  67. package/src/services/svm/utils/transaction.ts +132 -0
  68. package/src/utils/validation.ts +7 -3
  69. package/tsconfig.json +2 -1
@@ -0,0 +1,131 @@
1
+ import { Logger } from "../../utils/logger";
2
+ import { ExtraArgsOptions } from "../models";
3
+ import { BN } from "@coral-xyz/anchor";
4
+
5
+ /**
6
+ * Creates extra arguments for CCIP send
7
+ * @param options Extra args options
8
+ * @param logger Optional logger instance
9
+ * @returns Buffer with encoded extra args
10
+ */
11
+ export function createExtraArgs(
12
+ options?: ExtraArgsOptions,
13
+ logger?: Logger
14
+ ): Buffer {
15
+ if (logger) {
16
+ logger.debug(`Creating extraArgs buffer for CCIP message`);
17
+ }
18
+
19
+ // If no options provided, create a default buffer with allowOutOfOrderExecution=true
20
+ if (!options) {
21
+ if (logger) {
22
+ logger.warn(
23
+ `No options provided, creating default extraArgs with allowOutOfOrderExecution=true to avoid error 8030`
24
+ );
25
+ }
26
+
27
+ // Use the GENERIC_EXTRA_ARGS_V2_TAG which is bytes4(keccak256("CCIP EVMExtraArgsV2"))
28
+ const typeTag = Buffer.from([0x18, 0x1d, 0xcf, 0x10]);
29
+
30
+ // Default gas limit of 0 in little-endian format (16 bytes)
31
+ const gasLimitLE = Buffer.alloc(16, 0);
32
+
33
+ // Boolean true (1) for allowOutOfOrderExecution
34
+ const allowOutOfOrderExecutionByte = Buffer.from([1]);
35
+
36
+ // Concatenate for a properly formatted default buffer
37
+ const argsData = Buffer.concat([gasLimitLE, allowOutOfOrderExecutionByte]);
38
+ const result = Buffer.concat([typeTag, argsData]);
39
+
40
+ if (logger) {
41
+ logger.trace(
42
+ `Created default extraArgs buffer with allowOutOfOrderExecution=true`
43
+ );
44
+ }
45
+
46
+ return result;
47
+ }
48
+
49
+ // Get values from options with defaults
50
+ const gasLimit = options.gasLimit || 0;
51
+
52
+ // Handle the three cases for allowOutOfOrderExecution:
53
+ // 1. Undefined - we'll use true but inform the user
54
+ // 2. Explicitly false - we'll override to true with warning
55
+ // 3. Explicitly true - we'll use it as is
56
+
57
+ let warningMessage: string | null = null;
58
+
59
+ if (options.allowOutOfOrderExecution === undefined) {
60
+ // If undefined, we'll use true but log a message about the default behavior
61
+ warningMessage = `allowOutOfOrderExecution not specified, defaulting to true to avoid FeeQuoter error 8030`;
62
+ } else if (options.allowOutOfOrderExecution === false) {
63
+ // If explicitly false, we'll override it with a warning
64
+ warningMessage = `allowOutOfOrderExecution=false was explicitly specified but is not supported by FeeQuoter. Forcing to true to avoid error 8030.`;
65
+ }
66
+
67
+ // Log warning if needed
68
+ if (warningMessage && logger) {
69
+ logger.warn(warningMessage);
70
+ }
71
+
72
+ // Always use true regardless of what was specified
73
+ const allowOutOfOrderExecution = true;
74
+
75
+ // Log what we're doing
76
+ if (logger) {
77
+ const forcedMsg =
78
+ options.allowOutOfOrderExecution === false
79
+ ? " (forced)"
80
+ : options.allowOutOfOrderExecution === undefined
81
+ ? " (default)"
82
+ : "";
83
+ logger.debug(
84
+ `ExtraArgs options - gasLimit: ${gasLimit}, allowOutOfOrderExecution: true${forcedMsg}`
85
+ );
86
+ }
87
+
88
+ // Use the GENERIC_EXTRA_ARGS_V2_TAG which is bytes4(keccak256("CCIP EVMExtraArgsV2"))
89
+ // 0x181dcf10 in big-endian format
90
+ const typeTag = Buffer.from([0x18, 0x1d, 0xcf, 0x10]);
91
+ if (logger) {
92
+ logger.trace(`Using EVM ExtraArgs V2 type tag: 0x181dcf10`);
93
+ }
94
+
95
+ // Now we need to construct the serialized version of GenericExtraArgsV2
96
+ // Based on Anchor's serialization format:
97
+ // 1. gas_limit (u128) - 16 bytes
98
+ // 2. allow_out_of_order_execution (bool) - 1 byte (1 = true, 0 = false)
99
+
100
+ // Convert gas limit to little-endian bytes (Anchor uses little endian)
101
+ const gasLimitLE = new BN(gasLimit).toArrayLike(Buffer, "le", 16);
102
+
103
+ if (logger) {
104
+ logger.trace(
105
+ `Gas limit buffer (LE, 16 bytes): 0x${gasLimitLE.toString("hex")}`
106
+ );
107
+ }
108
+
109
+ // Create bool byte for allowOutOfOrderExecution - ALWAYS true (1)
110
+ const allowOutOfOrderExecutionByte = Buffer.from([1]);
111
+
112
+ if (logger) {
113
+ logger.trace(`AllowOutOfOrderExecution byte: 0x01 (true)`);
114
+ }
115
+
116
+ // Concatenate for the data part: gasLimit (LE) + allowOutOfOrderExecution
117
+ const argsData = Buffer.concat([gasLimitLE, allowOutOfOrderExecutionByte]);
118
+
119
+ // Final buffer is tag + serialized args
120
+ const result = Buffer.concat([typeTag, argsData]);
121
+
122
+ if (logger) {
123
+ logger.trace(
124
+ `Final extraArgs buffer (${result.length} bytes): 0x${result.toString(
125
+ "hex"
126
+ )}`
127
+ );
128
+ }
129
+
130
+ return result;
131
+ }
@@ -0,0 +1,236 @@
1
+ import {
2
+ PublicKey,
3
+ Keypair,
4
+ Connection,
5
+ Transaction,
6
+ VersionedTransaction,
7
+ } from "@solana/web3.js";
8
+ import { BN } from "@coral-xyz/anchor";
9
+ import { LogLevel } from "../utils/logger";
10
+
11
+ /**
12
+ * CCIP Send Request
13
+ */
14
+ export interface CCIPSendRequest {
15
+ readonly destChainSelector: BN;
16
+ readonly receiver: Uint8Array;
17
+ readonly data: Uint8Array;
18
+ readonly tokenAmounts: {
19
+ readonly token: PublicKey;
20
+ readonly amount: BN;
21
+ }[];
22
+ readonly feeToken: PublicKey;
23
+ readonly extraArgs: Uint8Array;
24
+ }
25
+
26
+ /**
27
+ * CCIP Fee Request
28
+ */
29
+ export interface CCIPFeeRequest {
30
+ readonly destChainSelector: BN;
31
+ readonly message: {
32
+ readonly receiver: Uint8Array;
33
+ readonly data: Uint8Array;
34
+ readonly tokenAmounts: {
35
+ readonly token: PublicKey;
36
+ readonly amount: BN;
37
+ }[];
38
+ readonly feeToken: PublicKey;
39
+ readonly extraArgs: Uint8Array;
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Result of a fee calculation
45
+ */
46
+ export interface GetFeeResult {
47
+ token: PublicKey;
48
+ amount: BN;
49
+ juels: BN;
50
+ }
51
+
52
+ /**
53
+ * Result of a CCIP send with message ID
54
+ */
55
+ export interface CCIPSendResult {
56
+ txSignature: string;
57
+ messageId?: string;
58
+ destinationChainSelector?: string;
59
+ sequenceNumber?: string;
60
+ }
61
+
62
+ /**
63
+ * Extra arguments for CCIP send
64
+ */
65
+ export interface ExtraArgsV1 {
66
+ gasLimit: number;
67
+ strict: boolean;
68
+ }
69
+
70
+ /**
71
+ * Options for creating extra arguments
72
+ */
73
+ export interface ExtraArgsOptions {
74
+ gasLimit?: number;
75
+ allowOutOfOrderExecution?: boolean;
76
+ }
77
+
78
+ /**
79
+ * Options for CCIPClient configuration
80
+ */
81
+ export interface CCIPClientOptions {
82
+ /**
83
+ * Log level for the client
84
+ * @default LogLevel.INFO
85
+ */
86
+ logLevel?: LogLevel;
87
+ }
88
+
89
+ /**
90
+ * Options for sending CCIP messages
91
+ */
92
+ export interface CCIPSendOptions {
93
+ /**
94
+ * Whether to skip the preflight transaction check
95
+ * @default false
96
+ */
97
+ skipPreflight?: boolean;
98
+ }
99
+
100
+ /**
101
+ * Provider interface to abstract wallet and connection
102
+ */
103
+ export interface CCIPProvider {
104
+ /** Solana RPC connection */
105
+ connection: Connection;
106
+
107
+ /** Wallet or keypair for signing transactions */
108
+ wallet: Keypair;
109
+
110
+ /** Get the public key address of the signer */
111
+ getAddress(): PublicKey;
112
+
113
+ /** Sign a transaction */
114
+ signTransaction(
115
+ tx: Transaction | VersionedTransaction,
116
+ ): Promise<Transaction | VersionedTransaction>;
117
+ }
118
+
119
+ /**
120
+ * Core configuration needed by all CCIP modules
121
+ */
122
+ export interface CCIPCoreConfig {
123
+ /** CCIP Router program ID */
124
+ ccipRouterProgramId: PublicKey;
125
+
126
+ /** Fee Quoter program ID */
127
+ feeQuoterProgramId: PublicKey;
128
+
129
+ /** RMN Remote program ID */
130
+ rmnRemoteProgramId: PublicKey;
131
+
132
+ /** LINK token mint */
133
+ linkTokenMint: PublicKey;
134
+
135
+ /** Token mint for the application */
136
+ tokenMint: PublicKey;
137
+
138
+ /** Native SOL public key */
139
+ nativeSol: PublicKey;
140
+
141
+ /** System program ID */
142
+ systemProgramId: PublicKey;
143
+
144
+ /** CCIP receiver program ID */
145
+ programId: PublicKey;
146
+ }
147
+
148
+ /**
149
+ * Combined context with provider, config and logger
150
+ */
151
+ export interface CCIPContext {
152
+ /** Provider for connecting to the blockchain */
153
+ provider: CCIPProvider;
154
+
155
+ /** Core configuration */
156
+ config: CCIPCoreConfig;
157
+
158
+ /** Optional logger */
159
+ logger?: Logger;
160
+ }
161
+
162
+ /**
163
+ * Options for creating a CCIP client from a keypair
164
+ */
165
+ export interface CCIPClientKeypairOptions {
166
+ /** Path to keypair file */
167
+ keypairPath: string;
168
+
169
+ /** Core configuration */
170
+ config: CCIPCoreConfig;
171
+
172
+ /** Log level */
173
+ logLevel?: LogLevel;
174
+
175
+ /** RPC endpoint URL */
176
+ endpoint?: string;
177
+
178
+ /** Commitment level */
179
+ commitment?: string;
180
+ }
181
+
182
+ /**
183
+ * Logger interface imported from logger.ts
184
+ */
185
+ export interface Logger {
186
+ trace(...message: any[]): void;
187
+ debug(...message: any[]): void;
188
+ info(...message: any[]): void;
189
+ warn(...message: any[]): void;
190
+ error(...message: any[]): void;
191
+ setLevel(level: LogLevel): void;
192
+ getLevel(): LogLevel;
193
+ }
194
+
195
+ /**
196
+ * Rate limit configuration for token pools in user-friendly format
197
+ */
198
+ export interface TokenPoolRateLimitConfig {
199
+ /** Whether rate limiting is enabled */
200
+ isEnabled: boolean;
201
+ /** Maximum capacity of the rate limit bucket */
202
+ capacity: bigint;
203
+ /** Refill rate of tokens per second */
204
+ rate: bigint;
205
+ /** Last updated timestamp */
206
+ lastTxTimestamp: bigint;
207
+ /** Current number of tokens in the bucket */
208
+ currentBucketValue: bigint;
209
+ }
210
+
211
+ /**
212
+ * Chain configuration for burn-mint token pools with consistent naming
213
+ */
214
+ export interface TokenPoolChainConfigResponse {
215
+ /** Chain config account address */
216
+ address: string;
217
+ /** Base configuration data */
218
+ base: {
219
+ /** Token decimals on remote chain */
220
+ decimals: number;
221
+ /** Pool addresses on remote chain */
222
+ poolAddresses: Array<{
223
+ /** Hex encoded address */
224
+ address: string;
225
+ }>;
226
+ /** Token address on remote chain */
227
+ tokenAddress: {
228
+ /** Hex encoded address */
229
+ address: string;
230
+ };
231
+ /** Inbound rate limit configuration */
232
+ inboundRateLimit: TokenPoolRateLimitConfig;
233
+ /** Outbound rate limit configuration */
234
+ outboundRateLimit: TokenPoolRateLimitConfig;
235
+ };
236
+ }
@@ -0,0 +1,32 @@
1
+ // Core components
2
+ export * from "./core/client/accounts";
3
+ export * from "./core/client/index";
4
+
5
+ // Export models with specific names to avoid conflicts
6
+ export type {
7
+ CCIPClientOptions,
8
+ CCIPSendRequest,
9
+ CCIPSendOptions,
10
+ CCIPFeeRequest,
11
+ CCIPSendResult,
12
+ ExtraArgsOptions,
13
+ ExtraArgsV1,
14
+ CCIPProvider,
15
+ CCIPCoreConfig,
16
+ CCIPContext,
17
+ CCIPClientKeypairOptions,
18
+ } from "./core/models";
19
+
20
+ // Utilities
21
+ export * from "./utils/pdas";
22
+ export * from "./utils/logger";
23
+ export * from "./utils/errors";
24
+ export * from "./utils/conversion";
25
+ export * from "./utils/keypair";
26
+
27
+ // Bindings exports
28
+ export * from "./bindings/types";
29
+ export * from "./bindings/accounts";
30
+
31
+ // Export version
32
+ export const SDK_VERSION = "0.1.0";
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Utilities for Solana to EVM address conversion
3
+ */
4
+ export class AddressConversion {
5
+ /**
6
+ * Converts an EVM address string (0x-prefixed) into a 32-byte left-padded Uint8Array.
7
+ * Required for EVM-to-Solana compatibility in programs expecting 32-byte addresses.
8
+ * @param evmAddress EVM address (0x-prefixed)
9
+ * @returns 32-byte padded address as Uint8Array
10
+ */
11
+ static evmAddressToSolanaBytes(evmAddress: string): Uint8Array {
12
+ return this.leftPadBytes(this.hexToBytes(evmAddress), 32);
13
+ }
14
+
15
+ /**
16
+ * Pretty prints a byte array as a 0x-prefixed hex string
17
+ * @param bytes Byte array
18
+ * @returns Hex string
19
+ */
20
+ static bytesToHexString(bytes: Uint8Array): string {
21
+ return '0x' + Buffer.from(bytes).toString('hex');
22
+ }
23
+
24
+ /**
25
+ * Converts a hex string to a byte array
26
+ * @param hex Hex string
27
+ * @returns Byte array
28
+ */
29
+ private static hexToBytes(hex: string): Uint8Array {
30
+ if (hex.startsWith('0x')) hex = hex.slice(2);
31
+ if (hex.length !== 40) throw new Error('Invalid Ethereum address length');
32
+ const bytes = new Uint8Array(20);
33
+ for (let i = 0; i < 40; i += 2) {
34
+ bytes[i / 2] = parseInt(hex.slice(i, i + 2), 16);
35
+ }
36
+ return bytes;
37
+ }
38
+
39
+ /**
40
+ * Left pads a byte array to a specified length
41
+ * @param data Data to pad
42
+ * @param length Target length
43
+ * @returns Padded byte array
44
+ */
45
+ private static leftPadBytes(data: Uint8Array, length: number): Uint8Array {
46
+ if (data.length > length) throw new Error('Data too long to pad');
47
+ const padded = new Uint8Array(length);
48
+ padded.set(data, length - data.length);
49
+ return padded;
50
+ }
51
+ }
52
+
53
+ /**
54
+ * Creates a buffer from a BigInt
55
+ * @param value BigInt value
56
+ * @returns Buffer
57
+ */
58
+ export function createBufferFromBigInt(value: bigint): Buffer {
59
+ const buffer = Buffer.alloc(8);
60
+ buffer.writeBigUInt64LE(value);
61
+ return buffer;
62
+ }
@@ -0,0 +1,51 @@
1
+ import { Logger } from "./logger";
2
+
3
+ /**
4
+ * Base CCIP error class for standardized error handling
5
+ */
6
+ export class CCIPError extends Error {
7
+ constructor(message: string, public context?: Record<string, unknown>) {
8
+ super(message);
9
+ this.name = "CCIPError";
10
+ }
11
+ }
12
+
13
+ /**
14
+ * Enhances an error with additional context for better diagnostics
15
+ * @param error Original error
16
+ * @param context Additional context to add
17
+ * @param logger Optional logger instance
18
+ * @returns Enhanced error with context attached
19
+ */
20
+ export function enhanceError(
21
+ error: unknown,
22
+ context: Record<string, unknown>,
23
+ logger?: Logger
24
+ ): Error {
25
+ const enhancedError =
26
+ error instanceof Error ? error : new Error(String(error));
27
+
28
+ // Attach context to the error
29
+ (enhancedError as any).context = context;
30
+
31
+ // Log the enhanced error if a logger is provided
32
+ if (logger) {
33
+ logger.error(`Error: ${enhancedError.message}`, {
34
+ context,
35
+ stack: enhancedError.stack,
36
+ });
37
+ }
38
+
39
+ return enhancedError;
40
+ }
41
+
42
+ /**
43
+ * Creates a type-safe error enhancer bound to a specific logger instance
44
+ * @param logger Logger instance to use for error logging
45
+ * @returns A function that enhances errors with context
46
+ */
47
+ export function createErrorEnhancer(logger: Logger) {
48
+ return (error: unknown, context: Record<string, unknown>): Error => {
49
+ return enhanceError(error, context, logger);
50
+ };
51
+ }
@@ -0,0 +1,19 @@
1
+ import { Keypair } from "@solana/web3.js";
2
+
3
+ // Default file paths
4
+ export const DEFAULT_KEYPAIR_PATH = "";
5
+
6
+ /**
7
+ * Loads a keypair from a file
8
+ * @param filePath Path to keypair file
9
+ * @returns Keypair
10
+ */
11
+ export function loadKeypair(filePath: string = DEFAULT_KEYPAIR_PATH): Keypair {
12
+ try {
13
+ const keypairJson = JSON.parse("keypairData");
14
+ return Keypair.fromSecretKey(Buffer.from(keypairJson));
15
+ } catch (error) {
16
+ console.error(`Error loading keypair from ${filePath}:`, error);
17
+ throw error;
18
+ }
19
+ }
@@ -0,0 +1,171 @@
1
+ import loglevel from 'loglevel';
2
+
3
+ /**
4
+ * Log levels available in the CCIP SDK
5
+ */
6
+ export enum LogLevel {
7
+ TRACE = 0,
8
+ DEBUG = 1,
9
+ INFO = 2,
10
+ WARN = 3,
11
+ ERROR = 4,
12
+ SILENT = 5
13
+ }
14
+
15
+ /**
16
+ * SDK logging namespace prefix
17
+ */
18
+ export const NAMESPACE = 'ccip';
19
+
20
+ /**
21
+ * Logger interface with all available logging methods
22
+ */
23
+ export interface Logger {
24
+ trace(...message: any[]): void;
25
+ debug(...message: any[]): void;
26
+ info(...message: any[]): void;
27
+ warn(...message: any[]): void;
28
+ error(...message: any[]): void;
29
+ setLevel(level: LogLevel): void;
30
+ getLevel(): LogLevel;
31
+ }
32
+
33
+ /**
34
+ * Logger options for configuration
35
+ */
36
+ export interface LoggerOptions {
37
+ level?: LogLevel;
38
+ timestamps?: boolean;
39
+ }
40
+
41
+ /**
42
+ * Default logger options
43
+ */
44
+ const DEFAULT_OPTIONS: LoggerOptions = {
45
+ level: LogLevel.INFO,
46
+ timestamps: true
47
+ };
48
+
49
+ /**
50
+ * Creates a namespaced logger with the given component name
51
+ * @param component Component name to create a logger for
52
+ * @param options Logger configuration options
53
+ * @returns A configured logger instance
54
+ */
55
+ export function createLogger(component: string, options?: LoggerOptions): Logger {
56
+ const fullOptions = { ...DEFAULT_OPTIONS, ...options };
57
+ const loggerName = component ? `${NAMESPACE}:${component}` : NAMESPACE;
58
+
59
+ // Get the underlying loglevel logger
60
+ const baseLogger = loglevel.getLogger(loggerName);
61
+
62
+ // Set the initial level
63
+ baseLogger.setLevel(fullOptions.level as unknown as loglevel.LogLevelDesc);
64
+
65
+ // Create our wrapper logger with timestamps if enabled
66
+ const logger: Logger = {
67
+ trace: createLogMethod(baseLogger, 'trace', fullOptions),
68
+ debug: createLogMethod(baseLogger, 'debug', fullOptions),
69
+ info: createLogMethod(baseLogger, 'info', fullOptions),
70
+ warn: createLogMethod(baseLogger, 'warn', fullOptions),
71
+ error: createLogMethod(baseLogger, 'error', fullOptions),
72
+
73
+ setLevel(level: LogLevel) {
74
+ baseLogger.setLevel(level as unknown as loglevel.LogLevelDesc);
75
+ },
76
+
77
+ getLevel(): LogLevel {
78
+ return baseLogger.getLevel() as unknown as LogLevel;
79
+ }
80
+ };
81
+
82
+ return logger;
83
+ }
84
+
85
+ /**
86
+ * Create a log method with optional timestamp
87
+ */
88
+ function createLogMethod(
89
+ logger: loglevel.Logger,
90
+ method: 'trace' | 'debug' | 'info' | 'warn' | 'error',
91
+ options: LoggerOptions
92
+ ): (...args: any[]) => void {
93
+ return function(...args: any[]) {
94
+ // Skip logging if the current level is higher than this method's level
95
+ const methodLevel = getMethodLogLevel(method);
96
+ if (methodLevel < (logger.getLevel() as unknown as LogLevel)) {
97
+ return;
98
+ }
99
+
100
+ if (options.timestamps) {
101
+ const timestamp = new Date().toISOString();
102
+
103
+ // For trace level, customize the output to avoid showing stack traces
104
+ if (method === 'trace') {
105
+ // Format objects for better readability
106
+ const formattedArgs = args.map(arg => {
107
+ if (typeof arg === 'object' && arg !== null) {
108
+ return JSON.stringify(arg, null, 2);
109
+ }
110
+ return arg;
111
+ });
112
+
113
+ // Use console.log directly with a prefix for trace level
114
+ console.log(`TRACE: [${timestamp}]`, ...formattedArgs);
115
+ } else {
116
+ // Use loglevel for other log levels
117
+ logger[method](`[${timestamp}]`, ...args);
118
+ }
119
+ } else {
120
+ if (method === 'trace') {
121
+ // Format objects for better readability
122
+ const formattedArgs = args.map(arg => {
123
+ if (typeof arg === 'object' && arg !== null) {
124
+ return JSON.stringify(arg, null, 2);
125
+ }
126
+ return arg;
127
+ });
128
+
129
+ // Use console.log directly without timestamps
130
+ console.log(`TRACE:`, ...formattedArgs);
131
+ } else {
132
+ // Use loglevel for other log levels
133
+ logger[method](...args);
134
+ }
135
+ }
136
+ };
137
+ }
138
+
139
+ /**
140
+ * Convert method name to LogLevel enum value
141
+ */
142
+ function getMethodLogLevel(method: 'trace' | 'debug' | 'info' | 'warn' | 'error'): LogLevel {
143
+ switch (method) {
144
+ case 'trace': return LogLevel.TRACE;
145
+ case 'debug': return LogLevel.DEBUG;
146
+ case 'info': return LogLevel.INFO;
147
+ case 'warn': return LogLevel.WARN;
148
+ case 'error': return LogLevel.ERROR;
149
+ default: return LogLevel.INFO;
150
+ }
151
+ }
152
+
153
+ /**
154
+ * Root SDK logger instance
155
+ */
156
+ export const rootLogger = createLogger('');
157
+
158
+ /**
159
+ * Set the global log level for all CCIP loggers
160
+ * @param level The log level to set globally
161
+ */
162
+ export function setGlobalLogLevel(level: LogLevel): void {
163
+ loglevel.setLevel(level as unknown as loglevel.LogLevelDesc);
164
+ }
165
+
166
+ /**
167
+ * Reset all loggers to their default levels
168
+ */
169
+ export function resetLoggers(): void {
170
+ loglevel.setDefaultLevel(loglevel.levels.INFO);
171
+ }