@circle-fin/adapter-ethers-v6 1.7.0 → 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 +10 -0
- package/index.cjs +65 -41
- package/index.d.ts +40 -0
- package/index.mjs +65 -41
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
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
|
+
|
|
3
13
|
## 1.7.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/index.cjs
CHANGED
|
@@ -17102,41 +17102,37 @@ function isBrowserWithEthereum() {
|
|
|
17102
17102
|
return (typeof window !== 'undefined' && !!window.ethereum);
|
|
17103
17103
|
}
|
|
17104
17104
|
/**
|
|
17105
|
-
*
|
|
17105
|
+
* Switch or add a chain via an EIP-1193 provider, then return a fresh signer.
|
|
17106
17106
|
*
|
|
17107
|
-
* @param
|
|
17108
|
-
* @param chain - The EVM chain definition
|
|
17109
|
-
* @returns A promise resolving to
|
|
17110
|
-
*
|
|
17111
|
-
* @remarks
|
|
17112
|
-
* This function uses the EIP-3326 `wallet_switchEthereumChain` and EIP-3085 `wallet_addEthereumChain` methods
|
|
17113
|
-
* to prompt the user to switch or add the specified chain in their browser wallet.
|
|
17114
|
-
*
|
|
17115
|
-
* @throws {Error} If the provider does not support chain switching, or if the user rejects the request,
|
|
17116
|
-
* 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.
|
|
17117
17111
|
*/
|
|
17118
|
-
async function
|
|
17119
|
-
const win = window;
|
|
17120
|
-
const signerWithProvider = signer;
|
|
17121
|
-
if (!signerWithProvider?.provider?.send) {
|
|
17122
|
-
throw new Error('Browser provider does not support chain switching');
|
|
17123
|
-
}
|
|
17112
|
+
async function switchOrAddViaProvider(provider, chain) {
|
|
17124
17113
|
try {
|
|
17125
|
-
await
|
|
17114
|
+
await provider.send('wallet_switchEthereumChain', [
|
|
17126
17115
|
{ chainId: `0x${chain.chainId.toString(16)}` },
|
|
17127
17116
|
]);
|
|
17128
|
-
return await getBrowserSigner(win);
|
|
17129
17117
|
}
|
|
17130
17118
|
catch (error) {
|
|
17131
17119
|
if (typeof error === 'object' &&
|
|
17132
17120
|
error !== null &&
|
|
17133
17121
|
'code' in error &&
|
|
17134
17122
|
error.code === UNRECOGNIZED_CHAIN_ID_ERROR_CODE) {
|
|
17135
|
-
await addChainInBrowser(
|
|
17136
|
-
|
|
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;
|
|
17137
17130
|
}
|
|
17138
|
-
throw error;
|
|
17139
17131
|
}
|
|
17132
|
+
const browserProvider = provider instanceof ethers.BrowserProvider
|
|
17133
|
+
? provider
|
|
17134
|
+
: new ethers.BrowserProvider(provider);
|
|
17135
|
+
return await browserProvider.getSigner();
|
|
17140
17136
|
}
|
|
17141
17137
|
/**
|
|
17142
17138
|
* Adds a new EVM chain to the user's browser wallet using the EIP-3085 `wallet_addEthereumChain` method.
|
|
@@ -17151,9 +17147,9 @@ async function switchOrAddChainInBrowser(signer, chain) {
|
|
|
17151
17147
|
*
|
|
17152
17148
|
* @throws {Error} If the provider does not support the `send` method or if the request fails.
|
|
17153
17149
|
*/
|
|
17154
|
-
async function addChainInBrowser(
|
|
17150
|
+
async function addChainInBrowser(providerLike, chain) {
|
|
17155
17151
|
const rpcUrl = chain.rpcEndpoints[0];
|
|
17156
|
-
await
|
|
17152
|
+
await providerLike.provider.send('wallet_addEthereumChain', [
|
|
17157
17153
|
{
|
|
17158
17154
|
chainId: `0x${chain.chainId.toString(16)}`,
|
|
17159
17155
|
chainName: chain.name,
|
|
@@ -17165,24 +17161,9 @@ async function addChainInBrowser(signerWithProvider, chain) {
|
|
|
17165
17161
|
},
|
|
17166
17162
|
]);
|
|
17167
17163
|
}
|
|
17168
|
-
/**
|
|
17169
|
-
* Returns a Signer instance from the browser's injected Ethereum provider.
|
|
17170
|
-
*
|
|
17171
|
-
* @param win - The browser window object with an injected `ethereum` provider.
|
|
17172
|
-
* @returns A promise resolving Signer instance connected to the browser's provider.
|
|
17173
|
-
*
|
|
17174
|
-
* @remarks
|
|
17175
|
-
* This function wraps the Ethers.js `BrowserProvider` to obtain a Signer for user interaction.
|
|
17176
|
-
*
|
|
17177
|
-
* @throws {Error} If the `ethereum` provider is not available or if the signer cannot be retrieved.
|
|
17178
|
-
*/
|
|
17179
|
-
async function getBrowserSigner(win) {
|
|
17180
|
-
const browserProvider = new ethers.BrowserProvider(win.ethereum);
|
|
17181
|
-
return await browserProvider.getSigner();
|
|
17182
|
-
}
|
|
17183
17164
|
/**
|
|
17184
17165
|
* Switches the chain for the given signer and returns a new signer for the target chain.
|
|
17185
|
-
* Handles
|
|
17166
|
+
* Handles browser (injected + WalletConnect/Dynamic) and server-side environments.
|
|
17186
17167
|
*
|
|
17187
17168
|
* @param signer - The current signer instance
|
|
17188
17169
|
* @param chain - The target chain definition
|
|
@@ -17190,8 +17171,21 @@ async function getBrowserSigner(win) {
|
|
|
17190
17171
|
* @throws If switching fails or the environment is unsupported
|
|
17191
17172
|
*/
|
|
17192
17173
|
async function switchChain(signer, chain) {
|
|
17174
|
+
// Injected browser wallet (window.ethereum present)
|
|
17193
17175
|
if (isBrowserWithEthereum()) {
|
|
17194
|
-
|
|
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);
|
|
17195
17189
|
}
|
|
17196
17190
|
// Server-side: recreate the provider and signer
|
|
17197
17191
|
const rpcUrl = chain.rpcEndpoints[0];
|
|
@@ -18167,6 +18161,36 @@ class EthersAdapter extends EvmAdapter {
|
|
|
18167
18161
|
});
|
|
18168
18162
|
}
|
|
18169
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
|
+
}
|
|
18170
18194
|
/**
|
|
18171
18195
|
* Signs EIP-712 typed data using the configured signer with OperationContext.
|
|
18172
18196
|
*
|
package/index.d.ts
CHANGED
|
@@ -3974,6 +3974,37 @@ declare abstract class EvmAdapter<TAdapterCapabilities extends AdapterCapabiliti
|
|
|
3974
3974
|
* @throws Error when balance retrieval fails.
|
|
3975
3975
|
*/
|
|
3976
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}`>;
|
|
3977
4008
|
/**
|
|
3978
4009
|
* Calculate the total transaction fee including compute cost and buffer for the configured chain.
|
|
3979
4010
|
*
|
|
@@ -4573,6 +4604,15 @@ declare class EthersAdapter<TAdapterCapabilities extends AdapterCapabilities = A
|
|
|
4573
4604
|
* ```
|
|
4574
4605
|
*/
|
|
4575
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}`>;
|
|
4576
4616
|
/**
|
|
4577
4617
|
* Signs EIP-712 typed data using the configured signer with OperationContext.
|
|
4578
4618
|
*
|
package/index.mjs
CHANGED
|
@@ -17097,41 +17097,37 @@ function isBrowserWithEthereum() {
|
|
|
17097
17097
|
return (typeof window !== 'undefined' && !!window.ethereum);
|
|
17098
17098
|
}
|
|
17099
17099
|
/**
|
|
17100
|
-
*
|
|
17100
|
+
* Switch or add a chain via an EIP-1193 provider, then return a fresh signer.
|
|
17101
17101
|
*
|
|
17102
|
-
* @param
|
|
17103
|
-
* @param chain - The EVM chain definition
|
|
17104
|
-
* @returns A promise resolving to
|
|
17105
|
-
*
|
|
17106
|
-
* @remarks
|
|
17107
|
-
* This function uses the EIP-3326 `wallet_switchEthereumChain` and EIP-3085 `wallet_addEthereumChain` methods
|
|
17108
|
-
* to prompt the user to switch or add the specified chain in their browser wallet.
|
|
17109
|
-
*
|
|
17110
|
-
* @throws {Error} If the provider does not support chain switching, or if the user rejects the request,
|
|
17111
|
-
* 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.
|
|
17112
17106
|
*/
|
|
17113
|
-
async function
|
|
17114
|
-
const win = window;
|
|
17115
|
-
const signerWithProvider = signer;
|
|
17116
|
-
if (!signerWithProvider?.provider?.send) {
|
|
17117
|
-
throw new Error('Browser provider does not support chain switching');
|
|
17118
|
-
}
|
|
17107
|
+
async function switchOrAddViaProvider(provider, chain) {
|
|
17119
17108
|
try {
|
|
17120
|
-
await
|
|
17109
|
+
await provider.send('wallet_switchEthereumChain', [
|
|
17121
17110
|
{ chainId: `0x${chain.chainId.toString(16)}` },
|
|
17122
17111
|
]);
|
|
17123
|
-
return await getBrowserSigner(win);
|
|
17124
17112
|
}
|
|
17125
17113
|
catch (error) {
|
|
17126
17114
|
if (typeof error === 'object' &&
|
|
17127
17115
|
error !== null &&
|
|
17128
17116
|
'code' in error &&
|
|
17129
17117
|
error.code === UNRECOGNIZED_CHAIN_ID_ERROR_CODE) {
|
|
17130
|
-
await addChainInBrowser(
|
|
17131
|
-
|
|
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;
|
|
17132
17125
|
}
|
|
17133
|
-
throw error;
|
|
17134
17126
|
}
|
|
17127
|
+
const browserProvider = provider instanceof BrowserProvider
|
|
17128
|
+
? provider
|
|
17129
|
+
: new BrowserProvider(provider);
|
|
17130
|
+
return await browserProvider.getSigner();
|
|
17135
17131
|
}
|
|
17136
17132
|
/**
|
|
17137
17133
|
* Adds a new EVM chain to the user's browser wallet using the EIP-3085 `wallet_addEthereumChain` method.
|
|
@@ -17146,9 +17142,9 @@ async function switchOrAddChainInBrowser(signer, chain) {
|
|
|
17146
17142
|
*
|
|
17147
17143
|
* @throws {Error} If the provider does not support the `send` method or if the request fails.
|
|
17148
17144
|
*/
|
|
17149
|
-
async function addChainInBrowser(
|
|
17145
|
+
async function addChainInBrowser(providerLike, chain) {
|
|
17150
17146
|
const rpcUrl = chain.rpcEndpoints[0];
|
|
17151
|
-
await
|
|
17147
|
+
await providerLike.provider.send('wallet_addEthereumChain', [
|
|
17152
17148
|
{
|
|
17153
17149
|
chainId: `0x${chain.chainId.toString(16)}`,
|
|
17154
17150
|
chainName: chain.name,
|
|
@@ -17160,24 +17156,9 @@ async function addChainInBrowser(signerWithProvider, chain) {
|
|
|
17160
17156
|
},
|
|
17161
17157
|
]);
|
|
17162
17158
|
}
|
|
17163
|
-
/**
|
|
17164
|
-
* Returns a Signer instance from the browser's injected Ethereum provider.
|
|
17165
|
-
*
|
|
17166
|
-
* @param win - The browser window object with an injected `ethereum` provider.
|
|
17167
|
-
* @returns A promise resolving Signer instance connected to the browser's provider.
|
|
17168
|
-
*
|
|
17169
|
-
* @remarks
|
|
17170
|
-
* This function wraps the Ethers.js `BrowserProvider` to obtain a Signer for user interaction.
|
|
17171
|
-
*
|
|
17172
|
-
* @throws {Error} If the `ethereum` provider is not available or if the signer cannot be retrieved.
|
|
17173
|
-
*/
|
|
17174
|
-
async function getBrowserSigner(win) {
|
|
17175
|
-
const browserProvider = new BrowserProvider(win.ethereum);
|
|
17176
|
-
return await browserProvider.getSigner();
|
|
17177
|
-
}
|
|
17178
17159
|
/**
|
|
17179
17160
|
* Switches the chain for the given signer and returns a new signer for the target chain.
|
|
17180
|
-
* Handles
|
|
17161
|
+
* Handles browser (injected + WalletConnect/Dynamic) and server-side environments.
|
|
17181
17162
|
*
|
|
17182
17163
|
* @param signer - The current signer instance
|
|
17183
17164
|
* @param chain - The target chain definition
|
|
@@ -17185,8 +17166,21 @@ async function getBrowserSigner(win) {
|
|
|
17185
17166
|
* @throws If switching fails or the environment is unsupported
|
|
17186
17167
|
*/
|
|
17187
17168
|
async function switchChain(signer, chain) {
|
|
17169
|
+
// Injected browser wallet (window.ethereum present)
|
|
17188
17170
|
if (isBrowserWithEthereum()) {
|
|
17189
|
-
|
|
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);
|
|
17190
17184
|
}
|
|
17191
17185
|
// Server-side: recreate the provider and signer
|
|
17192
17186
|
const rpcUrl = chain.rpcEndpoints[0];
|
|
@@ -18162,6 +18156,36 @@ class EthersAdapter extends EvmAdapter {
|
|
|
18162
18156
|
});
|
|
18163
18157
|
}
|
|
18164
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
|
+
}
|
|
18165
18189
|
/**
|
|
18166
18190
|
* Signs EIP-712 typed data using the configured signer with OperationContext.
|
|
18167
18191
|
*
|