@reservoir0x/relay-sdk
Version:
Relay is the Fastest and Cheapest Way to Bridge and Transact Across Chains.
182 lines • 7.4 kB
JavaScript
import { LogLevel } from './logger.js';
import { getClient } from '../client.js';
import { createPublicClient, custom, fallback, hexToBigInt, http } from 'viem';
import { eip5792Actions } from 'viem/experimental';
export function isViemWalletClient(wallet) {
return (wallet.extend !== undefined &&
wallet.getPermissions !== undefined);
}
export const adaptViemWallet = (wallet) => {
return {
vmType: 'evm',
getChainId: async () => {
return wallet.getChainId();
},
transport: custom(wallet.transport),
address: async () => {
let address = wallet.account?.address;
if (!address) {
;
[address] = await wallet.getAddresses();
}
return address;
},
handleSignMessageStep: async (stepItem) => {
const client = getClient();
const signData = stepItem.data?.sign;
let signature;
if (signData) {
if (signData.signatureKind === 'eip191') {
client.log(['Execute Steps: Signing with eip191'], LogLevel.Verbose);
if (signData.message.match(/0x[0-9a-fA-F]{64}/)) {
// If the message represents a hash, we need to convert it to raw bytes first
signature = await wallet.signMessage({
account: wallet.account,
message: {
raw: signData.message
}
});
}
else {
signature = await wallet.signMessage({
account: wallet.account,
message: signData.message
});
}
}
else if (signData.signatureKind === 'eip712') {
client.log(['Execute Steps: Signing with eip712'], LogLevel.Verbose);
signature = await wallet.signTypedData({
account: wallet.account,
domain: signData.domain,
types: signData.types,
primaryType: signData.primaryType,
message: signData.value
});
}
}
return signature;
},
handleSendTransactionStep: async (chainId, stepItem) => {
const stepData = stepItem.data;
const client = getClient();
const chain = getClient().chains.find((chain) => chain.id === chainId)?.viemChain;
if (!chain) {
throw 'Chain not found when sending transaction';
}
return await wallet.sendTransaction({
chain,
data: stepData.data,
account: wallet.account ?? stepData.from, // use signer.account if it's defined
to: stepData.to,
value: hexToBigInt(stepData.value || 0),
...(stepData.maxFeePerGas &&
client.useGasFeeEstimations && {
maxFeePerGas: hexToBigInt(stepData.maxFeePerGas)
}),
...(stepData.maxPriorityFeePerGas &&
client.useGasFeeEstimations && {
maxPriorityFeePerGas: hexToBigInt(stepData.maxPriorityFeePerGas)
}),
...(stepData.gas &&
client.useGasFeeEstimations && {
gas: hexToBigInt(stepData.gas)
})
});
},
handleConfirmTransactionStep: async (txHash, chainId, onReplaced, onCancelled) => {
const client = getClient();
const chain = client.chains.find((chain) => chain.id === chainId);
const viemClient = createPublicClient({
chain: chain?.viemChain,
transport: wallet.transport
? fallback([custom(wallet.transport), http()])
: http()
});
const receipt = await viemClient.waitForTransactionReceipt({
hash: txHash,
onReplaced: (replacement) => {
if (replacement.reason === 'cancelled') {
onCancelled();
throw Error('Transaction cancelled');
}
onReplaced(replacement.transaction.hash);
}
});
return receipt;
},
switchChain: async (chainId) => {
try {
await wallet.switchChain({
id: chainId
});
return;
}
catch (e) {
if (e && e?.message) {
if (e.message.includes('does not support the requested chain')) {
throw new Error('Wallet does not support chain');
}
else if (e.message.includes('rejected')) {
throw e;
}
else if (e.message.includes('already pending')) {
return;
}
}
const client = getClient();
const chain = client.chains.find((chain) => chain.id === chainId);
if (!chain) {
throw 'Chain missing from Relay Client';
}
await wallet.addChain({
chain: chain?.viemChain
});
return;
}
},
supportsAtomicBatch: async (chainId) => {
if (!wallet.account)
return false;
try {
const eip5792Wallet = wallet.extend(eip5792Actions());
const capabilities = await eip5792Wallet.getCapabilities({
account: eip5792Wallet.account
});
return capabilities[chainId]?.atomicBatch?.supported;
}
catch {
return false;
}
},
handleBatchTransactionStep: async (chainId, items) => {
const calls = items.map((item) => ({
to: item.data.to,
data: item.data.data,
value: hexToBigInt(item.data.value || 0),
...(item.data.maxFeePerGas && {
maxFeePerGas: hexToBigInt(item.data.maxFeePerGas)
}),
...(item.data.maxPriorityFeePerGas && {
maxPriorityFeePerGas: hexToBigInt(item.data.maxPriorityFeePerGas)
}),
...(item.data.gas && {
gas: hexToBigInt(item.data.gas)
})
}));
const eip5792Wallet = wallet.extend(eip5792Actions());
const client = getClient();
const chain = client.chains.find((chain) => chain.id === chainId)?.viemChain;
if (!chain) {
throw 'Chain not found when sending transaction';
}
const id = await eip5792Wallet.sendCalls({
chain,
account: wallet.account,
calls
});
return id;
}
};
};
//# sourceMappingURL=viemWallet.js.map