@circle-fin/adapter-ethers-v6 1.6.6 → 1.8.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,21 @@
1
1
  # @circle-fin/adapter-ethers-v6
2
2
 
3
+ ## 1.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Improves the error you get when attempting a Gateway spend with a smart-contract account (SCA) as the signer. The failure previously surfaced as a confusing `invalid integer value <nil>/<nil> for type uint256` response from the Circle Wallets backend; you now get a clear `INPUT_UNSUPPORTED_ACTION` error up front that points at the delegate workflow (`kit.unifiedBalance.addDelegate` + `kit.unifiedBalance.spend` with the delegate EOA as `from.address` and the SCA as `from.sourceAccount`).
8
+
9
+ ### Patch Changes
10
+
11
+ - Fix excessive MetaMask mobile app-switching prompts during bridge estimation and support chain switching for WalletConnect/Dynamic mobile wallet providers
12
+
13
+ ## 1.7.0
14
+
15
+ ### Minor Changes
16
+
17
+ - Add support for bridging USDC to and from Injective (mainnet and testnet) via CCTP v2. Both networks are now available as source and destination options in Bridge Kit.
18
+
3
19
  ## 1.6.6
4
20
 
5
21
  ### Patch Changes
package/index.cjs CHANGED
@@ -1733,6 +1733,8 @@ exports.Blockchain = void 0;
1733
1733
  Blockchain["Hedera_Testnet"] = "Hedera_Testnet";
1734
1734
  Blockchain["HyperEVM"] = "HyperEVM";
1735
1735
  Blockchain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1736
+ Blockchain["Injective"] = "Injective";
1737
+ Blockchain["Injective_Testnet"] = "Injective_Testnet";
1736
1738
  Blockchain["Ink"] = "Ink";
1737
1739
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
1738
1740
  Blockchain["Linea"] = "Linea";
@@ -1952,6 +1954,7 @@ var BridgeChain;
1952
1954
  BridgeChain["Edge"] = "Edge";
1953
1955
  BridgeChain["Ethereum"] = "Ethereum";
1954
1956
  BridgeChain["HyperEVM"] = "HyperEVM";
1957
+ BridgeChain["Injective"] = "Injective";
1955
1958
  BridgeChain["Ink"] = "Ink";
1956
1959
  BridgeChain["Linea"] = "Linea";
1957
1960
  BridgeChain["Monad"] = "Monad";
@@ -1975,6 +1978,7 @@ var BridgeChain;
1975
1978
  BridgeChain["Edge_Testnet"] = "Edge_Testnet";
1976
1979
  BridgeChain["Ethereum_Sepolia"] = "Ethereum_Sepolia";
1977
1980
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1981
+ BridgeChain["Injective_Testnet"] = "Injective_Testnet";
1978
1982
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
1979
1983
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
1980
1984
  BridgeChain["Monad_Testnet"] = "Monad_Testnet";
@@ -3394,6 +3398,98 @@ const HyperEVMTestnet = defineChain({
3394
3398
  },
3395
3399
  });
3396
3400
 
3401
+ /**
3402
+ * Injective Mainnet chain definition
3403
+ * @remarks
3404
+ * This represents the official production network for the Injective blockchain.
3405
+ * Injective is a high-performance, interoperable Layer-1 blockchain built for
3406
+ * finance, with an EVM execution layer on top of a Cosmos SDK base and
3407
+ * sub-second block finality.
3408
+ */
3409
+ const Injective = defineChain({
3410
+ type: 'evm',
3411
+ chain: exports.Blockchain.Injective,
3412
+ name: 'Injective',
3413
+ title: 'Injective Mainnet',
3414
+ nativeCurrency: {
3415
+ name: 'Injective',
3416
+ symbol: 'INJ',
3417
+ decimals: 18,
3418
+ },
3419
+ chainId: 1776,
3420
+ isTestnet: false,
3421
+ explorerUrl: 'https://injscan.com/transaction/{hash}',
3422
+ rpcEndpoints: ['https://sentry.evm-rpc.injective.network'],
3423
+ eurcAddress: null,
3424
+ usdcAddress: '0xa00C59fF5a080D2b954d0c75e46E22a0c371235a',
3425
+ usdtAddress: null,
3426
+ cctp: {
3427
+ domain: 29,
3428
+ contracts: {
3429
+ v2: {
3430
+ type: 'split',
3431
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3432
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3433
+ confirmations: 1,
3434
+ fastConfirmations: 1,
3435
+ },
3436
+ },
3437
+ forwarderSupported: {
3438
+ source: false,
3439
+ destination: false,
3440
+ },
3441
+ },
3442
+ kitContracts: {
3443
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3444
+ },
3445
+ });
3446
+
3447
+ /**
3448
+ * Injective Testnet chain definition
3449
+ * @remarks
3450
+ * This represents the official test network for the Injective blockchain.
3451
+ * Injective is a high-performance, interoperable Layer-1 blockchain built for
3452
+ * finance, with an EVM execution layer on top of a Cosmos SDK base and
3453
+ * sub-second block finality.
3454
+ */
3455
+ const InjectiveTestnet = defineChain({
3456
+ type: 'evm',
3457
+ chain: exports.Blockchain.Injective_Testnet,
3458
+ name: 'Injective Testnet',
3459
+ title: 'Injective Testnet',
3460
+ nativeCurrency: {
3461
+ name: 'Injective',
3462
+ symbol: 'INJ',
3463
+ decimals: 18,
3464
+ },
3465
+ chainId: 1439,
3466
+ isTestnet: true,
3467
+ explorerUrl: 'https://testnet.explorer.injective.network/transaction/{hash}',
3468
+ rpcEndpoints: ['https://k8s.testnet.json-rpc.injective.network'],
3469
+ eurcAddress: null,
3470
+ usdcAddress: '0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d',
3471
+ usdtAddress: null,
3472
+ cctp: {
3473
+ domain: 29,
3474
+ contracts: {
3475
+ v2: {
3476
+ type: 'split',
3477
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3478
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3479
+ confirmations: 1,
3480
+ fastConfirmations: 1,
3481
+ },
3482
+ },
3483
+ forwarderSupported: {
3484
+ source: false,
3485
+ destination: false,
3486
+ },
3487
+ },
3488
+ kitContracts: {
3489
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3490
+ },
3491
+ });
3492
+
3397
3493
  /**
3398
3494
  * Ink Mainnet chain definition
3399
3495
  * @remarks
@@ -5236,6 +5332,8 @@ var Blockchains = {
5236
5332
  HederaTestnet: HederaTestnet,
5237
5333
  HyperEVM: HyperEVM,
5238
5334
  HyperEVMTestnet: HyperEVMTestnet,
5335
+ Injective: Injective,
5336
+ InjectiveTestnet: InjectiveTestnet,
5239
5337
  Ink: Ink,
5240
5338
  InkTestnet: InkTestnet,
5241
5339
  Linea: Linea,
@@ -6806,6 +6904,7 @@ const USDC = {
6806
6904
  [exports.Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
6807
6905
  [exports.Blockchain.Hedera]: '0.0.456858',
6808
6906
  [exports.Blockchain.HyperEVM]: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',
6907
+ [exports.Blockchain.Injective]: '0xa00C59fF5a080D2b954d0c75e46E22a0c371235a',
6809
6908
  [exports.Blockchain.Ink]: '0x2D270e6886d130D724215A266106e6832161EAEd',
6810
6909
  [exports.Blockchain.Linea]: '0x176211869ca2b568f2a7d4ee941e073a821ee1ff',
6811
6910
  [exports.Blockchain.Monad]: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
@@ -6838,6 +6937,7 @@ const USDC = {
6838
6937
  [exports.Blockchain.Ethereum_Sepolia]: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
6839
6938
  [exports.Blockchain.Hedera_Testnet]: '0.0.429274',
6840
6939
  [exports.Blockchain.HyperEVM_Testnet]: '0x2B3370eE501B4a559b57D449569354196457D8Ab',
6940
+ [exports.Blockchain.Injective_Testnet]: '0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d',
6841
6941
  [exports.Blockchain.Ink_Testnet]: '0xFabab97dCE620294D2B0b0e46C68964e326300Ac',
6842
6942
  [exports.Blockchain.Linea_Sepolia]: '0xfece4462d57bd51a6a552365a011b95f0e16d9b7',
6843
6943
  [exports.Blockchain.Monad_Testnet]: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
@@ -17002,41 +17102,37 @@ function isBrowserWithEthereum() {
17002
17102
  return (typeof window !== 'undefined' && !!window.ethereum);
17003
17103
  }
17004
17104
  /**
17005
- * Attempts to switch the connected chain in a browser wallet, or adds the chain if it is not recognized.
17006
- *
17007
- * @param signer - The current Ethers.js Signer instance, expected to be connected to a browser provider.
17008
- * @param chain - The EVM chain definition to switch to.
17009
- * @returns A promise resolving to the new Signer instance connected to the target chain.
17010
- *
17011
- * @remarks
17012
- * This function uses the EIP-3326 `wallet_switchEthereumChain` and EIP-3085 `wallet_addEthereumChain` methods
17013
- * to prompt the user to switch or add the specified chain in their browser wallet.
17105
+ * Switch or add a chain via an EIP-1193 provider, then return a fresh signer.
17014
17106
  *
17015
- * @throws {Error} If the provider does not support chain switching, or if the user rejects the request,
17016
- * or if the operation fails for any other reason.
17107
+ * @param provider - An EIP-1193 compatible provider with a `send` method.
17108
+ * @param chain - The target EVM chain definition.
17109
+ * @returns A promise resolving to a new Signer connected to the target chain.
17110
+ * @throws When the user rejects the switch or the provider fails.
17017
17111
  */
17018
- async function switchOrAddChainInBrowser(signer, chain) {
17019
- const win = window;
17020
- const signerWithProvider = signer;
17021
- if (!signerWithProvider?.provider?.send) {
17022
- throw new Error('Browser provider does not support chain switching');
17023
- }
17112
+ async function switchOrAddViaProvider(provider, chain) {
17024
17113
  try {
17025
- await signerWithProvider.provider.send('wallet_switchEthereumChain', [
17114
+ await provider.send('wallet_switchEthereumChain', [
17026
17115
  { chainId: `0x${chain.chainId.toString(16)}` },
17027
17116
  ]);
17028
- return await getBrowserSigner(win);
17029
17117
  }
17030
17118
  catch (error) {
17031
17119
  if (typeof error === 'object' &&
17032
17120
  error !== null &&
17033
17121
  'code' in error &&
17034
17122
  error.code === UNRECOGNIZED_CHAIN_ID_ERROR_CODE) {
17035
- await addChainInBrowser(signerWithProvider, chain);
17036
- return await getBrowserSigner(win);
17123
+ await addChainInBrowser({ provider }, chain);
17124
+ await provider.send('wallet_switchEthereumChain', [
17125
+ { chainId: `0x${chain.chainId.toString(16)}` },
17126
+ ]);
17127
+ }
17128
+ else {
17129
+ throw error;
17037
17130
  }
17038
- throw error;
17039
17131
  }
17132
+ const browserProvider = provider instanceof ethers.BrowserProvider
17133
+ ? provider
17134
+ : new ethers.BrowserProvider(provider);
17135
+ return await browserProvider.getSigner();
17040
17136
  }
17041
17137
  /**
17042
17138
  * Adds a new EVM chain to the user's browser wallet using the EIP-3085 `wallet_addEthereumChain` method.
@@ -17051,9 +17147,9 @@ async function switchOrAddChainInBrowser(signer, chain) {
17051
17147
  *
17052
17148
  * @throws {Error} If the provider does not support the `send` method or if the request fails.
17053
17149
  */
17054
- async function addChainInBrowser(signerWithProvider, chain) {
17150
+ async function addChainInBrowser(providerLike, chain) {
17055
17151
  const rpcUrl = chain.rpcEndpoints[0];
17056
- await signerWithProvider.provider.send('wallet_addEthereumChain', [
17152
+ await providerLike.provider.send('wallet_addEthereumChain', [
17057
17153
  {
17058
17154
  chainId: `0x${chain.chainId.toString(16)}`,
17059
17155
  chainName: chain.name,
@@ -17065,24 +17161,9 @@ async function addChainInBrowser(signerWithProvider, chain) {
17065
17161
  },
17066
17162
  ]);
17067
17163
  }
17068
- /**
17069
- * Returns a Signer instance from the browser's injected Ethereum provider.
17070
- *
17071
- * @param win - The browser window object with an injected `ethereum` provider.
17072
- * @returns A promise resolving Signer instance connected to the browser's provider.
17073
- *
17074
- * @remarks
17075
- * This function wraps the Ethers.js `BrowserProvider` to obtain a Signer for user interaction.
17076
- *
17077
- * @throws {Error} If the `ethereum` provider is not available or if the signer cannot be retrieved.
17078
- */
17079
- async function getBrowserSigner(win) {
17080
- const browserProvider = new ethers.BrowserProvider(win.ethereum);
17081
- return await browserProvider.getSigner();
17082
- }
17083
17164
  /**
17084
17165
  * Switches the chain for the given signer and returns a new signer for the target chain.
17085
- * Handles both browser and server-side environments.
17166
+ * Handles browser (injected + WalletConnect/Dynamic) and server-side environments.
17086
17167
  *
17087
17168
  * @param signer - The current signer instance
17088
17169
  * @param chain - The target chain definition
@@ -17090,8 +17171,21 @@ async function getBrowserSigner(win) {
17090
17171
  * @throws If switching fails or the environment is unsupported
17091
17172
  */
17092
17173
  async function switchChain(signer, chain) {
17174
+ // Injected browser wallet (window.ethereum present)
17093
17175
  if (isBrowserWithEthereum()) {
17094
- return switchOrAddChainInBrowser(signer, chain);
17176
+ const signerWithProvider = signer;
17177
+ if (!signerWithProvider?.provider?.send) {
17178
+ throw new Error('Browser provider does not support chain switching');
17179
+ }
17180
+ return switchOrAddViaProvider(signerWithProvider.provider, chain);
17181
+ }
17182
+ // Browser without window.ethereum (e.g., WalletConnect/Dynamic mobile wallets)
17183
+ const signerWithProvider = signer;
17184
+ const signerProvider = signerWithProvider.provider;
17185
+ if (globalThis.window !== undefined &&
17186
+ signerProvider &&
17187
+ 'send' in signerProvider) {
17188
+ return switchOrAddViaProvider(signerProvider, chain);
17095
17189
  }
17096
17190
  // Server-side: recreate the provider and signer
17097
17191
  const rpcUrl = chain.rpcEndpoints[0];
@@ -18067,6 +18161,36 @@ class EthersAdapter extends EvmAdapter {
18067
18161
  });
18068
18162
  }
18069
18163
  }
18164
+ /**
18165
+ * Reads the on-chain bytecode for a given address via ethers' `getCode`.
18166
+ *
18167
+ * Returns the hex-encoded bytecode when the address is a contract, or
18168
+ * `'0x'` when the address has no code (EOA). Used by Gateway burn-intent
18169
+ * signing to detect smart-contract accounts, which are not supported by
18170
+ * Gateway's ecrecover-based verification path.
18171
+ */
18172
+ async readBytecode(address, chain) {
18173
+ const provider = await this.getProvider(chain);
18174
+ try {
18175
+ const code = await provider.getCode(address);
18176
+ return code;
18177
+ }
18178
+ catch (error) {
18179
+ const errorMessage = error instanceof Error ? error.message : String(error);
18180
+ throw new KitError({
18181
+ ...RpcError.ENDPOINT_ERROR,
18182
+ recoverability: 'RETRYABLE',
18183
+ message: `Failed to read bytecode for ${address}: ${errorMessage}`,
18184
+ cause: {
18185
+ trace: {
18186
+ operation: 'readBytecode',
18187
+ address,
18188
+ chain: chain.name,
18189
+ },
18190
+ },
18191
+ });
18192
+ }
18193
+ }
18070
18194
  /**
18071
18195
  * Signs EIP-712 typed data using the configured signer with OperationContext.
18072
18196
  *
package/index.d.ts CHANGED
@@ -668,6 +668,8 @@ declare enum Blockchain {
668
668
  Hedera_Testnet = "Hedera_Testnet",
669
669
  HyperEVM = "HyperEVM",
670
670
  HyperEVM_Testnet = "HyperEVM_Testnet",
671
+ Injective = "Injective",
672
+ Injective_Testnet = "Injective_Testnet",
671
673
  Ink = "Ink",
672
674
  Ink_Testnet = "Ink_Testnet",
673
675
  Linea = "Linea",
@@ -3972,6 +3974,37 @@ declare abstract class EvmAdapter<TAdapterCapabilities extends AdapterCapabiliti
3972
3974
  * @throws Error when balance retrieval fails.
3973
3975
  */
3974
3976
  abstract readNativeBalance(address: string, chain: EVMChainDefinition): Promise<bigint>;
3977
+ /**
3978
+ * Reads the on-chain bytecode for a given address.
3979
+ *
3980
+ * Returns the deployed contract bytecode as a hex string (`0x`-prefixed),
3981
+ * or `'0x'` when the address has no code (i.e. is a plain EOA).
3982
+ * Implementations MUST normalize a "no code" RPC response to `'0x'` so
3983
+ * callers can compare against a single sentinel.
3984
+ *
3985
+ * Useful for detecting smart-contract accounts before attempting an
3986
+ * operation that only supports EOA signing (e.g. Gateway burn intents).
3987
+ *
3988
+ * @param address - The address to read bytecode for.
3989
+ * @param chain - The chain definition to read from.
3990
+ * @returns Promise resolving to `'0x'` for an EOA, or the hex-encoded
3991
+ * deployed bytecode otherwise.
3992
+ * @throws Error when the underlying RPC call fails.
3993
+ *
3994
+ * @example
3995
+ * ```typescript
3996
+ * import { ViemAdapter } from '@circle-fin/adapter-viem-v2'
3997
+ * import { Ethereum } from '@core/chains'
3998
+ *
3999
+ * const adapter = new ViemAdapter({ publicClient, walletClient })
4000
+ * const code = await adapter.readBytecode('0xabc...', Ethereum)
4001
+ *
4002
+ * if (code !== '0x') {
4003
+ * throw new Error('signer has on-chain bytecode')
4004
+ * }
4005
+ * ```
4006
+ */
4007
+ abstract readBytecode(address: string, chain: EVMChainDefinition): Promise<`0x${string}`>;
3975
4008
  /**
3976
4009
  * Calculate the total transaction fee including compute cost and buffer for the configured chain.
3977
4010
  *
@@ -4571,6 +4604,15 @@ declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = A
4571
4604
  * ```
4572
4605
  */
4573
4606
  readNativeBalance(address: string, chain: EVMChainDefinition): Promise<bigint>;
4607
+ /**
4608
+ * Reads the on-chain bytecode for a given address via ethers' `getCode`.
4609
+ *
4610
+ * Returns the hex-encoded bytecode when the address is a contract, or
4611
+ * `'0x'` when the address has no code (EOA). Used by Gateway burn-intent
4612
+ * signing to detect smart-contract accounts, which are not supported by
4613
+ * Gateway's ecrecover-based verification path.
4614
+ */
4615
+ readBytecode(address: string, chain: EVMChainDefinition): Promise<`0x${string}`>;
4574
4616
  /**
4575
4617
  * Signs EIP-712 typed data using the configured signer with OperationContext.
4576
4618
  *
package/index.mjs CHANGED
@@ -1728,6 +1728,8 @@ var Blockchain;
1728
1728
  Blockchain["Hedera_Testnet"] = "Hedera_Testnet";
1729
1729
  Blockchain["HyperEVM"] = "HyperEVM";
1730
1730
  Blockchain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1731
+ Blockchain["Injective"] = "Injective";
1732
+ Blockchain["Injective_Testnet"] = "Injective_Testnet";
1731
1733
  Blockchain["Ink"] = "Ink";
1732
1734
  Blockchain["Ink_Testnet"] = "Ink_Testnet";
1733
1735
  Blockchain["Linea"] = "Linea";
@@ -1947,6 +1949,7 @@ var BridgeChain;
1947
1949
  BridgeChain["Edge"] = "Edge";
1948
1950
  BridgeChain["Ethereum"] = "Ethereum";
1949
1951
  BridgeChain["HyperEVM"] = "HyperEVM";
1952
+ BridgeChain["Injective"] = "Injective";
1950
1953
  BridgeChain["Ink"] = "Ink";
1951
1954
  BridgeChain["Linea"] = "Linea";
1952
1955
  BridgeChain["Monad"] = "Monad";
@@ -1970,6 +1973,7 @@ var BridgeChain;
1970
1973
  BridgeChain["Edge_Testnet"] = "Edge_Testnet";
1971
1974
  BridgeChain["Ethereum_Sepolia"] = "Ethereum_Sepolia";
1972
1975
  BridgeChain["HyperEVM_Testnet"] = "HyperEVM_Testnet";
1976
+ BridgeChain["Injective_Testnet"] = "Injective_Testnet";
1973
1977
  BridgeChain["Ink_Testnet"] = "Ink_Testnet";
1974
1978
  BridgeChain["Linea_Sepolia"] = "Linea_Sepolia";
1975
1979
  BridgeChain["Monad_Testnet"] = "Monad_Testnet";
@@ -3389,6 +3393,98 @@ const HyperEVMTestnet = defineChain({
3389
3393
  },
3390
3394
  });
3391
3395
 
3396
+ /**
3397
+ * Injective Mainnet chain definition
3398
+ * @remarks
3399
+ * This represents the official production network for the Injective blockchain.
3400
+ * Injective is a high-performance, interoperable Layer-1 blockchain built for
3401
+ * finance, with an EVM execution layer on top of a Cosmos SDK base and
3402
+ * sub-second block finality.
3403
+ */
3404
+ const Injective = defineChain({
3405
+ type: 'evm',
3406
+ chain: Blockchain.Injective,
3407
+ name: 'Injective',
3408
+ title: 'Injective Mainnet',
3409
+ nativeCurrency: {
3410
+ name: 'Injective',
3411
+ symbol: 'INJ',
3412
+ decimals: 18,
3413
+ },
3414
+ chainId: 1776,
3415
+ isTestnet: false,
3416
+ explorerUrl: 'https://injscan.com/transaction/{hash}',
3417
+ rpcEndpoints: ['https://sentry.evm-rpc.injective.network'],
3418
+ eurcAddress: null,
3419
+ usdcAddress: '0xa00C59fF5a080D2b954d0c75e46E22a0c371235a',
3420
+ usdtAddress: null,
3421
+ cctp: {
3422
+ domain: 29,
3423
+ contracts: {
3424
+ v2: {
3425
+ type: 'split',
3426
+ tokenMessenger: '0x28b5a0e9C621a5BadaA536219b3a228C8168cf5d',
3427
+ messageTransmitter: '0x81D40F21F12A8F0E3252Bccb954D722d4c464B64',
3428
+ confirmations: 1,
3429
+ fastConfirmations: 1,
3430
+ },
3431
+ },
3432
+ forwarderSupported: {
3433
+ source: false,
3434
+ destination: false,
3435
+ },
3436
+ },
3437
+ kitContracts: {
3438
+ bridge: BRIDGE_CONTRACT_EVM_MAINNET,
3439
+ },
3440
+ });
3441
+
3442
+ /**
3443
+ * Injective Testnet chain definition
3444
+ * @remarks
3445
+ * This represents the official test network for the Injective blockchain.
3446
+ * Injective is a high-performance, interoperable Layer-1 blockchain built for
3447
+ * finance, with an EVM execution layer on top of a Cosmos SDK base and
3448
+ * sub-second block finality.
3449
+ */
3450
+ const InjectiveTestnet = defineChain({
3451
+ type: 'evm',
3452
+ chain: Blockchain.Injective_Testnet,
3453
+ name: 'Injective Testnet',
3454
+ title: 'Injective Testnet',
3455
+ nativeCurrency: {
3456
+ name: 'Injective',
3457
+ symbol: 'INJ',
3458
+ decimals: 18,
3459
+ },
3460
+ chainId: 1439,
3461
+ isTestnet: true,
3462
+ explorerUrl: 'https://testnet.explorer.injective.network/transaction/{hash}',
3463
+ rpcEndpoints: ['https://k8s.testnet.json-rpc.injective.network'],
3464
+ eurcAddress: null,
3465
+ usdcAddress: '0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d',
3466
+ usdtAddress: null,
3467
+ cctp: {
3468
+ domain: 29,
3469
+ contracts: {
3470
+ v2: {
3471
+ type: 'split',
3472
+ tokenMessenger: '0x8FE6B999Dc680CcFDD5Bf7EB0974218be2542DAA',
3473
+ messageTransmitter: '0xE737e5cEBEEBa77EFE34D4aa090756590b1CE275',
3474
+ confirmations: 1,
3475
+ fastConfirmations: 1,
3476
+ },
3477
+ },
3478
+ forwarderSupported: {
3479
+ source: false,
3480
+ destination: false,
3481
+ },
3482
+ },
3483
+ kitContracts: {
3484
+ bridge: BRIDGE_CONTRACT_EVM_TESTNET,
3485
+ },
3486
+ });
3487
+
3392
3488
  /**
3393
3489
  * Ink Mainnet chain definition
3394
3490
  * @remarks
@@ -5231,6 +5327,8 @@ var Blockchains = /*#__PURE__*/Object.freeze({
5231
5327
  HederaTestnet: HederaTestnet,
5232
5328
  HyperEVM: HyperEVM,
5233
5329
  HyperEVMTestnet: HyperEVMTestnet,
5330
+ Injective: Injective,
5331
+ InjectiveTestnet: InjectiveTestnet,
5234
5332
  Ink: Ink,
5235
5333
  InkTestnet: InkTestnet,
5236
5334
  Linea: Linea,
@@ -6801,6 +6899,7 @@ const USDC = {
6801
6899
  [Blockchain.Ethereum]: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48',
6802
6900
  [Blockchain.Hedera]: '0.0.456858',
6803
6901
  [Blockchain.HyperEVM]: '0xb88339CB7199b77E23DB6E890353E22632Ba630f',
6902
+ [Blockchain.Injective]: '0xa00C59fF5a080D2b954d0c75e46E22a0c371235a',
6804
6903
  [Blockchain.Ink]: '0x2D270e6886d130D724215A266106e6832161EAEd',
6805
6904
  [Blockchain.Linea]: '0x176211869ca2b568f2a7d4ee941e073a821ee1ff',
6806
6905
  [Blockchain.Monad]: '0x754704Bc059F8C67012fEd69BC8A327a5aafb603',
@@ -6833,6 +6932,7 @@ const USDC = {
6833
6932
  [Blockchain.Ethereum_Sepolia]: '0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238',
6834
6933
  [Blockchain.Hedera_Testnet]: '0.0.429274',
6835
6934
  [Blockchain.HyperEVM_Testnet]: '0x2B3370eE501B4a559b57D449569354196457D8Ab',
6935
+ [Blockchain.Injective_Testnet]: '0x0C382e685bbeeFE5d3d9C29e29E341fEE8E84C5d',
6836
6936
  [Blockchain.Ink_Testnet]: '0xFabab97dCE620294D2B0b0e46C68964e326300Ac',
6837
6937
  [Blockchain.Linea_Sepolia]: '0xfece4462d57bd51a6a552365a011b95f0e16d9b7',
6838
6938
  [Blockchain.Monad_Testnet]: '0x534b2f3A21130d7a60830c2Df862319e593943A3',
@@ -16997,41 +17097,37 @@ function isBrowserWithEthereum() {
16997
17097
  return (typeof window !== 'undefined' && !!window.ethereum);
16998
17098
  }
16999
17099
  /**
17000
- * Attempts to switch the connected chain in a browser wallet, or adds the chain if it is not recognized.
17001
- *
17002
- * @param signer - The current Ethers.js Signer instance, expected to be connected to a browser provider.
17003
- * @param chain - The EVM chain definition to switch to.
17004
- * @returns A promise resolving to the new Signer instance connected to the target chain.
17005
- *
17006
- * @remarks
17007
- * This function uses the EIP-3326 `wallet_switchEthereumChain` and EIP-3085 `wallet_addEthereumChain` methods
17008
- * to prompt the user to switch or add the specified chain in their browser wallet.
17100
+ * Switch or add a chain via an EIP-1193 provider, then return a fresh signer.
17009
17101
  *
17010
- * @throws {Error} If the provider does not support chain switching, or if the user rejects the request,
17011
- * or if the operation fails for any other reason.
17102
+ * @param provider - An EIP-1193 compatible provider with a `send` method.
17103
+ * @param chain - The target EVM chain definition.
17104
+ * @returns A promise resolving to a new Signer connected to the target chain.
17105
+ * @throws When the user rejects the switch or the provider fails.
17012
17106
  */
17013
- async function switchOrAddChainInBrowser(signer, chain) {
17014
- const win = window;
17015
- const signerWithProvider = signer;
17016
- if (!signerWithProvider?.provider?.send) {
17017
- throw new Error('Browser provider does not support chain switching');
17018
- }
17107
+ async function switchOrAddViaProvider(provider, chain) {
17019
17108
  try {
17020
- await signerWithProvider.provider.send('wallet_switchEthereumChain', [
17109
+ await provider.send('wallet_switchEthereumChain', [
17021
17110
  { chainId: `0x${chain.chainId.toString(16)}` },
17022
17111
  ]);
17023
- return await getBrowserSigner(win);
17024
17112
  }
17025
17113
  catch (error) {
17026
17114
  if (typeof error === 'object' &&
17027
17115
  error !== null &&
17028
17116
  'code' in error &&
17029
17117
  error.code === UNRECOGNIZED_CHAIN_ID_ERROR_CODE) {
17030
- await addChainInBrowser(signerWithProvider, chain);
17031
- return await getBrowserSigner(win);
17118
+ await addChainInBrowser({ provider }, chain);
17119
+ await provider.send('wallet_switchEthereumChain', [
17120
+ { chainId: `0x${chain.chainId.toString(16)}` },
17121
+ ]);
17122
+ }
17123
+ else {
17124
+ throw error;
17032
17125
  }
17033
- throw error;
17034
17126
  }
17127
+ const browserProvider = provider instanceof BrowserProvider
17128
+ ? provider
17129
+ : new BrowserProvider(provider);
17130
+ return await browserProvider.getSigner();
17035
17131
  }
17036
17132
  /**
17037
17133
  * Adds a new EVM chain to the user's browser wallet using the EIP-3085 `wallet_addEthereumChain` method.
@@ -17046,9 +17142,9 @@ async function switchOrAddChainInBrowser(signer, chain) {
17046
17142
  *
17047
17143
  * @throws {Error} If the provider does not support the `send` method or if the request fails.
17048
17144
  */
17049
- async function addChainInBrowser(signerWithProvider, chain) {
17145
+ async function addChainInBrowser(providerLike, chain) {
17050
17146
  const rpcUrl = chain.rpcEndpoints[0];
17051
- await signerWithProvider.provider.send('wallet_addEthereumChain', [
17147
+ await providerLike.provider.send('wallet_addEthereumChain', [
17052
17148
  {
17053
17149
  chainId: `0x${chain.chainId.toString(16)}`,
17054
17150
  chainName: chain.name,
@@ -17060,24 +17156,9 @@ async function addChainInBrowser(signerWithProvider, chain) {
17060
17156
  },
17061
17157
  ]);
17062
17158
  }
17063
- /**
17064
- * Returns a Signer instance from the browser's injected Ethereum provider.
17065
- *
17066
- * @param win - The browser window object with an injected `ethereum` provider.
17067
- * @returns A promise resolving Signer instance connected to the browser's provider.
17068
- *
17069
- * @remarks
17070
- * This function wraps the Ethers.js `BrowserProvider` to obtain a Signer for user interaction.
17071
- *
17072
- * @throws {Error} If the `ethereum` provider is not available or if the signer cannot be retrieved.
17073
- */
17074
- async function getBrowserSigner(win) {
17075
- const browserProvider = new BrowserProvider(win.ethereum);
17076
- return await browserProvider.getSigner();
17077
- }
17078
17159
  /**
17079
17160
  * Switches the chain for the given signer and returns a new signer for the target chain.
17080
- * Handles both browser and server-side environments.
17161
+ * Handles browser (injected + WalletConnect/Dynamic) and server-side environments.
17081
17162
  *
17082
17163
  * @param signer - The current signer instance
17083
17164
  * @param chain - The target chain definition
@@ -17085,8 +17166,21 @@ async function getBrowserSigner(win) {
17085
17166
  * @throws If switching fails or the environment is unsupported
17086
17167
  */
17087
17168
  async function switchChain(signer, chain) {
17169
+ // Injected browser wallet (window.ethereum present)
17088
17170
  if (isBrowserWithEthereum()) {
17089
- return switchOrAddChainInBrowser(signer, chain);
17171
+ const signerWithProvider = signer;
17172
+ if (!signerWithProvider?.provider?.send) {
17173
+ throw new Error('Browser provider does not support chain switching');
17174
+ }
17175
+ return switchOrAddViaProvider(signerWithProvider.provider, chain);
17176
+ }
17177
+ // Browser without window.ethereum (e.g., WalletConnect/Dynamic mobile wallets)
17178
+ const signerWithProvider = signer;
17179
+ const signerProvider = signerWithProvider.provider;
17180
+ if (globalThis.window !== undefined &&
17181
+ signerProvider &&
17182
+ 'send' in signerProvider) {
17183
+ return switchOrAddViaProvider(signerProvider, chain);
17090
17184
  }
17091
17185
  // Server-side: recreate the provider and signer
17092
17186
  const rpcUrl = chain.rpcEndpoints[0];
@@ -18062,6 +18156,36 @@ class EthersAdapter extends EvmAdapter {
18062
18156
  });
18063
18157
  }
18064
18158
  }
18159
+ /**
18160
+ * Reads the on-chain bytecode for a given address via ethers' `getCode`.
18161
+ *
18162
+ * Returns the hex-encoded bytecode when the address is a contract, or
18163
+ * `'0x'` when the address has no code (EOA). Used by Gateway burn-intent
18164
+ * signing to detect smart-contract accounts, which are not supported by
18165
+ * Gateway's ecrecover-based verification path.
18166
+ */
18167
+ async readBytecode(address, chain) {
18168
+ const provider = await this.getProvider(chain);
18169
+ try {
18170
+ const code = await provider.getCode(address);
18171
+ return code;
18172
+ }
18173
+ catch (error) {
18174
+ const errorMessage = error instanceof Error ? error.message : String(error);
18175
+ throw new KitError({
18176
+ ...RpcError.ENDPOINT_ERROR,
18177
+ recoverability: 'RETRYABLE',
18178
+ message: `Failed to read bytecode for ${address}: ${errorMessage}`,
18179
+ cause: {
18180
+ trace: {
18181
+ operation: 'readBytecode',
18182
+ address,
18183
+ chain: chain.name,
18184
+ },
18185
+ },
18186
+ });
18187
+ }
18188
+ }
18065
18189
  /**
18066
18190
  * Signs EIP-712 typed data using the configured signer with OperationContext.
18067
18191
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@circle-fin/adapter-ethers-v6",
3
- "version": "1.6.6",
3
+ "version": "1.8.0",
4
4
  "description": "EVM blockchain adapter powered by Ethers v6",
5
5
  "keywords": [
6
6
  "circle",