@circle-fin/bridge-kit 1.4.0 → 1.5.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @circle-fin/bridge-kit
2
2
 
3
+ ## 1.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **Monad support**: Bridge Kit now supports Monad mainnet and testnet. You can include Monad in cross-chain USDC transfer flows without additional configuration or changes to existing integrations.
8
+
9
+ - **Automatic re-attestation for fast transfers**: When retrying a failed CCTP v2 fast transfer, the kit now automatically detects if the mint failed due to an expired attestation and triggers re-attestation. This eliminates manual intervention when attestations expire before the mint transaction completes.
10
+
3
11
  ## 1.4.0
4
12
 
5
13
  ### Minor Changes
package/QUICKSTART.md CHANGED
@@ -273,7 +273,7 @@ const adapter = createViemAdapterFromPrivateKey({
273
273
  createPublicClient({
274
274
  chain,
275
275
  transport: http(
276
- `https://eth-mainnet.alchemyapi.io/v2/${process.env.ALCHEMY_KEY}`,
276
+ `https://eth-mainnet.g.alchemy.com/v2/${process.env.ALCHEMY_KEY}`,
277
277
  {
278
278
  retryCount: 3,
279
279
  timeout: 10000,
@@ -1150,7 +1150,7 @@ import { mainnet } from 'viem/chains'
1150
1150
  const publicClient = createPublicClient({
1151
1151
  chain: mainnet,
1152
1152
  transport: fallback([
1153
- http('https://eth-mainnet.alchemyapi.io/v2/your-key'),
1153
+ http('https://eth-mainnet.g.alchemy.com/v2/your-key'),
1154
1154
  http('https://mainnet.infura.io/v3/your-key'),
1155
1155
  http(), // Default public RPC as fallback
1156
1156
  ]),
package/README.md CHANGED
@@ -72,9 +72,9 @@ The Bridge Kit enables cross-chain stablecoin transfers via a type-safe, develop
72
72
  - **🔧 Bring your own infrastructure**: Seamlessly integrate with your existing setup when needed
73
73
  - **🔒 Production-ready security**: Leverages Circle's CCTPv2 with deterministic quotes and finality tracking
74
74
  - **🚀 Developer experience**: Complete TypeScript support, comprehensive validation, and instant connectivity
75
- - **🌍 Cross-chain bridging**: The Bridge Kit supports **34 chains** with **544 total bridge routes** through Circle's CCTPv2
76
- - **Mainnet (17 chains)**: Arbitrum, Avalanche, Base, Codex, Ethereum, HyperEVM, Ink, Linea, OP Mainnet, Plume, Polygon PoS, Sei, Solana, Sonic, Unichain, World Chain, XDC
77
- - **Testnet (17 chains)**: Arbitrum Sepolia, Avalanche Fuji, Base Sepolia, Codex Testnet, Ethereum Sepolia, HyperEVM Testnet, Ink Testnet, Linea Sepolia, OP Sepolia, Plume Testnet, Polygon PoS Amoy, Sei Testnet, Solana Devnet, Sonic Testnet, Unichain Sepolia, World Chain Sepolia, XDC Apothem
75
+ - **🌍 Cross-chain bridging**: The Bridge Kit supports **37 chains** with **666 total bridge routes** through Circle's CCTPv2
76
+ - **Mainnet (18 chains)**: Arbitrum, Avalanche, Base, Codex, Ethereum, HyperEVM, Ink, Linea, Monad, OP Mainnet, Plume, Polygon PoS, Sei, Solana, Sonic, Unichain, World Chain, XDC
77
+ - **Testnet (19 chains)**: Arc Testnet, Arbitrum Sepolia, Avalanche Fuji, Base Sepolia, Codex Testnet, Ethereum Sepolia, HyperEVM Testnet, Ink Testnet, Linea Sepolia, Monad Testnet, OP Sepolia, Plume Testnet, Polygon PoS Amoy, Sei Testnet, Solana Devnet, Sonic Testnet, Unichain Sepolia, World Chain Sepolia, XDC Apothem
78
78
  - **🎯 Flexible adapters**: Supporting EVM (Viem, Ethers) and Solana (@solana/web3)
79
79
  - **⚙️ Configurable bridge speeds**: FAST/SLOW options with fee optimization
80
80
  - **📡 Real-time event monitoring**: Track progress throughout the transfer lifecycle
package/chains.cjs CHANGED
@@ -62,6 +62,8 @@ var Blockchain;
62
62
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
63
63
  Blockchain["Linea"] = "Linea";
64
64
  Blockchain["Linea_Sepolia"] = "Linea_Sepolia";
65
+ Blockchain["Monad"] = "Monad";
66
+ Blockchain["Monad_Testnet"] = "Monad_Testnet";
65
67
  Blockchain["NEAR"] = "NEAR";
66
68
  Blockchain["NEAR_Testnet"] = "NEAR_Testnet";
67
69
  Blockchain["Noble"] = "Noble";
@@ -153,6 +155,7 @@ exports.BridgeChain = void 0;
153
155
  BridgeChain["HyperEVM"] = "HyperEVM";
154
156
  BridgeChain["Ink"] = "Ink";
155
157
  BridgeChain["Linea"] = "Linea";
158
+ BridgeChain["Monad"] = "Monad";
156
159
  BridgeChain["Optimism"] = "Optimism";
157
160
  BridgeChain["Plume"] = "Plume";
158
161
  BridgeChain["Polygon"] = "Polygon";
@@ -172,6 +175,7 @@ exports.BridgeChain = void 0;
172
175
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
173
176
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
174
177
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
178
+ BridgeChain["Monad_Testnet"] = "Monad_Testnet";
175
179
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
176
180
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
177
181
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
@@ -1158,6 +1162,86 @@ const LineaSepolia = defineChain({
1158
1162
  },
1159
1163
  });
1160
1164
 
1165
+ /**
1166
+ * Monad Mainnet chain definition
1167
+ * @remarks
1168
+ * This represents the official production network for the Monad blockchain.
1169
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1170
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1171
+ */
1172
+ const Monad = defineChain({
1173
+ type: 'evm',
1174
+ chain: Blockchain.Monad,
1175
+ name: 'Monad',
1176
+ title: 'Monad Mainnet',
1177
+ nativeCurrency: {
1178
+ name: 'Monad',
1179
+ symbol: 'MON',
1180
+ decimals: 18,
1181
+ },
1182
+ chainId: 143,
1183
+ isTestnet: false,
1184
+ explorerUrl: 'https://monadscan.com/tx/{hash}',
1185
+ rpcEndpoints: ['https://rpc.monad.xyz'],
1186
+ eurcAddress: null,
1187
+ usdcAddress: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
1188
+ cctp: {
1189
+ domain: 15,
1190
+ contracts: {
1191
+ v2: {
1192
+ type: 'split',
1193
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
1194
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
1195
+ confirmations: 1,
1196
+ fastConfirmations: 1,
1197
+ },
1198
+ },
1199
+ },
1200
+ kitContracts: {
1201
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
1202
+ },
1203
+ });
1204
+
1205
+ /**
1206
+ * Monad Testnet chain definition
1207
+ * @remarks
1208
+ * This represents the official test network for the Monad blockchain.
1209
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1210
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1211
+ */
1212
+ const MonadTestnet = defineChain({
1213
+ type: 'evm',
1214
+ chain: Blockchain.Monad_Testnet,
1215
+ name: 'Monad Testnet',
1216
+ title: 'Monad Testnet',
1217
+ nativeCurrency: {
1218
+ name: 'Monad',
1219
+ symbol: 'MON',
1220
+ decimals: 18,
1221
+ },
1222
+ chainId: 10143,
1223
+ isTestnet: true,
1224
+ explorerUrl: 'https://testnet.monadscan.com/tx/{hash}',
1225
+ rpcEndpoints: ['https://testnet-rpc.monad.xyz'],
1226
+ eurcAddress: null,
1227
+ usdcAddress: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
1228
+ cctp: {
1229
+ domain: 15,
1230
+ contracts: {
1231
+ v2: {
1232
+ type: 'split',
1233
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
1234
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
1235
+ confirmations: 1,
1236
+ fastConfirmations: 1,
1237
+ },
1238
+ },
1239
+ },
1240
+ kitContracts: {
1241
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
1242
+ },
1243
+ });
1244
+
1161
1245
  /**
1162
1246
  * NEAR Protocol Mainnet chain definition
1163
1247
  * @remarks
@@ -2419,6 +2503,8 @@ exports.Ink = Ink;
2419
2503
  exports.InkTestnet = InkTestnet;
2420
2504
  exports.Linea = Linea;
2421
2505
  exports.LineaSepolia = LineaSepolia;
2506
+ exports.Monad = Monad;
2507
+ exports.MonadTestnet = MonadTestnet;
2422
2508
  exports.Optimism = Optimism;
2423
2509
  exports.OptimismSepolia = OptimismSepolia;
2424
2510
  exports.Plume = Plume;
package/chains.d.ts CHANGED
@@ -54,6 +54,8 @@ declare enum Blockchain {
54
54
  Ink_Testnet = "Ink_Testnet",
55
55
  Linea = "Linea",
56
56
  Linea_Sepolia = "Linea_Sepolia",
57
+ Monad = "Monad",
58
+ Monad_Testnet = "Monad_Testnet",
57
59
  NEAR = "NEAR",
58
60
  NEAR_Testnet = "NEAR_Testnet",
59
61
  Noble = "Noble",
@@ -140,6 +142,7 @@ declare enum BridgeChain {
140
142
  HyperEVM = "HyperEVM",
141
143
  Ink = "Ink",
142
144
  Linea = "Linea",
145
+ Monad = "Monad",
143
146
  Optimism = "Optimism",
144
147
  Plume = "Plume",
145
148
  Polygon = "Polygon",
@@ -158,6 +161,7 @@ declare enum BridgeChain {
158
161
  HyperEVM_Testnet = "HyperEVM_Testnet",
159
162
  Ink_Testnet = "Ink_Testnet",
160
163
  Linea_Sepolia = "Linea_Sepolia",
164
+ Monad_Testnet = "Monad_Testnet",
161
165
  Optimism_Sepolia = "Optimism_Sepolia",
162
166
  Plume_Testnet = "Plume_Testnet",
163
167
  Polygon_Amoy_Testnet = "Polygon_Amoy_Testnet",
@@ -873,6 +877,86 @@ declare const LineaSepolia: {
873
877
  };
874
878
  };
875
879
 
880
+ /**
881
+ * Monad Mainnet chain definition
882
+ * @remarks
883
+ * This represents the official production network for the Monad blockchain.
884
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
885
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
886
+ */
887
+ declare const Monad: {
888
+ readonly type: "evm";
889
+ readonly chain: Blockchain.Monad;
890
+ readonly name: "Monad";
891
+ readonly title: "Monad Mainnet";
892
+ readonly nativeCurrency: {
893
+ readonly name: "Monad";
894
+ readonly symbol: "MON";
895
+ readonly decimals: 18;
896
+ };
897
+ readonly chainId: 143;
898
+ readonly isTestnet: false;
899
+ readonly explorerUrl: "https://monadscan.com/tx/{hash}";
900
+ readonly rpcEndpoints: readonly ["https://rpc.monad.xyz"];
901
+ readonly eurcAddress: null;
902
+ readonly usdcAddress: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603";
903
+ readonly cctp: {
904
+ readonly domain: 15;
905
+ readonly contracts: {
906
+ readonly v2: {
907
+ readonly type: "split";
908
+ readonly tokenMessenger: "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
909
+ readonly messageTransmitter: "0x81D40F21F12A8F0E3252Bccb954D722d4c464B64";
910
+ readonly confirmations: 1;
911
+ readonly fastConfirmations: 1;
912
+ };
913
+ };
914
+ };
915
+ readonly kitContracts: {
916
+ readonly bridge: "0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0";
917
+ };
918
+ };
919
+
920
+ /**
921
+ * Monad Testnet chain definition
922
+ * @remarks
923
+ * This represents the official test network for the Monad blockchain.
924
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
925
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
926
+ */
927
+ declare const MonadTestnet: {
928
+ readonly type: "evm";
929
+ readonly chain: Blockchain.Monad_Testnet;
930
+ readonly name: "Monad Testnet";
931
+ readonly title: "Monad Testnet";
932
+ readonly nativeCurrency: {
933
+ readonly name: "Monad";
934
+ readonly symbol: "MON";
935
+ readonly decimals: 18;
936
+ };
937
+ readonly chainId: 10143;
938
+ readonly isTestnet: true;
939
+ readonly explorerUrl: "https://testnet.monadscan.com/tx/{hash}";
940
+ readonly rpcEndpoints: readonly ["https://testnet-rpc.monad.xyz"];
941
+ readonly eurcAddress: null;
942
+ readonly usdcAddress: "0x534b2f3A21130d7a60830c2Df862319e593943A3";
943
+ readonly cctp: {
944
+ readonly domain: 15;
945
+ readonly contracts: {
946
+ readonly v2: {
947
+ readonly type: "split";
948
+ readonly tokenMessenger: "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA";
949
+ readonly messageTransmitter: "0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275";
950
+ readonly confirmations: 1;
951
+ readonly fastConfirmations: 1;
952
+ };
953
+ };
954
+ };
955
+ readonly kitContracts: {
956
+ readonly bridge: "0xC5567a5E3370d4DBfB0540025078e283e36A363d";
957
+ };
958
+ };
959
+
876
960
  /**
877
961
  * Optimism Mainnet chain definition
878
962
  * @remarks
@@ -1611,4 +1695,4 @@ declare const XDCApothem: {
1611
1695
  };
1612
1696
  };
1613
1697
 
1614
- export { Arbitrum, ArbitrumSepolia, ArcTestnet, Avalanche, AvalancheFuji, Base, BaseSepolia, BridgeChain, Codex, CodexTestnet, Ethereum, EthereumSepolia, HyperEVM, HyperEVMTestnet, Ink, InkTestnet, Linea, LineaSepolia, Optimism, OptimismSepolia, Plume, PlumeTestnet, Polygon, PolygonAmoy, Sei, SeiTestnet, Solana, SolanaDevnet, Sonic, SonicTestnet, Unichain, UnichainSepolia, WorldChain, WorldChainSepolia, XDC, XDCApothem };
1698
+ export { Arbitrum, ArbitrumSepolia, ArcTestnet, Avalanche, AvalancheFuji, Base, BaseSepolia, BridgeChain, Codex, CodexTestnet, Ethereum, EthereumSepolia, HyperEVM, HyperEVMTestnet, Ink, InkTestnet, Linea, LineaSepolia, Monad, MonadTestnet, Optimism, OptimismSepolia, Plume, PlumeTestnet, Polygon, PolygonAmoy, Sei, SeiTestnet, Solana, SolanaDevnet, Sonic, SonicTestnet, Unichain, UnichainSepolia, WorldChain, WorldChainSepolia, XDC, XDCApothem };
package/chains.mjs CHANGED
@@ -60,6 +60,8 @@ var Blockchain;
60
60
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
61
61
  Blockchain["Linea"] = "Linea";
62
62
  Blockchain["Linea_Sepolia"] = "Linea_Sepolia";
63
+ Blockchain["Monad"] = "Monad";
64
+ Blockchain["Monad_Testnet"] = "Monad_Testnet";
63
65
  Blockchain["NEAR"] = "NEAR";
64
66
  Blockchain["NEAR_Testnet"] = "NEAR_Testnet";
65
67
  Blockchain["Noble"] = "Noble";
@@ -151,6 +153,7 @@ var BridgeChain;
151
153
  BridgeChain["HyperEVM"] = "HyperEVM";
152
154
  BridgeChain["Ink"] = "Ink";
153
155
  BridgeChain["Linea"] = "Linea";
156
+ BridgeChain["Monad"] = "Monad";
154
157
  BridgeChain["Optimism"] = "Optimism";
155
158
  BridgeChain["Plume"] = "Plume";
156
159
  BridgeChain["Polygon"] = "Polygon";
@@ -170,6 +173,7 @@ var BridgeChain;
170
173
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
171
174
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
172
175
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
176
+ BridgeChain["Monad_Testnet"] = "Monad_Testnet";
173
177
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
174
178
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
175
179
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
@@ -1156,6 +1160,86 @@ const LineaSepolia = defineChain({
1156
1160
  },
1157
1161
  });
1158
1162
 
1163
+ /**
1164
+ * Monad Mainnet chain definition
1165
+ * @remarks
1166
+ * This represents the official production network for the Monad blockchain.
1167
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1168
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1169
+ */
1170
+ const Monad = defineChain({
1171
+ type: 'evm',
1172
+ chain: Blockchain.Monad,
1173
+ name: 'Monad',
1174
+ title: 'Monad Mainnet',
1175
+ nativeCurrency: {
1176
+ name: 'Monad',
1177
+ symbol: 'MON',
1178
+ decimals: 18,
1179
+ },
1180
+ chainId: 143,
1181
+ isTestnet: false,
1182
+ explorerUrl: 'https://monadscan.com/tx/{hash}',
1183
+ rpcEndpoints: ['https://rpc.monad.xyz'],
1184
+ eurcAddress: null,
1185
+ usdcAddress: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
1186
+ cctp: {
1187
+ domain: 15,
1188
+ contracts: {
1189
+ v2: {
1190
+ type: 'split',
1191
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
1192
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
1193
+ confirmations: 1,
1194
+ fastConfirmations: 1,
1195
+ },
1196
+ },
1197
+ },
1198
+ kitContracts: {
1199
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
1200
+ },
1201
+ });
1202
+
1203
+ /**
1204
+ * Monad Testnet chain definition
1205
+ * @remarks
1206
+ * This represents the official test network for the Monad blockchain.
1207
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1208
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1209
+ */
1210
+ const MonadTestnet = defineChain({
1211
+ type: 'evm',
1212
+ chain: Blockchain.Monad_Testnet,
1213
+ name: 'Monad Testnet',
1214
+ title: 'Monad Testnet',
1215
+ nativeCurrency: {
1216
+ name: 'Monad',
1217
+ symbol: 'MON',
1218
+ decimals: 18,
1219
+ },
1220
+ chainId: 10143,
1221
+ isTestnet: true,
1222
+ explorerUrl: 'https://testnet.monadscan.com/tx/{hash}',
1223
+ rpcEndpoints: ['https://testnet-rpc.monad.xyz'],
1224
+ eurcAddress: null,
1225
+ usdcAddress: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
1226
+ cctp: {
1227
+ domain: 15,
1228
+ contracts: {
1229
+ v2: {
1230
+ type: 'split',
1231
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
1232
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
1233
+ confirmations: 1,
1234
+ fastConfirmations: 1,
1235
+ },
1236
+ },
1237
+ },
1238
+ kitContracts: {
1239
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
1240
+ },
1241
+ });
1242
+
1159
1243
  /**
1160
1244
  * NEAR Protocol Mainnet chain definition
1161
1245
  * @remarks
@@ -2400,5 +2484,5 @@ z.union([
2400
2484
  })),
2401
2485
  ]);
2402
2486
 
2403
- export { Arbitrum, ArbitrumSepolia, ArcTestnet, Avalanche, AvalancheFuji, Base, BaseSepolia, BridgeChain, Codex, CodexTestnet, Ethereum, EthereumSepolia, HyperEVM, HyperEVMTestnet, Ink, InkTestnet, Linea, LineaSepolia, Optimism, OptimismSepolia, Plume, PlumeTestnet, Polygon, PolygonAmoy, Sei, SeiTestnet, Solana, SolanaDevnet, Sonic, SonicTestnet, Unichain, UnichainSepolia, WorldChain, WorldChainSepolia, XDC, XDCApothem };
2487
+ export { Arbitrum, ArbitrumSepolia, ArcTestnet, Avalanche, AvalancheFuji, Base, BaseSepolia, BridgeChain, Codex, CodexTestnet, Ethereum, EthereumSepolia, HyperEVM, HyperEVMTestnet, Ink, InkTestnet, Linea, LineaSepolia, Monad, MonadTestnet, Optimism, OptimismSepolia, Plume, PlumeTestnet, Polygon, PolygonAmoy, Sei, SeiTestnet, Solana, SolanaDevnet, Sonic, SonicTestnet, Unichain, UnichainSepolia, WorldChain, WorldChainSepolia, XDC, XDCApothem };
2404
2488
  //# sourceMappingURL=chains.mjs.map
package/index.cjs CHANGED
@@ -122,6 +122,8 @@ const ERROR_TYPES = {
122
122
  RPC: 'RPC',
123
123
  /** Internet connectivity, DNS resolution, connection issues */
124
124
  NETWORK: 'NETWORK',
125
+ /** Catch-all for unrecognized errors (code 0) */
126
+ UNKNOWN: 'UNKNOWN',
125
127
  };
126
128
  /**
127
129
  * Array of valid error type values for validation.
@@ -135,6 +137,8 @@ const ERROR_TYPE_ARRAY = [...ERROR_TYPE_VALUES];
135
137
  /**
136
138
  * Error code ranges for validation.
137
139
  * Single source of truth for valid error code ranges.
140
+ *
141
+ * Note: Code 0 is special - it's the UNKNOWN catch-all error.
138
142
  */
139
143
  const ERROR_CODE_RANGES = [
140
144
  { min: 1000, max: 1999, type: 'INPUT' },
@@ -143,6 +147,8 @@ const ERROR_CODE_RANGES = [
143
147
  { min: 5000, max: 5999, type: 'ONCHAIN' },
144
148
  { min: 9000, max: 9999, type: 'BALANCE' },
145
149
  ];
150
+ /** Special code for UNKNOWN errors */
151
+ const UNKNOWN_ERROR_CODE = 0;
146
152
  /**
147
153
  * Zod schema for validating ErrorDetails objects.
148
154
  *
@@ -181,6 +187,7 @@ const ERROR_CODE_RANGES = [
181
187
  const errorDetailsSchema = zod.z.object({
182
188
  /**
183
189
  * Numeric identifier following standardized ranges:
190
+ * - 0: UNKNOWN - Catch-all for unrecognized errors
184
191
  * - 1000-1999: INPUT errors - Parameter validation
185
192
  * - 3000-3999: NETWORK errors - Connectivity issues
186
193
  * - 4000-4999: RPC errors - Provider issues, gas estimation
@@ -190,8 +197,9 @@ const errorDetailsSchema = zod.z.object({
190
197
  code: zod.z
191
198
  .number()
192
199
  .int('Error code must be an integer')
193
- .refine((code) => ERROR_CODE_RANGES.some((range) => code >= range.min && code <= range.max), {
194
- message: 'Error code must be in valid ranges: 1000-1999 (INPUT), 3000-3999 (NETWORK), 4000-4999 (RPC), 5000-5999 (ONCHAIN), 9000-9999 (BALANCE)',
200
+ .refine((code) => code === UNKNOWN_ERROR_CODE ||
201
+ ERROR_CODE_RANGES.some((range) => code >= range.min && code <= range.max), {
202
+ message: 'Error code must be 0 (UNKNOWN) or in valid ranges: 1000-1999 (INPUT), 3000-3999 (NETWORK), 4000-4999 (RPC), 5000-5999 (ONCHAIN), 9000-9999 (BALANCE)',
195
203
  }),
196
204
  /** Human-readable ID (e.g., "INPUT_NETWORK_MISMATCH", "BALANCE_INSUFFICIENT_TOKEN") */
197
205
  name: zod.z
@@ -201,7 +209,7 @@ const errorDetailsSchema = zod.z.object({
201
209
  /** Error category indicating where the error originated */
202
210
  type: zod.z.enum(ERROR_TYPE_ARRAY, {
203
211
  errorMap: () => ({
204
- message: 'Error type must be one of: INPUT, BALANCE, ONCHAIN, RPC, NETWORK',
212
+ message: 'Error type must be one of: INPUT, BALANCE, ONCHAIN, RPC, NETWORK, UNKNOWN',
205
213
  }),
206
214
  }),
207
215
  /** Error handling strategy */
@@ -418,6 +426,7 @@ class KitError extends Error {
418
426
  /**
419
427
  * Standardized error code ranges for consistent categorization:
420
428
  *
429
+ * - 0: UNKNOWN - Catch-all for unrecognized errors
421
430
  * - 1000-1999: INPUT errors - Parameter validation, input format errors
422
431
  * - 3000-3999: NETWORK errors - Internet connectivity, DNS, connection issues
423
432
  * - 4000-4999: RPC errors - Blockchain provider issues, gas estimation, nonce errors
@@ -966,6 +975,8 @@ exports.Blockchain = void 0;
966
975
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
967
976
  Blockchain["Linea"] = "Linea";
968
977
  Blockchain["Linea_Sepolia"] = "Linea_Sepolia";
978
+ Blockchain["Monad"] = "Monad";
979
+ Blockchain["Monad_Testnet"] = "Monad_Testnet";
969
980
  Blockchain["NEAR"] = "NEAR";
970
981
  Blockchain["NEAR_Testnet"] = "NEAR_Testnet";
971
982
  Blockchain["Noble"] = "Noble";
@@ -1057,6 +1068,7 @@ exports.BridgeChain = void 0;
1057
1068
  BridgeChain["HyperEVM"] = "HyperEVM";
1058
1069
  BridgeChain["Ink"] = "Ink";
1059
1070
  BridgeChain["Linea"] = "Linea";
1071
+ BridgeChain["Monad"] = "Monad";
1060
1072
  BridgeChain["Optimism"] = "Optimism";
1061
1073
  BridgeChain["Plume"] = "Plume";
1062
1074
  BridgeChain["Polygon"] = "Polygon";
@@ -1076,6 +1088,7 @@ exports.BridgeChain = void 0;
1076
1088
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1077
1089
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
1078
1090
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
1091
+ BridgeChain["Monad_Testnet"] = "Monad_Testnet";
1079
1092
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
1080
1093
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
1081
1094
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
@@ -2062,6 +2075,86 @@ const LineaSepolia = defineChain({
2062
2075
  },
2063
2076
  });
2064
2077
 
2078
+ /**
2079
+ * Monad Mainnet chain definition
2080
+ * @remarks
2081
+ * This represents the official production network for the Monad blockchain.
2082
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
2083
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
2084
+ */
2085
+ const Monad = defineChain({
2086
+ type: 'evm',
2087
+ chain: exports.Blockchain.Monad,
2088
+ name: 'Monad',
2089
+ title: 'Monad Mainnet',
2090
+ nativeCurrency: {
2091
+ name: 'Monad',
2092
+ symbol: 'MON',
2093
+ decimals: 18,
2094
+ },
2095
+ chainId: 143,
2096
+ isTestnet: false,
2097
+ explorerUrl: 'https://monadscan.com/tx/{hash}',
2098
+ rpcEndpoints: ['https://rpc.monad.xyz'],
2099
+ eurcAddress: null,
2100
+ usdcAddress: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
2101
+ cctp: {
2102
+ domain: 15,
2103
+ contracts: {
2104
+ v2: {
2105
+ type: 'split',
2106
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
2107
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
2108
+ confirmations: 1,
2109
+ fastConfirmations: 1,
2110
+ },
2111
+ },
2112
+ },
2113
+ kitContracts: {
2114
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
2115
+ },
2116
+ });
2117
+
2118
+ /**
2119
+ * Monad Testnet chain definition
2120
+ * @remarks
2121
+ * This represents the official test network for the Monad blockchain.
2122
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
2123
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
2124
+ */
2125
+ const MonadTestnet = defineChain({
2126
+ type: 'evm',
2127
+ chain: exports.Blockchain.Monad_Testnet,
2128
+ name: 'Monad Testnet',
2129
+ title: 'Monad Testnet',
2130
+ nativeCurrency: {
2131
+ name: 'Monad',
2132
+ symbol: 'MON',
2133
+ decimals: 18,
2134
+ },
2135
+ chainId: 10143,
2136
+ isTestnet: true,
2137
+ explorerUrl: 'https://testnet.monadscan.com/tx/{hash}',
2138
+ rpcEndpoints: ['https://testnet-rpc.monad.xyz'],
2139
+ eurcAddress: null,
2140
+ usdcAddress: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
2141
+ cctp: {
2142
+ domain: 15,
2143
+ contracts: {
2144
+ v2: {
2145
+ type: 'split',
2146
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
2147
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
2148
+ confirmations: 1,
2149
+ fastConfirmations: 1,
2150
+ },
2151
+ },
2152
+ },
2153
+ kitContracts: {
2154
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
2155
+ },
2156
+ });
2157
+
2065
2158
  /**
2066
2159
  * NEAR Protocol Mainnet chain definition
2067
2160
  * @remarks
@@ -3146,6 +3239,8 @@ var Blockchains = {
3146
3239
  InkTestnet: InkTestnet,
3147
3240
  Linea: Linea,
3148
3241
  LineaSepolia: LineaSepolia,
3242
+ Monad: Monad,
3243
+ MonadTestnet: MonadTestnet,
3149
3244
  NEAR: NEAR,
3150
3245
  NEARTestnet: NEARTestnet,
3151
3246
  Noble: Noble,
@@ -3557,14 +3652,41 @@ function isFatalError(error) {
3557
3652
  return isKitError(error) && error.recoverability === 'FATAL';
3558
3653
  }
3559
3654
  /**
3560
- * Checks if an error is a KitError with RETRYABLE recoverability.
3655
+ * Error codes that are considered retryable by default.
3656
+ *
3657
+ * @remarks
3658
+ * These are typically transient errors that may succeed on retry:
3659
+ * - Network connectivity issues (3001, 3002)
3660
+ * - Provider unavailability (4001, 4002)
3661
+ * - RPC nonce errors (4003)
3662
+ */
3663
+ const DEFAULT_RETRYABLE_ERROR_CODES = [
3664
+ // Network errors
3665
+ 3001, // NETWORK_CONNECTION_FAILED
3666
+ 3002, // NETWORK_TIMEOUT
3667
+ // Provider errors
3668
+ 4001, // PROVIDER_UNAVAILABLE
3669
+ 4002, // PROVIDER_TIMEOUT
3670
+ 4003, // RPC_NONCE_ERROR
3671
+ ];
3672
+ /**
3673
+ * Checks if an error is retryable.
3674
+ *
3675
+ * @remarks
3676
+ * Check order for KitError instances:
3677
+ * 1. If `recoverability === 'RETRYABLE'`, return `true` immediately (priority check).
3678
+ * 2. Otherwise, check if `error.code` is in `DEFAULT_RETRYABLE_ERROR_CODES` (fallback check).
3679
+ * 3. Non-KitError instances always return `false`.
3680
+ *
3681
+ * This two-tier approach allows both explicit recoverability control and
3682
+ * backward-compatible code-based retry logic.
3561
3683
  *
3562
3684
  * RETRYABLE errors indicate transient failures that may succeed on
3563
3685
  * subsequent attempts, such as network timeouts or temporary service
3564
3686
  * unavailability. These errors are safe to retry after a delay.
3565
3687
  *
3566
3688
  * @param error - Unknown error to check
3567
- * @returns True if error is a KitError with RETRYABLE recoverability
3689
+ * @returns True if error is retryable
3568
3690
  *
3569
3691
  * @example
3570
3692
  * ```typescript
@@ -3579,9 +3701,51 @@ function isFatalError(error) {
3579
3701
  * }
3580
3702
  * }
3581
3703
  * ```
3704
+ *
3705
+ * @example
3706
+ * ```typescript
3707
+ * import { isRetryableError, createNetworkConnectionError, KitError } from '@core/errors'
3708
+ *
3709
+ * // KitError with RETRYABLE recoverability (priority check)
3710
+ * const error1 = createNetworkConnectionError('Ethereum')
3711
+ * isRetryableError(error1) // true
3712
+ *
3713
+ * // KitError with default retryable code (fallback check)
3714
+ * const error2 = new KitError({
3715
+ * code: 3002, // NETWORK_TIMEOUT - in DEFAULT_RETRYABLE_ERROR_CODES
3716
+ * name: 'NETWORK_TIMEOUT',
3717
+ * type: 'NETWORK',
3718
+ * recoverability: 'FATAL', // Not RETRYABLE
3719
+ * message: 'Timeout',
3720
+ * })
3721
+ * isRetryableError(error2) // true (code 3002 is in default list)
3722
+ *
3723
+ * // KitError with non-retryable code and FATAL recoverability
3724
+ * const error3 = new KitError({
3725
+ * code: 1001,
3726
+ * name: 'INVALID_INPUT',
3727
+ * type: 'INPUT',
3728
+ * recoverability: 'FATAL',
3729
+ * message: 'Invalid input',
3730
+ * })
3731
+ * isRetryableError(error3) // false
3732
+ *
3733
+ * // Non-KitError
3734
+ * const error4 = new Error('Standard error')
3735
+ * isRetryableError(error4) // false
3736
+ * ```
3582
3737
  */
3583
3738
  function isRetryableError(error) {
3584
- return isKitError(error) && error.recoverability === 'RETRYABLE';
3739
+ // Use proper type guard to check if it's a KitError
3740
+ if (isKitError(error)) {
3741
+ // Priority check: explicit recoverability
3742
+ if (error.recoverability === 'RETRYABLE') {
3743
+ return true;
3744
+ }
3745
+ // Fallback check: error code against default retryable codes
3746
+ return DEFAULT_RETRYABLE_ERROR_CODES.includes(error.code);
3747
+ }
3748
+ return false;
3585
3749
  }
3586
3750
  /**
3587
3751
  * Type guard to check if error is KitError with INPUT type.
@@ -4639,7 +4803,7 @@ const parseAmount = (params) => {
4639
4803
  };
4640
4804
 
4641
4805
  var name = "@circle-fin/bridge-kit";
4642
- var version = "1.4.0";
4806
+ var version = "1.5.0";
4643
4807
  var pkg = {
4644
4808
  name: name,
4645
4809
  version: version};
package/index.d.ts CHANGED
@@ -437,6 +437,8 @@ declare enum Blockchain {
437
437
  Ink_Testnet = "Ink_Testnet",
438
438
  Linea = "Linea",
439
439
  Linea_Sepolia = "Linea_Sepolia",
440
+ Monad = "Monad",
441
+ Monad_Testnet = "Monad_Testnet",
440
442
  NEAR = "NEAR",
441
443
  NEAR_Testnet = "NEAR_Testnet",
442
444
  Noble = "Noble",
@@ -523,6 +525,7 @@ declare enum BridgeChain {
523
525
  HyperEVM = "HyperEVM",
524
526
  Ink = "Ink",
525
527
  Linea = "Linea",
528
+ Monad = "Monad",
526
529
  Optimism = "Optimism",
527
530
  Plume = "Plume",
528
531
  Polygon = "Polygon",
@@ -541,6 +544,7 @@ declare enum BridgeChain {
541
544
  HyperEVM_Testnet = "HyperEVM_Testnet",
542
545
  Ink_Testnet = "Ink_Testnet",
543
546
  Linea_Sepolia = "Linea_Sepolia",
547
+ Monad_Testnet = "Monad_Testnet",
544
548
  Optimism_Sepolia = "Optimism_Sepolia",
545
549
  Plume_Testnet = "Plume_Testnet",
546
550
  Polygon_Amoy_Testnet = "Polygon_Amoy_Testnet",
@@ -1491,6 +1495,86 @@ declare const LineaSepolia: {
1491
1495
  };
1492
1496
  };
1493
1497
 
1498
+ /**
1499
+ * Monad Mainnet chain definition
1500
+ * @remarks
1501
+ * This represents the official production network for the Monad blockchain.
1502
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1503
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1504
+ */
1505
+ declare const Monad: {
1506
+ readonly type: "evm";
1507
+ readonly chain: Blockchain.Monad;
1508
+ readonly name: "Monad";
1509
+ readonly title: "Monad Mainnet";
1510
+ readonly nativeCurrency: {
1511
+ readonly name: "Monad";
1512
+ readonly symbol: "MON";
1513
+ readonly decimals: 18;
1514
+ };
1515
+ readonly chainId: 143;
1516
+ readonly isTestnet: false;
1517
+ readonly explorerUrl: "https://monadscan.com/tx/{hash}";
1518
+ readonly rpcEndpoints: readonly ["https://rpc.monad.xyz"];
1519
+ readonly eurcAddress: null;
1520
+ readonly usdcAddress: "0x754704Bc059F8C67012fEd69BC8A327a5aafb603";
1521
+ readonly cctp: {
1522
+ readonly domain: 15;
1523
+ readonly contracts: {
1524
+ readonly v2: {
1525
+ readonly type: "split";
1526
+ readonly tokenMessenger: "0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d";
1527
+ readonly messageTransmitter: "0x81D40F21F12A8F0E3252Bccb954D722d4c464B64";
1528
+ readonly confirmations: 1;
1529
+ readonly fastConfirmations: 1;
1530
+ };
1531
+ };
1532
+ };
1533
+ readonly kitContracts: {
1534
+ readonly bridge: "0xB3FA262d0fB521cc93bE83d87b322b8A23DAf3F0";
1535
+ };
1536
+ };
1537
+
1538
+ /**
1539
+ * Monad Testnet chain definition
1540
+ * @remarks
1541
+ * This represents the official test network for the Monad blockchain.
1542
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
1543
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
1544
+ */
1545
+ declare const MonadTestnet: {
1546
+ readonly type: "evm";
1547
+ readonly chain: Blockchain.Monad_Testnet;
1548
+ readonly name: "Monad Testnet";
1549
+ readonly title: "Monad Testnet";
1550
+ readonly nativeCurrency: {
1551
+ readonly name: "Monad";
1552
+ readonly symbol: "MON";
1553
+ readonly decimals: 18;
1554
+ };
1555
+ readonly chainId: 10143;
1556
+ readonly isTestnet: true;
1557
+ readonly explorerUrl: "https://testnet.monadscan.com/tx/{hash}";
1558
+ readonly rpcEndpoints: readonly ["https://testnet-rpc.monad.xyz"];
1559
+ readonly eurcAddress: null;
1560
+ readonly usdcAddress: "0x534b2f3A21130d7a60830c2Df862319e593943A3";
1561
+ readonly cctp: {
1562
+ readonly domain: 15;
1563
+ readonly contracts: {
1564
+ readonly v2: {
1565
+ readonly type: "split";
1566
+ readonly tokenMessenger: "0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA";
1567
+ readonly messageTransmitter: "0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275";
1568
+ readonly confirmations: 1;
1569
+ readonly fastConfirmations: 1;
1570
+ };
1571
+ };
1572
+ };
1573
+ readonly kitContracts: {
1574
+ readonly bridge: "0xC5567a5E3370d4DBfB0540025078e283e36A363d";
1575
+ };
1576
+ };
1577
+
1494
1578
  /**
1495
1579
  * NEAR Protocol Mainnet chain definition
1496
1580
  * @remarks
@@ -2570,6 +2654,8 @@ declare const Chains_Ink: typeof Ink;
2570
2654
  declare const Chains_InkTestnet: typeof InkTestnet;
2571
2655
  declare const Chains_Linea: typeof Linea;
2572
2656
  declare const Chains_LineaSepolia: typeof LineaSepolia;
2657
+ declare const Chains_Monad: typeof Monad;
2658
+ declare const Chains_MonadTestnet: typeof MonadTestnet;
2573
2659
  declare const Chains_NEAR: typeof NEAR;
2574
2660
  declare const Chains_NEARTestnet: typeof NEARTestnet;
2575
2661
  declare const Chains_Noble: typeof Noble;
@@ -2627,6 +2713,8 @@ declare namespace Chains {
2627
2713
  Chains_InkTestnet as InkTestnet,
2628
2714
  Chains_Linea as Linea,
2629
2715
  Chains_LineaSepolia as LineaSepolia,
2716
+ Chains_Monad as Monad,
2717
+ Chains_MonadTestnet as MonadTestnet,
2630
2718
  Chains_NEAR as NEAR,
2631
2719
  Chains_NEARTestnet as NEARTestnet,
2632
2720
  Chains_Noble as Noble,
@@ -6598,7 +6686,7 @@ type Recoverability = (typeof RECOVERABILITY_VALUES)[number];
6598
6686
  * Array of valid error type values for validation.
6599
6687
  * Derived from ERROR_TYPES const object.
6600
6688
  */
6601
- declare const ERROR_TYPE_VALUES: ("INPUT" | "BALANCE" | "ONCHAIN" | "RPC" | "NETWORK")[];
6689
+ declare const ERROR_TYPE_VALUES: ("INPUT" | "BALANCE" | "ONCHAIN" | "RPC" | "NETWORK" | "UNKNOWN")[];
6602
6690
  /**
6603
6691
  * Error type indicating the category of the error.
6604
6692
  */
@@ -6725,6 +6813,7 @@ declare class KitError extends Error implements ErrorDetails {
6725
6813
  /**
6726
6814
  * Standardized error code ranges for consistent categorization:
6727
6815
  *
6816
+ * - 0: UNKNOWN - Catch-all for unrecognized errors
6728
6817
  * - 1000-1999: INPUT errors - Parameter validation, input format errors
6729
6818
  * - 3000-3999: NETWORK errors - Internet connectivity, DNS, connection issues
6730
6819
  * - 4000-4999: RPC errors - Blockchain provider issues, gas estimation, nonce errors
@@ -7008,14 +7097,23 @@ declare function isKitError(error: unknown): error is KitError;
7008
7097
  */
7009
7098
  declare function isFatalError(error: unknown): boolean;
7010
7099
  /**
7011
- * Checks if an error is a KitError with RETRYABLE recoverability.
7100
+ * Checks if an error is retryable.
7101
+ *
7102
+ * @remarks
7103
+ * Check order for KitError instances:
7104
+ * 1. If `recoverability === 'RETRYABLE'`, return `true` immediately (priority check).
7105
+ * 2. Otherwise, check if `error.code` is in `DEFAULT_RETRYABLE_ERROR_CODES` (fallback check).
7106
+ * 3. Non-KitError instances always return `false`.
7107
+ *
7108
+ * This two-tier approach allows both explicit recoverability control and
7109
+ * backward-compatible code-based retry logic.
7012
7110
  *
7013
7111
  * RETRYABLE errors indicate transient failures that may succeed on
7014
7112
  * subsequent attempts, such as network timeouts or temporary service
7015
7113
  * unavailability. These errors are safe to retry after a delay.
7016
7114
  *
7017
7115
  * @param error - Unknown error to check
7018
- * @returns True if error is a KitError with RETRYABLE recoverability
7116
+ * @returns True if error is retryable
7019
7117
  *
7020
7118
  * @example
7021
7119
  * ```typescript
@@ -7030,6 +7128,39 @@ declare function isFatalError(error: unknown): boolean;
7030
7128
  * }
7031
7129
  * }
7032
7130
  * ```
7131
+ *
7132
+ * @example
7133
+ * ```typescript
7134
+ * import { isRetryableError, createNetworkConnectionError, KitError } from '@core/errors'
7135
+ *
7136
+ * // KitError with RETRYABLE recoverability (priority check)
7137
+ * const error1 = createNetworkConnectionError('Ethereum')
7138
+ * isRetryableError(error1) // true
7139
+ *
7140
+ * // KitError with default retryable code (fallback check)
7141
+ * const error2 = new KitError({
7142
+ * code: 3002, // NETWORK_TIMEOUT - in DEFAULT_RETRYABLE_ERROR_CODES
7143
+ * name: 'NETWORK_TIMEOUT',
7144
+ * type: 'NETWORK',
7145
+ * recoverability: 'FATAL', // Not RETRYABLE
7146
+ * message: 'Timeout',
7147
+ * })
7148
+ * isRetryableError(error2) // true (code 3002 is in default list)
7149
+ *
7150
+ * // KitError with non-retryable code and FATAL recoverability
7151
+ * const error3 = new KitError({
7152
+ * code: 1001,
7153
+ * name: 'INVALID_INPUT',
7154
+ * type: 'INPUT',
7155
+ * recoverability: 'FATAL',
7156
+ * message: 'Invalid input',
7157
+ * })
7158
+ * isRetryableError(error3) // false
7159
+ *
7160
+ * // Non-KitError
7161
+ * const error4 = new Error('Standard error')
7162
+ * isRetryableError(error4) // false
7163
+ * ```
7033
7164
  */
7034
7165
  declare function isRetryableError(error: unknown): boolean;
7035
7166
  /**
package/index.mjs CHANGED
@@ -120,6 +120,8 @@ const ERROR_TYPES = {
120
120
  RPC: 'RPC',
121
121
  /** Internet connectivity, DNS resolution, connection issues */
122
122
  NETWORK: 'NETWORK',
123
+ /** Catch-all for unrecognized errors (code 0) */
124
+ UNKNOWN: 'UNKNOWN',
123
125
  };
124
126
  /**
125
127
  * Array of valid error type values for validation.
@@ -133,6 +135,8 @@ const ERROR_TYPE_ARRAY = [...ERROR_TYPE_VALUES];
133
135
  /**
134
136
  * Error code ranges for validation.
135
137
  * Single source of truth for valid error code ranges.
138
+ *
139
+ * Note: Code 0 is special - it's the UNKNOWN catch-all error.
136
140
  */
137
141
  const ERROR_CODE_RANGES = [
138
142
  { min: 1000, max: 1999, type: 'INPUT' },
@@ -141,6 +145,8 @@ const ERROR_CODE_RANGES = [
141
145
  { min: 5000, max: 5999, type: 'ONCHAIN' },
142
146
  { min: 9000, max: 9999, type: 'BALANCE' },
143
147
  ];
148
+ /** Special code for UNKNOWN errors */
149
+ const UNKNOWN_ERROR_CODE = 0;
144
150
  /**
145
151
  * Zod schema for validating ErrorDetails objects.
146
152
  *
@@ -179,6 +185,7 @@ const ERROR_CODE_RANGES = [
179
185
  const errorDetailsSchema = z.object({
180
186
  /**
181
187
  * Numeric identifier following standardized ranges:
188
+ * - 0: UNKNOWN - Catch-all for unrecognized errors
182
189
  * - 1000-1999: INPUT errors - Parameter validation
183
190
  * - 3000-3999: NETWORK errors - Connectivity issues
184
191
  * - 4000-4999: RPC errors - Provider issues, gas estimation
@@ -188,8 +195,9 @@ const errorDetailsSchema = z.object({
188
195
  code: z
189
196
  .number()
190
197
  .int('Error code must be an integer')
191
- .refine((code) => ERROR_CODE_RANGES.some((range) => code >= range.min && code <= range.max), {
192
- message: 'Error code must be in valid ranges: 1000-1999 (INPUT), 3000-3999 (NETWORK), 4000-4999 (RPC), 5000-5999 (ONCHAIN), 9000-9999 (BALANCE)',
198
+ .refine((code) => code === UNKNOWN_ERROR_CODE ||
199
+ ERROR_CODE_RANGES.some((range) => code >= range.min && code <= range.max), {
200
+ message: 'Error code must be 0 (UNKNOWN) or in valid ranges: 1000-1999 (INPUT), 3000-3999 (NETWORK), 4000-4999 (RPC), 5000-5999 (ONCHAIN), 9000-9999 (BALANCE)',
193
201
  }),
194
202
  /** Human-readable ID (e.g., "INPUT_NETWORK_MISMATCH", "BALANCE_INSUFFICIENT_TOKEN") */
195
203
  name: z
@@ -199,7 +207,7 @@ const errorDetailsSchema = z.object({
199
207
  /** Error category indicating where the error originated */
200
208
  type: z.enum(ERROR_TYPE_ARRAY, {
201
209
  errorMap: () => ({
202
- message: 'Error type must be one of: INPUT, BALANCE, ONCHAIN, RPC, NETWORK',
210
+ message: 'Error type must be one of: INPUT, BALANCE, ONCHAIN, RPC, NETWORK, UNKNOWN',
203
211
  }),
204
212
  }),
205
213
  /** Error handling strategy */
@@ -416,6 +424,7 @@ class KitError extends Error {
416
424
  /**
417
425
  * Standardized error code ranges for consistent categorization:
418
426
  *
427
+ * - 0: UNKNOWN - Catch-all for unrecognized errors
419
428
  * - 1000-1999: INPUT errors - Parameter validation, input format errors
420
429
  * - 3000-3999: NETWORK errors - Internet connectivity, DNS, connection issues
421
430
  * - 4000-4999: RPC errors - Blockchain provider issues, gas estimation, nonce errors
@@ -964,6 +973,8 @@ var Blockchain;
964
973
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
965
974
  Blockchain["Linea"] = "Linea";
966
975
  Blockchain["Linea_Sepolia"] = "Linea_Sepolia";
976
+ Blockchain["Monad"] = "Monad";
977
+ Blockchain["Monad_Testnet"] = "Monad_Testnet";
967
978
  Blockchain["NEAR"] = "NEAR";
968
979
  Blockchain["NEAR_Testnet"] = "NEAR_Testnet";
969
980
  Blockchain["Noble"] = "Noble";
@@ -1055,6 +1066,7 @@ var BridgeChain;
1055
1066
  BridgeChain["HyperEVM"] = "HyperEVM";
1056
1067
  BridgeChain["Ink"] = "Ink";
1057
1068
  BridgeChain["Linea"] = "Linea";
1069
+ BridgeChain["Monad"] = "Monad";
1058
1070
  BridgeChain["Optimism"] = "Optimism";
1059
1071
  BridgeChain["Plume"] = "Plume";
1060
1072
  BridgeChain["Polygon"] = "Polygon";
@@ -1074,6 +1086,7 @@ var BridgeChain;
1074
1086
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1075
1087
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
1076
1088
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
1089
+ BridgeChain["Monad_Testnet"] = "Monad_Testnet";
1077
1090
  BridgeChain["Optimism_Sepolia"] = "Optimism_Sepolia";
1078
1091
  BridgeChain["Plume_Testnet"] = "Plume_Testnet";
1079
1092
  BridgeChain["Polygon_Amoy_Testnet"] = "Polygon_Amoy_Testnet";
@@ -2060,6 +2073,86 @@ const LineaSepolia = defineChain({
2060
2073
  },
2061
2074
  });
2062
2075
 
2076
+ /**
2077
+ * Monad Mainnet chain definition
2078
+ * @remarks
2079
+ * This represents the official production network for the Monad blockchain.
2080
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
2081
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
2082
+ */
2083
+ const Monad = defineChain({
2084
+ type: 'evm',
2085
+ chain: Blockchain.Monad,
2086
+ name: 'Monad',
2087
+ title: 'Monad Mainnet',
2088
+ nativeCurrency: {
2089
+ name: 'Monad',
2090
+ symbol: 'MON',
2091
+ decimals: 18,
2092
+ },
2093
+ chainId: 143,
2094
+ isTestnet: false,
2095
+ explorerUrl: 'https://monadscan.com/tx/{hash}',
2096
+ rpcEndpoints: ['https://rpc.monad.xyz'],
2097
+ eurcAddress: null,
2098
+ usdcAddress: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
2099
+ cctp: {
2100
+ domain: 15,
2101
+ contracts: {
2102
+ v2: {
2103
+ type: 'split',
2104
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
2105
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
2106
+ confirmations: 1,
2107
+ fastConfirmations: 1,
2108
+ },
2109
+ },
2110
+ },
2111
+ kitContracts: {
2112
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
2113
+ },
2114
+ });
2115
+
2116
+ /**
2117
+ * Monad Testnet chain definition
2118
+ * @remarks
2119
+ * This represents the official test network for the Monad blockchain.
2120
+ * Monad is a high-performance EVM-compatible Layer-1 blockchain featuring
2121
+ * over 10,000 TPS, sub-second finality, and near-zero gas fees.
2122
+ */
2123
+ const MonadTestnet = defineChain({
2124
+ type: 'evm',
2125
+ chain: Blockchain.Monad_Testnet,
2126
+ name: 'Monad Testnet',
2127
+ title: 'Monad Testnet',
2128
+ nativeCurrency: {
2129
+ name: 'Monad',
2130
+ symbol: 'MON',
2131
+ decimals: 18,
2132
+ },
2133
+ chainId: 10143,
2134
+ isTestnet: true,
2135
+ explorerUrl: 'https://testnet.monadscan.com/tx/{hash}',
2136
+ rpcEndpoints: ['https://testnet-rpc.monad.xyz'],
2137
+ eurcAddress: null,
2138
+ usdcAddress: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
2139
+ cctp: {
2140
+ domain: 15,
2141
+ contracts: {
2142
+ v2: {
2143
+ type: 'split',
2144
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
2145
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
2146
+ confirmations: 1,
2147
+ fastConfirmations: 1,
2148
+ },
2149
+ },
2150
+ },
2151
+ kitContracts: {
2152
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
2153
+ },
2154
+ });
2155
+
2063
2156
  /**
2064
2157
  * NEAR Protocol Mainnet chain definition
2065
2158
  * @remarks
@@ -3144,6 +3237,8 @@ var Blockchains = /*#__PURE__*/Object.freeze({
3144
3237
  InkTestnet: InkTestnet,
3145
3238
  Linea: Linea,
3146
3239
  LineaSepolia: LineaSepolia,
3240
+ Monad: Monad,
3241
+ MonadTestnet: MonadTestnet,
3147
3242
  NEAR: NEAR,
3148
3243
  NEARTestnet: NEARTestnet,
3149
3244
  Noble: Noble,
@@ -3555,14 +3650,41 @@ function isFatalError(error) {
3555
3650
  return isKitError(error) && error.recoverability === 'FATAL';
3556
3651
  }
3557
3652
  /**
3558
- * Checks if an error is a KitError with RETRYABLE recoverability.
3653
+ * Error codes that are considered retryable by default.
3654
+ *
3655
+ * @remarks
3656
+ * These are typically transient errors that may succeed on retry:
3657
+ * - Network connectivity issues (3001, 3002)
3658
+ * - Provider unavailability (4001, 4002)
3659
+ * - RPC nonce errors (4003)
3660
+ */
3661
+ const DEFAULT_RETRYABLE_ERROR_CODES = [
3662
+ // Network errors
3663
+ 3001, // NETWORK_CONNECTION_FAILED
3664
+ 3002, // NETWORK_TIMEOUT
3665
+ // Provider errors
3666
+ 4001, // PROVIDER_UNAVAILABLE
3667
+ 4002, // PROVIDER_TIMEOUT
3668
+ 4003, // RPC_NONCE_ERROR
3669
+ ];
3670
+ /**
3671
+ * Checks if an error is retryable.
3672
+ *
3673
+ * @remarks
3674
+ * Check order for KitError instances:
3675
+ * 1. If `recoverability === 'RETRYABLE'`, return `true` immediately (priority check).
3676
+ * 2. Otherwise, check if `error.code` is in `DEFAULT_RETRYABLE_ERROR_CODES` (fallback check).
3677
+ * 3. Non-KitError instances always return `false`.
3678
+ *
3679
+ * This two-tier approach allows both explicit recoverability control and
3680
+ * backward-compatible code-based retry logic.
3559
3681
  *
3560
3682
  * RETRYABLE errors indicate transient failures that may succeed on
3561
3683
  * subsequent attempts, such as network timeouts or temporary service
3562
3684
  * unavailability. These errors are safe to retry after a delay.
3563
3685
  *
3564
3686
  * @param error - Unknown error to check
3565
- * @returns True if error is a KitError with RETRYABLE recoverability
3687
+ * @returns True if error is retryable
3566
3688
  *
3567
3689
  * @example
3568
3690
  * ```typescript
@@ -3577,9 +3699,51 @@ function isFatalError(error) {
3577
3699
  * }
3578
3700
  * }
3579
3701
  * ```
3702
+ *
3703
+ * @example
3704
+ * ```typescript
3705
+ * import { isRetryableError, createNetworkConnectionError, KitError } from '@core/errors'
3706
+ *
3707
+ * // KitError with RETRYABLE recoverability (priority check)
3708
+ * const error1 = createNetworkConnectionError('Ethereum')
3709
+ * isRetryableError(error1) // true
3710
+ *
3711
+ * // KitError with default retryable code (fallback check)
3712
+ * const error2 = new KitError({
3713
+ * code: 3002, // NETWORK_TIMEOUT - in DEFAULT_RETRYABLE_ERROR_CODES
3714
+ * name: 'NETWORK_TIMEOUT',
3715
+ * type: 'NETWORK',
3716
+ * recoverability: 'FATAL', // Not RETRYABLE
3717
+ * message: 'Timeout',
3718
+ * })
3719
+ * isRetryableError(error2) // true (code 3002 is in default list)
3720
+ *
3721
+ * // KitError with non-retryable code and FATAL recoverability
3722
+ * const error3 = new KitError({
3723
+ * code: 1001,
3724
+ * name: 'INVALID_INPUT',
3725
+ * type: 'INPUT',
3726
+ * recoverability: 'FATAL',
3727
+ * message: 'Invalid input',
3728
+ * })
3729
+ * isRetryableError(error3) // false
3730
+ *
3731
+ * // Non-KitError
3732
+ * const error4 = new Error('Standard error')
3733
+ * isRetryableError(error4) // false
3734
+ * ```
3580
3735
  */
3581
3736
  function isRetryableError(error) {
3582
- return isKitError(error) && error.recoverability === 'RETRYABLE';
3737
+ // Use proper type guard to check if it's a KitError
3738
+ if (isKitError(error)) {
3739
+ // Priority check: explicit recoverability
3740
+ if (error.recoverability === 'RETRYABLE') {
3741
+ return true;
3742
+ }
3743
+ // Fallback check: error code against default retryable codes
3744
+ return DEFAULT_RETRYABLE_ERROR_CODES.includes(error.code);
3745
+ }
3746
+ return false;
3583
3747
  }
3584
3748
  /**
3585
3749
  * Type guard to check if error is KitError with INPUT type.
@@ -4637,7 +4801,7 @@ const parseAmount = (params) => {
4637
4801
  };
4638
4802
 
4639
4803
  var name = "@circle-fin/bridge-kit";
4640
- var version = "1.4.0";
4804
+ var version = "1.5.0";
4641
4805
  var pkg = {
4642
4806
  name: name,
4643
4807
  version: version};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circle-fin/bridge-kit",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
4
4
  "description": "SDK for seamless cross-chain stablecoin bridging",
5
5
  "keywords": [
6
6
  "circle",
@@ -22,7 +22,7 @@
22
22
  "types": "./index.d.ts",
23
23
  "dependencies": {
24
24
  "zod": "3.25.67",
25
- "@circle-fin/provider-cctp-v2": "^1.2.0",
25
+ "@circle-fin/provider-cctp-v2": "^1.3.0",
26
26
  "abitype": "^1.1.0",
27
27
  "@solana/web3.js": "^1.98.4",
28
28
  "@ethersproject/address": "^5.8.0",