diff --git a/.changeset/four-gifts-try.md b/.changeset/four-gifts-try.md new file mode 100644 index 00000000..3ff6c667 --- /dev/null +++ b/.changeset/four-gifts-try.md @@ -0,0 +1,6 @@ +--- +'@moonbeam-network/xcm-config': minor +'@moonbeam-network/xcm-sdk': minor +--- + +Allow viem Wallet Client as signer diff --git a/examples/sdk-simple/index.ts b/examples/sdk-simple/index.ts index 688fae8b..087c16d1 100644 --- a/examples/sdk-simple/index.ts +++ b/examples/sdk-simple/index.ts @@ -13,7 +13,7 @@ const provider = new ethers.providers.WebSocketProvider(moonbeam.ws, { chainId: moonbeam.id, name: moonbeam.name, }); -const ethersSigner = new ethers.Wallet(moonbeamPrivateKey, provider); +const evmSigner = new ethers.Wallet(moonbeamPrivateKey, provider); // Polkadot Signer =========================================================== @@ -65,7 +65,7 @@ export async function fromPolkadot() { console.log('\nTransfer from Polkadot to Moonbeam\n'); const data = await Sdk().getTransferData({ - destinationAddress: ethersSigner.address, + destinationAddress: evmSigner.address, destinationKeyOrChain: moonbeam, keyOrAsset: dot, polkadotSigner: pair, @@ -93,8 +93,8 @@ export async function fromMoonbeam() { .asset(dot) .source(moonbeam) .destination(polkadot) - .accounts(ethersSigner.address, pair.address, { - ethersSigner, + .accounts(evmSigner.address, pair.address, { + evmSigner, }); logBalances(data); @@ -114,7 +114,7 @@ async function main() { console.warn = () => null; console.clear(); - console.log(`\nMoonbeam address: ${ethersSigner.address}.`); + console.log(`\nMoonbeam address: ${evmSigner.address}.`); console.log(`Polkadot address: ${pair.address}.`); await fromPolkadot(); diff --git a/package-lock.json b/package-lock.json index d908620b..81f900fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,8 +15,7 @@ "@polkadot/api-augment": "^10.9.1", "@polkadot/types": "^10.9.1", "@polkadot/util": "^12.3.2", - "@polkadot/util-crypto": "^12.3.2", - "ethers": "^5.7.2" + "@polkadot/util-crypto": "^12.3.2" }, "devDependencies": { "@changesets/changelog-github": "^0.4.8", @@ -32,6 +31,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-jest": "^27.2.1", "eslint-plugin-prettier": "^4.2.1", + "ethers": "^5.7.2", "glob": "^10.3.3", "husky": "^8.0.3", "jest": "^29.6.1", @@ -41,7 +41,8 @@ "ts-node": "^10.9.1", "tsup": "^6.7.0", "turbo": "^1.9.9", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "viem": "^1.10.3" } }, "examples/sdk-simple": { @@ -4983,6 +4984,61 @@ } ] }, + "node_modules/@scure/bip32": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.2.tgz", + "integrity": "sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==", + "dependencies": { + "@noble/curves": "~1.2.0", + "@noble/hashes": "~1.3.2", + "@scure/base": "~1.1.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip32/node_modules/@scure/base": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.3.tgz", + "integrity": "sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q==", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", + "dependencies": { + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/@sinclair/typebox": { "version": "0.27.8", "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", @@ -5794,6 +5850,14 @@ "@types/node": "*" } }, + "node_modules/@types/ws": { + "version": "8.5.5", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.5.tgz", + "integrity": "sha512-lwhs8hktwxSjf9UaZ9tG5M03PGogvFaH8gUgLNbN9HKIg0dvv6q+gkSuJ8HN4/VbyxkuLzCjlN7GquQ0gUJfIg==", + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/yargs": { "version": "17.0.24", "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz", @@ -6148,6 +6212,29 @@ "integrity": "sha512-OkqtOLPkR7oqWLrsgRKhzyLZVFLnNLfEF3DMXH+Rpn1fMNMDq/fOY9pXt55B+flBc62saN73CfOTy3hMSVZFTA==", "peer": true }, + "node_modules/abitype": { + "version": "0.9.8", + "resolved": "https://registry.npmjs.org/abitype/-/abitype-0.9.8.tgz", + "integrity": "sha512-puLifILdm+8sjyss4S+fsUN09obiT1g2YW6CtcQF+QDzxR0euzgEB29MZujC6zMk2a6SVmtttq1fc6+YFA7WYQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "peerDependencies": { + "typescript": ">=5.0.4", + "zod": "^3 >=3.19.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "zod": { + "optional": true + } + } + }, "node_modules/acorn": { "version": "8.8.2", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", @@ -9621,6 +9708,14 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", + "peerDependencies": { + "ws": "*" + } + }, "node_modules/istanbul-lib-coverage": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz", @@ -16105,7 +16200,7 @@ "version": "5.1.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.3.tgz", "integrity": "sha512-XH627E9vkeqhlZFQuL+UsyAXEnibT0kWR2FWONlr4sTjvxyJYnyefgrkyECLzM5NenmKzRAy2rR/OlYLA1HkZw==", - "dev": true, + "devOptional": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -16241,6 +16336,57 @@ "spdx-expression-parse": "^3.0.0" } }, + "node_modules/viem": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/viem/-/viem-1.10.3.tgz", + "integrity": "sha512-7L35k0JmxTa7xIx1s8lCsTLGrTEUXTYnLppZ56EVBjtvE2OKSfDjL8No0Fnedu6Ye0zi/VX2BQC3arhpKOVIlw==", + "dependencies": { + "@adraffy/ens-normalize": "1.9.4", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", + "@scure/bip32": "1.3.2", + "@scure/bip39": "1.2.1", + "@types/ws": "^8.5.5", + "abitype": "0.9.8", + "isomorphic-ws": "5.0.0", + "ws": "8.13.0" + }, + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/viem/node_modules/@adraffy/ens-normalize": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.4.tgz", + "integrity": "sha512-UK0bHA7hh9cR39V+4gl2/NnBBjoXIxkuWAPCaY4X7fbH4L/azIi7ilWOCjMUYfpJgraLUAqkRi2BqrjME8Rynw==" + }, + "node_modules/viem/node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "dependencies": { + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/viem/node_modules/@noble/hashes": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, "node_modules/walker": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", @@ -16854,7 +17000,8 @@ "@polkadot/api-augment": "^10.9.1", "@polkadot/types": "^10.9.1", "@polkadot/util": "^12.3.2", - "ethers": "^5.7.2" + "ethers": "^5.7.2", + "viem": "^1.10.3" } }, "packages/types": { diff --git a/package.json b/package.json index 30812518..32c6d66d 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,7 @@ "@polkadot/api-augment": "^10.9.1", "@polkadot/types": "^10.9.1", "@polkadot/util": "^12.3.2", - "@polkadot/util-crypto": "^12.3.2", - "ethers": "^5.7.2" + "@polkadot/util-crypto": "^12.3.2" }, "devDependencies": { "@changesets/changelog-github": "^0.4.8", @@ -55,6 +54,7 @@ "eslint-plugin-import": "^2.27.5", "eslint-plugin-jest": "^27.2.1", "eslint-plugin-prettier": "^4.2.1", + "ethers": "^5.7.2", "glob": "^10.3.3", "husky": "^8.0.3", "jest": "^29.6.1", @@ -64,7 +64,8 @@ "ts-node": "^10.9.1", "tsup": "^6.7.0", "turbo": "^1.9.9", - "typescript": "^5.0.4" + "typescript": "^5.0.4", + "viem": "^1.10.3" }, "lint-staged": { "*.{js,ts}": "eslint --cache --fix --max-warnings=0", diff --git a/packages/config/src/configs/moonbaseBeta.ts b/packages/config/src/configs/moonbaseBeta.ts index 1900a417..ef9cbadd 100644 --- a/packages/config/src/configs/moonbaseBeta.ts +++ b/packages/config/src/configs/moonbaseBeta.ts @@ -29,7 +29,7 @@ export const moonbaseBetaConfig = new ChainConfig({ balance: BalanceBuilder().substrate().assets().account(), destination: moonbaseAlpha, destinationFee: { - amount: 0.0002, + amount: 0.002, asset: dev, balance: BalanceBuilder().substrate().system().account(), }, diff --git a/packages/sdk/README.md b/packages/sdk/README.md index 7b6bfe2e..136a0a66 100644 --- a/packages/sdk/README.md +++ b/packages/sdk/README.md @@ -47,7 +47,7 @@ const dataViaAssetsMethod = await assets() .source('INSERT_SOURCE_CHAIN') .destination('INSERT_DESTINATION_CHAIN') .accounts('INSERT_SOURCE_ADDRESS', 'INSERT_DESTINATION_ADDRESS', { - ethersSigner?: 'INSERT_ETHERS_SIGNER', + evmSigner?: 'INSERT_EVM_SIGNER', polkadotSigner?: 'INSERT_POLKADOT_SIGNER', }); @@ -55,7 +55,7 @@ const dataViaAssetsMethod = await assets() const dataViaGetTransferDataMethod = await getTransferData({ destinationAddress: 'INSERT_DESTINATION_ADDRESS', destinationKeyOrChain: 'INSERT_DESTINATION_CHAIN', - ethersSigner?: 'INSERT_ETHERS_SIGNER', + evmSigner?: 'INSERT_EVM_SIGNER', keyOrAsset: 'INSERT_ASSET', polkadotSigner?: 'INSERT_POLKADOT_SIGNER', sourceAddress: 'INSERT_SOURCE_ADDRESS', diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 1916364e..3b3954b8 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -58,6 +58,7 @@ "@polkadot/api-augment": "^10.9.1", "@polkadot/types": "^10.9.1", "@polkadot/util": "^12.3.2", - "ethers": "^5.7.2" + "ethers": "^5.7.2", + "viem": "^1.10.3" } } diff --git a/packages/sdk/src/contract/contract.factory.ts b/packages/sdk/src/contract/contract.factory.ts index 250fdd56..a90a76d7 100644 --- a/packages/sdk/src/contract/contract.factory.ts +++ b/packages/sdk/src/contract/contract.factory.ts @@ -1,5 +1,5 @@ import { ContractConfig } from '@moonbeam-network/xcm-builder'; -import { Signer } from 'ethers'; +import { EvmSigner } from '../sdk.interfaces'; import { BalanceContractInterface, TransferContractInterface, @@ -8,7 +8,7 @@ import { Erc20, Xtokens } from './contracts'; export function createContract( config: ContractConfig, - signer: Signer, + signer: EvmSigner, ): TransferContractInterface | BalanceContractInterface { if (config.module === 'Erc20') { return new Erc20(config, signer); diff --git a/packages/sdk/src/contract/contract.interfaces.ts b/packages/sdk/src/contract/contract.interfaces.ts index 018e6626..2b08e16c 100644 --- a/packages/sdk/src/contract/contract.interfaces.ts +++ b/packages/sdk/src/contract/contract.interfaces.ts @@ -1,11 +1,13 @@ import type { TransactionResponse } from '@ethersproject/abstract-provider'; +import { Contract, Signer as EthersSigner } from 'ethers'; +import { PublicClient, WalletClient, WriteContractReturnType } from 'viem'; export interface BaseContractInterface { readonly address: string; } export interface TransferContractInterface extends BaseContractInterface { - transfer(): Promise; + transfer(): Promise; getFee(amount: bigint): Promise; } @@ -13,3 +15,15 @@ export interface BalanceContractInterface extends BaseContractInterface { getBalance(): Promise; getDecimals(): Promise; } + +export type ContractClient = EthersClient | ViemClient; + +export interface EthersClient { + contract: Contract; + signer: EthersSigner; +} + +export interface ViemClient { + publicClient: PublicClient; + walletClient: WalletClient; +} diff --git a/packages/sdk/src/contract/contract.utils.ts b/packages/sdk/src/contract/contract.utils.ts new file mode 100644 index 00000000..3a275b74 --- /dev/null +++ b/packages/sdk/src/contract/contract.utils.ts @@ -0,0 +1,17 @@ +import { Contract, Signer as EthersSigner } from 'ethers'; +import { Abi, GetContractReturnType, WalletClient } from 'viem'; +import { EvmSigner } from '../sdk.interfaces'; + +export function isEthersSigner(signer: EvmSigner): signer is EthersSigner { + return 'provider' in signer; +} + +export function isWalletClient(signer: EvmSigner): signer is WalletClient { + return 'chain' in signer; +} + +export function isEthersContract( + contract: Contract | GetContractReturnType, +): contract is Contract { + return 'signer' in contract; +} diff --git a/packages/sdk/src/contract/contracts/Erc20/Erc20.ts b/packages/sdk/src/contract/contracts/Erc20/Erc20.ts index d9b41070..a7ddc7dd 100644 --- a/packages/sdk/src/contract/contracts/Erc20/Erc20.ts +++ b/packages/sdk/src/contract/contracts/Erc20/Erc20.ts @@ -1,33 +1,65 @@ import { ContractConfig } from '@moonbeam-network/xcm-builder'; -import { Contract, Signer } from 'ethers'; +import { Contract } from 'ethers'; +import { + GetContractReturnType, + PublicClient, + WalletClient, + createPublicClient, + getContract, + http, +} from 'viem'; +import { EvmSigner } from '../../../sdk.interfaces'; import { BalanceContractInterface } from '../../contract.interfaces'; +import { isEthersContract, isEthersSigner } from '../../contract.utils'; import abi from './Erc20ABI.json'; +type Erc20Contract = GetContractReturnType< + typeof abi, + PublicClient, + WalletClient +>; + export class Erc20 implements BalanceContractInterface { readonly address: string; readonly #config: ContractConfig; - readonly #contract: Contract; + readonly #contract: Contract | Erc20Contract; - constructor(config: ContractConfig, signer: Signer) { + constructor(config: ContractConfig, signer: EvmSigner) { if (!config.address) { throw new Error('Contract address is required'); } this.address = config.address; this.#config = config; - this.#contract = new Contract(this.address, abi, signer); + this.#contract = isEthersSigner(signer) + ? new Contract(this.address, abi, signer) + : getContract({ + abi, + address: this.address as `0x${string}`, + publicClient: createPublicClient({ + chain: signer.chain, + transport: http(), + }), + walletClient: signer, + }); } async getBalance(): Promise { - const balance = await this.#contract.balanceOf(...this.#config.args); - - return balance.toBigInt(); + if (isEthersContract(this.#contract)) { + const balance = await this.#contract.balanceOf(...this.#config.args); + return balance.toBigInt(); + } + return this.#contract.read.balanceOf( + this.#config.args, + ) as unknown as bigint; } async getDecimals(): Promise { - const decimals = await this.#contract.decimals(); + const decimals = isEthersContract(this.#contract) + ? await this.#contract.decimals() + : this.#contract.read.decimals(); return decimals; } diff --git a/packages/sdk/src/contract/contracts/Xtokens/Xtokens.ts b/packages/sdk/src/contract/contracts/Xtokens/Xtokens.ts index 85e17851..3e4eee0a 100644 --- a/packages/sdk/src/contract/contracts/Xtokens/Xtokens.ts +++ b/packages/sdk/src/contract/contracts/Xtokens/Xtokens.ts @@ -1,26 +1,75 @@ import type { TransactionResponse } from '@ethersproject/abstract-provider'; import { ContractConfig } from '@moonbeam-network/xcm-builder'; -import { Contract, Signer } from 'ethers'; +import { Contract } from 'ethers'; +import { + GetContractReturnType, + PublicClient, + WalletClient, + WriteContractReturnType, + createPublicClient, + getContract, + http, +} from 'viem'; +import { EvmSigner } from '../../../sdk.interfaces'; import { TransferContractInterface } from '../../contract.interfaces'; +import { isEthersContract, isEthersSigner } from '../../contract.utils'; import abi from './XtokensABI.json'; +type XtokensContract = GetContractReturnType< + typeof abi, + PublicClient, + WalletClient +>; + export class Xtokens implements TransferContractInterface { - readonly address: string = '0x0000000000000000000000000000000000000804'; + readonly address = '0x0000000000000000000000000000000000000804'; readonly #config: ContractConfig; - readonly #contract: Contract; + readonly #contract: Contract | XtokensContract; - readonly #signer: Signer; + readonly #signer: EvmSigner; - constructor(config: ContractConfig, signer: Signer) { + constructor(config: ContractConfig, signer: EvmSigner) { this.#config = config; + this.#signer = signer; - this.#contract = new Contract(this.address, abi, signer); + + this.#contract = isEthersSigner(signer) + ? new Contract(this.address, abi, signer) + : getContract({ + abi, + address: this.address, + publicClient: createPublicClient({ + chain: signer.chain, + transport: http(), + }), + walletClient: signer, + }); + } + + async transfer(): Promise { + if (isEthersContract(this.#contract)) { + return this.#contract[this.#config.func](...this.#config.args); + } + + return this.#contract.write[this.#config.func](this.#config.args); } - async transfer(): Promise { - return this.#contract[this.#config.func](...this.#config.args); + async getEthersContractEstimatedGas(contract: Contract): Promise { + return ( + await contract.estimateGas[this.#config.func](...this.#config.args) + ).toBigInt(); + } + + async getViemContractEstimatedGas( + contract: XtokensContract, + ): Promise { + if (!contract) { + return 0n; + } + + return contract.estimateGas[this.#config.func](this.#config.args as any); } async getFee(amount: bigint): Promise { @@ -33,13 +82,10 @@ export class Xtokens implements TransferContractInterface { * Or if you try to send 0 as amount. */ try { - const estimatedGas = ( - await this.#contract.estimateGas[this.#config.func]( - ...this.#config.args, - ) - ).toBigInt(); + const estimatedGas = isEthersContract(this.#contract) + ? await this.getEthersContractEstimatedGas(this.#contract) + : await this.getViemContractEstimatedGas(this.#contract); const gasPrice = await this.getGasPrice(); - return estimatedGas * gasPrice; } catch (error) { // eslint-disable-next-line no-console @@ -52,10 +98,20 @@ export class Xtokens implements TransferContractInterface { } private async getGasPrice() { - const { gasPrice, maxPriorityFeePerGas } = await this.#signer.getFeeData(); + if (isEthersSigner(this.#signer)) { + const { gasPrice, maxPriorityFeePerGas } = + await this.#signer.getFeeData(); - return ( - (gasPrice?.toBigInt() || 0n) + (maxPriorityFeePerGas?.toBigInt() || 0n) - ); + return ( + (gasPrice?.toBigInt() || 0n) + (maxPriorityFeePerGas?.toBigInt() || 0n) + ); + } + + const publicClient = createPublicClient({ + chain: this.#signer.chain, + transport: http(), + }); + + return publicClient.getGasPrice(); } } diff --git a/packages/sdk/src/getTransferData/getDestinationData.ts b/packages/sdk/src/getTransferData/getDestinationData.ts index 0c018776..076792b0 100644 --- a/packages/sdk/src/getTransferData/getDestinationData.ts +++ b/packages/sdk/src/getTransferData/getDestinationData.ts @@ -3,22 +3,21 @@ import { FeeConfigBuilder } from '@moonbeam-network/xcm-builder'; import { TransferConfig } from '@moonbeam-network/xcm-config'; import { AssetAmount } from '@moonbeam-network/xcm-types'; import { toBigInt } from '@moonbeam-network/xcm-utils'; -import { Signer as EthersSigner } from 'ethers'; import { PolkadotService } from '../polkadot'; -import { DestinationChainTransferData } from '../sdk.interfaces'; +import { DestinationChainTransferData, EvmSigner } from '../sdk.interfaces'; import { getBalance, getDecimals, getMin } from './getTransferData.utils'; export interface GetDestinationDataParams { transferConfig: TransferConfig; destinationAddress: string; - ethersSigner: EthersSigner; + evmSigner: EvmSigner; polkadot: PolkadotService; } export async function getDestinationData({ transferConfig, destinationAddress, - ethersSigner, + evmSigner, polkadot, }: GetDestinationDataParams): Promise { const { @@ -31,7 +30,7 @@ export async function getDestinationData({ decimals: await getDecimals({ address: destinationAddress, config, - ethersSigner, + evmSigner, polkadot, }), }); @@ -39,7 +38,7 @@ export async function getDestinationData({ const balance = await getBalance({ address: destinationAddress, config, - ethersSigner, + evmSigner, polkadot, }); const min = await getMin(config, polkadot); diff --git a/packages/sdk/src/getTransferData/getSourceData.ts b/packages/sdk/src/getTransferData/getSourceData.ts index 60298f19..3e9b2eb6 100644 --- a/packages/sdk/src/getTransferData/getSourceData.ts +++ b/packages/sdk/src/getTransferData/getSourceData.ts @@ -8,17 +8,16 @@ import { FeeAssetConfig, TransferConfig } from '@moonbeam-network/xcm-config'; import { AssetAmount } from '@moonbeam-network/xcm-types'; import { convertDecimals } from '@moonbeam-network/xcm-utils'; import Big from 'big.js'; -import { Signer as EthersSigner } from 'ethers'; import { TransferContractInterface, createContract } from '../contract'; import { PolkadotService } from '../polkadot'; -import { SourceChainTransferData } from '../sdk.interfaces'; +import { EvmSigner, SourceChainTransferData } from '../sdk.interfaces'; import { getBalance, getDecimals, getMin } from './getTransferData.utils'; export interface GetSourceDataParams { transferConfig: TransferConfig; destinationAddress: string; destinationFee: AssetAmount; - ethersSigner: EthersSigner; + evmSigner: EvmSigner; polkadot: PolkadotService; sourceAddress: string; } @@ -27,7 +26,7 @@ export async function getSourceData({ transferConfig, destinationAddress, destinationFee, - ethersSigner, + evmSigner, polkadot, sourceAddress, }: GetSourceDataParams): Promise { @@ -41,7 +40,7 @@ export async function getSourceData({ decimals: await getDecimals({ address: destinationAddress, config, - ethersSigner, + evmSigner, polkadot, }), }); @@ -52,7 +51,7 @@ export async function getSourceData({ address: destinationAddress, asset: config.fee.asset, config, - ethersSigner, + evmSigner, polkadot, }), }) @@ -64,7 +63,7 @@ export async function getSourceData({ address: destinationAddress, asset: config.destinationFee.asset, config, - ethersSigner, + evmSigner, polkadot, }), }) @@ -73,7 +72,7 @@ export async function getSourceData({ const balance = await getBalance({ address: sourceAddress, config, - ethersSigner, + evmSigner, polkadot, }); @@ -107,6 +106,7 @@ export async function getSourceData({ palletInstance: chain.getAssetPalletInstance(asset), source: chain, }); + const contract = config.contract?.build({ address: destinationAddress, amount: balance, @@ -119,7 +119,7 @@ export async function getSourceData({ balance, contract, decimals: zeroFeeAmount.decimals, - ethersSigner, + evmSigner, extrinsic, polkadot, sourceAddress, @@ -179,7 +179,7 @@ export interface GetFeeParams { balance: bigint; contract?: ContractConfig; decimals: number; - ethersSigner?: EthersSigner; + evmSigner?: EvmSigner; extrinsic?: ExtrinsicConfig; polkadot: PolkadotService; sourceAddress: string; @@ -189,17 +189,17 @@ export async function getFee({ balance, contract, decimals, - ethersSigner, + evmSigner, extrinsic, polkadot, sourceAddress, }: GetFeeParams): Promise { if (contract) { - if (!ethersSigner) { - throw new Error('Ethers signer must be provided'); + if (!evmSigner) { + throw new Error('EVM Signer must be provided'); } - return getContractFee(balance, contract, decimals, ethersSigner); + return getContractFee(balance, contract, decimals, evmSigner); } if (extrinsic) { @@ -213,11 +213,11 @@ export async function getContractFee( balance: bigint, config: ContractConfig, decimals: number, - ethersSigner: EthersSigner, + evmSigner: EvmSigner, ): Promise { const contract = createContract( config, - ethersSigner, + evmSigner, ) as TransferContractInterface; const fee = await contract.getFee(balance); diff --git a/packages/sdk/src/getTransferData/getTransferData.ts b/packages/sdk/src/getTransferData/getTransferData.ts index 7ecef59f..90b49456 100644 --- a/packages/sdk/src/getTransferData/getTransferData.ts +++ b/packages/sdk/src/getTransferData/getTransferData.ts @@ -1,4 +1,5 @@ /* eslint-disable @typescript-eslint/no-use-before-define */ +import type { TransactionResponse } from '@ethersproject/abstract-provider'; import { TransferConfig } from '@moonbeam-network/xcm-config'; import { AssetAmount } from '@moonbeam-network/xcm-types'; import { convertDecimals, toBigInt } from '@moonbeam-network/xcm-utils'; @@ -21,13 +22,13 @@ export interface GetTransferDataParams extends Partial { export async function getTransferData({ destinationAddress, - ethersSigner, + evmSigner, polkadotSigner, sourceAddress, transferConfig, }: GetTransferDataParams): Promise { - if (!ethersSigner) { - throw new Error('Ethers signer must be provided'); + if (!evmSigner) { + throw new Error('EVM Signer must be provided'); } const [destPolkadot, srcPolkadot] = await PolkadotService.createMulti([ @@ -37,7 +38,7 @@ export async function getTransferData({ const destination = await getDestinationData({ destinationAddress, - ethersSigner, + evmSigner, polkadot: destPolkadot, transferConfig, }); @@ -50,7 +51,7 @@ export async function getTransferData({ const source = await getSourceData({ destinationAddress, destinationFee, - ethersSigner, + evmSigner, polkadot: srcPolkadot, sourceAddress, transferConfig, @@ -82,7 +83,7 @@ export async function getTransferData({ async swap() { return getTransferData({ destinationAddress: sourceAddress, - ethersSigner, + evmSigner, polkadotSigner, sourceAddress: destinationAddress, transferConfig: { @@ -119,15 +120,17 @@ export async function getTransferData({ }); if (contract) { - if (!ethersSigner) { - throw new Error('Ethers signer must be provided'); + if (!evmSigner) { + throw new Error('EVM Signer must be provided'); } return ( - createContract(contract, ethersSigner) as TransferContractInterface + createContract(contract, evmSigner) as TransferContractInterface ) .transfer() - .then((tx) => tx.hash); + .then((tx) => + typeof tx === 'object' ? (tx as TransactionResponse).hash : tx, + ); } if (extrinsic) { diff --git a/packages/sdk/src/getTransferData/getTransferData.utils.ts b/packages/sdk/src/getTransferData/getTransferData.utils.ts index 19df16b7..b1af6a52 100644 --- a/packages/sdk/src/getTransferData/getTransferData.utils.ts +++ b/packages/sdk/src/getTransferData/getTransferData.utils.ts @@ -2,14 +2,14 @@ import { CallType, SubstrateQueryConfig } from '@moonbeam-network/xcm-builder'; import { AssetConfig } from '@moonbeam-network/xcm-config'; import { Asset } from '@moonbeam-network/xcm-types'; import { toBigInt } from '@moonbeam-network/xcm-utils'; -import { Signer as EthersSigner } from 'ethers'; import { BalanceContractInterface, createContract } from '../contract'; import { PolkadotService } from '../polkadot'; +import { EvmSigner } from '../sdk.interfaces'; export interface GetFeeBalancesParams { address: string; config: AssetConfig; - ethersSigner: EthersSigner; + evmSigner: EvmSigner; polkadot: PolkadotService; asset?: Asset; } @@ -17,7 +17,7 @@ export interface GetFeeBalancesParams { export async function getBalance({ address, config, - ethersSigner, + evmSigner, polkadot, }: GetFeeBalancesParams) { const cfg = config.balance.build({ @@ -29,10 +29,7 @@ export async function getBalance({ return polkadot.query(cfg as SubstrateQueryConfig); } - const contract = createContract( - cfg, - ethersSigner, - ) as BalanceContractInterface; + const contract = createContract(cfg, evmSigner) as BalanceContractInterface; return contract.getBalance(); } @@ -41,7 +38,7 @@ export async function getDecimals({ address, asset, config, - ethersSigner, + evmSigner, polkadot, }: GetFeeBalancesParams) { const cfg = config.balance.build({ @@ -53,10 +50,7 @@ export async function getDecimals({ return polkadot.getAssetDecimals(asset || config.asset); } - const contract = createContract( - cfg, - ethersSigner, - ) as BalanceContractInterface; + const contract = createContract(cfg, evmSigner) as BalanceContractInterface; return contract.getDecimals(); } diff --git a/packages/sdk/src/sdk.interfaces.ts b/packages/sdk/src/sdk.interfaces.ts index 82927000..b68aea34 100644 --- a/packages/sdk/src/sdk.interfaces.ts +++ b/packages/sdk/src/sdk.interfaces.ts @@ -1,10 +1,17 @@ import { AnyChain, AssetAmount } from '@moonbeam-network/xcm-types'; import type { Signer as PolkadotSigner } from '@polkadot/api/types'; import type { IKeyringPair } from '@polkadot/types/types'; -import type { Signer as EthersSigner } from 'ethers'; +import { Signer as EthersSigner } from 'ethers'; +import { WalletClient } from 'viem'; + +export type EvmSigner = EthersSigner | WalletClient; export interface Signers { - ethersSigner: EthersSigner; + /** + * @deprecated ethersSigner - is deprecated and will be removed in v2, use evmSigner instead + */ + ethersSigner?: EthersSigner; + evmSigner?: EvmSigner; polkadotSigner: PolkadotSigner | IKeyringPair; } diff --git a/packages/sdk/src/sdk.ts b/packages/sdk/src/sdk.ts index 794d45ba..6969c4d1 100644 --- a/packages/sdk/src/sdk.ts +++ b/packages/sdk/src/sdk.ts @@ -35,10 +35,11 @@ export function Sdk(options?: SdkOptions) { ): Promise { return gtd({ ...options, - ...signers, destinationAddress, + evmSigner: signers?.evmSigner ?? signers?.ethersSigner, sourceAddress, transferConfig: destination(destKeyOrChain).build(), + polkadotSigner: signers?.polkadotSigner, }); }, }; @@ -53,6 +54,7 @@ export function Sdk(options?: SdkOptions) { destinationAddress, destinationKeyOrChain, ethersSigner, + evmSigner, keyOrAsset, polkadotSigner, sourceAddress, @@ -60,7 +62,7 @@ export function Sdk(options?: SdkOptions) { }: SdkTransferParams): Promise { return gtd({ destinationAddress, - ethersSigner, + evmSigner: evmSigner ?? ethersSigner, polkadotSigner, sourceAddress, transferConfig: ConfigBuilder(configService)