diff --git a/src/antelope/types/EvmContractData.ts b/src/antelope/types/EvmContractData.ts index 16e0a57f4..8d8b9e930 100644 --- a/src/antelope/types/EvmContractData.ts +++ b/src/antelope/types/EvmContractData.ts @@ -100,3 +100,5 @@ export interface EvmContractFactoryData { timestamp?: string; manager?: EvmContractManagerI; } + +export type EvmFunctionParam = string | number | boolean; diff --git a/src/antelope/types/EvmTransaction.ts b/src/antelope/types/EvmTransaction.ts index 3700eee2b..2fe5a9958 100644 --- a/src/antelope/types/EvmTransaction.ts +++ b/src/antelope/types/EvmTransaction.ts @@ -143,3 +143,4 @@ export interface EvmTransfer { timestamp: number; // integer representing ms from epoch id?: string; // id of the NFT transferred (ERC721 or ERC1155 only) } + diff --git a/src/antelope/wallets/authenticators/EVMAuthenticator.ts b/src/antelope/wallets/authenticators/EVMAuthenticator.ts index 18cb2093d..3bea27f15 100644 --- a/src/antelope/wallets/authenticators/EVMAuthenticator.ts +++ b/src/antelope/wallets/authenticators/EVMAuthenticator.ts @@ -8,7 +8,7 @@ import { useChainStore } from 'src/antelope/stores/chain'; import { useEVMStore } from 'src/antelope/stores/evm'; import { createTraceFunction, isTracingAll, useFeedbackStore } from 'src/antelope/stores/feedback'; import { usePlatformStore } from 'src/antelope/stores/platform'; -import { AntelopeError, EvmTransactionResponse, ExceptionError, TokenClass, addressString } from 'src/antelope/types'; +import { AntelopeError, EvmABI, EvmFunctionParam, EvmTransactionResponse, ExceptionError, TokenClass, addressString } from 'src/antelope/types'; export abstract class EVMAuthenticator { @@ -25,6 +25,7 @@ export abstract class EVMAuthenticator { abstract logout(): Promise; abstract getSystemTokenBalance(address: addressString | string): Promise; abstract getERC20TokenBalance(address: addressString | string, tokenAddress: addressString | string): Promise; + abstract signCustomTransaction(contract: string, abi: EvmABI, parameters: EvmFunctionParam[], value?: BigNumber): Promise; abstract transferTokens(token: TokenClass, amount: BigNumber, to: addressString | string): Promise; abstract prepareTokenForTransfer(token: TokenClass | null, amount: BigNumber, to: string): Promise; abstract wrapSystemToken(amount: BigNumber): Promise; diff --git a/src/antelope/wallets/authenticators/InjectedProviderAuth.ts b/src/antelope/wallets/authenticators/InjectedProviderAuth.ts index 307038a66..fbc3ba365 100644 --- a/src/antelope/wallets/authenticators/InjectedProviderAuth.ts +++ b/src/antelope/wallets/authenticators/InjectedProviderAuth.ts @@ -7,6 +7,8 @@ import { AntelopeError, ERC20_TYPE, EthereumProvider, + EvmABI, + EvmFunctionParam, EvmTransactionResponse, TokenClass, addressString, @@ -72,6 +74,22 @@ export abstract class InjectedProviderAuth extends EVMAuthenticator { // EVMAuthenticator API ---------------------------------------------------------- + async signCustomTransaction(contract: string, abi: EvmABI, parameters: EvmFunctionParam[], value?: BigNumber): Promise { + this.trace('signCustomTransaction', contract, [abi], parameters, value?.toString()); + // TODO: implement this method and remove this comment + // https://github.com/telosnetwork/telos-wallet/issues/625 + + const method = abi[0].name; + if (abi.length > 1) { + console.warn( + `signCustomTransaction: abi contains more than one function, + we asume the first one (${method}) is the one to be called`, + ); + } + + return Promise.resolve({} as EvmTransactionResponse); + } + async wrapSystemToken(amount: BigNumber): Promise { this.trace('wrapSystemToken', amount.toString()); const chainSettings = this.getChainSettings(); diff --git a/src/antelope/wallets/authenticators/OreIdAuth.ts b/src/antelope/wallets/authenticators/OreIdAuth.ts index b3b0d0332..af342984f 100644 --- a/src/antelope/wallets/authenticators/OreIdAuth.ts +++ b/src/antelope/wallets/authenticators/OreIdAuth.ts @@ -2,6 +2,8 @@ import { AuthProvider, ChainNetwork, OreId, OreIdOptions, JSONObject, UserChainA import { BigNumber, ethers } from 'ethers'; import { WebPopup } from 'oreid-webpopup'; import { + EvmABI, + EvmFunctionParam, erc20Abi, escrowAbiWithdraw, stlosAbiDeposit, @@ -209,43 +211,6 @@ export class OreIdAuth extends EVMAuthenticator { } } - async transferTokens(token: TokenClass, amount: ethers.BigNumber, to: addressString): Promise { - this.trace('transferTokens', token, amount, to); - this.checkIntegrity(); - - // prepare variables - const from = this.getAccountAddress(); - const value = amount.toHexString(); - const abi = erc20Abi; - - // transaction body: transfer system tokens - const systemTransfer = { - from, - to, - value, - }; - - // transaction body: transfer erc20 tokens - const erc20Transfer = { - from, - to: token.address, - 'contract': { - abi, - 'parameters': [to, value], - 'method': 'transfer', - }, - } as unknown as JSONObject; - - let transactionBody = null as unknown as JSONObject; - if (token.isSystem) { - transactionBody = systemTransfer; - } else { - transactionBody = erc20Transfer; - } - - return this.performOreIdTransaction(from, transactionBody); - } - async prepareTokenForTransfer(token: TokenClass | null, amount: ethers.BigNumber, to: string): Promise { this.trace('prepareTokenForTransfer', [token], amount, to); } @@ -291,30 +256,54 @@ export class OreIdAuth extends EVMAuthenticator { } as EvmTransactionResponse; } - async wrapSystemToken(amount: BigNumber): Promise { - this.trace('wrapSystemToken', amount); + async signCustomTransaction(contract: string, abi: EvmABI, parameters: EvmFunctionParam[], value?: BigNumber): Promise { + this.trace('signCustomTransaction', contract, [abi], parameters, value?.toString()); this.checkIntegrity(); - // prepare variables - const chainSettings = this.getChainSettings(); - const wrappedSystemTokenContractAddress = chainSettings.getWrappedSystemToken().address as addressString; const from = this.getAccountAddress(); - const value = amount.toHexString(); - const abi = wtlosAbiDeposit; + const method = abi[0].name; + + // if the developer is passing more than one function in the abi + // we must warn we asume the first one is the one to be called + if (abi.length > 1) { + console.warn( + `signCustomTransaction: abi contains more than one function, + we asume the first one (${method}) is the one to be called`, + ); + } // transaction body: wrap system token - const wrapTransaction = { + const transactionBody = { from, - to: wrappedSystemTokenContractAddress, - value, + to: contract, 'contract': { abi, - 'parameters': [], - 'method': 'deposit', + parameters, + 'method': abi[0].name, }, } as unknown as JSONObject; - return this.performOreIdTransaction(from, wrapTransaction); + if (value) { + transactionBody.value = value.toHexString(); + } + + return this.performOreIdTransaction(from, transactionBody); + } + + async wrapSystemToken(amount: BigNumber): Promise { + this.trace('wrapSystemToken', amount); + this.checkIntegrity(); + + // prepare variables + const chainSettings = this.getChainSettings(); + const wrappedSystemTokenContractAddress = chainSettings.getWrappedSystemToken().address as addressString; + + return this.signCustomTransaction( + wrappedSystemTokenContractAddress, + wtlosAbiDeposit, + [], + amount, + ); } async unwrapSystemToken(amount: BigNumber): Promise { @@ -324,22 +313,13 @@ export class OreIdAuth extends EVMAuthenticator { // prepare variables const chainSettings = this.getChainSettings(); const wrappedSystemTokenContractAddress = chainSettings.getWrappedSystemToken().address as addressString; - const from = this.getAccountAddress(); const value = amount.toHexString(); - const abi = wtlosAbiWithdraw; - // transaction body: unwrap system token - const unwrapTransaction = { - from, - to: wrappedSystemTokenContractAddress, - 'contract': { - abi, - 'parameters': [value], - 'method': 'withdraw', - }, - } as unknown as JSONObject; - - return this.performOreIdTransaction(from, unwrapTransaction); + return this.signCustomTransaction( + wrappedSystemTokenContractAddress, + wtlosAbiWithdraw, + [value], + ); } async stakeSystemTokens(amount: BigNumber): Promise { @@ -349,23 +329,13 @@ export class OreIdAuth extends EVMAuthenticator { // prepare variables const chainSettings = this.getChainSettings(); const stakedSystemTokenContractAddress = chainSettings.getStakedSystemToken().address as addressString; - const from = this.getAccountAddress(); - const value = amount.toHexString(); - const abi = stlosAbiDeposit; - // transaction body: stake system token - const stakeTransaction = { - from, - to: stakedSystemTokenContractAddress, - value, - 'contract': { - abi, - 'parameters': [], - 'method': stlosAbiDeposit[0].name, - }, - } as unknown as JSONObject; - - return this.performOreIdTransaction(from, stakeTransaction); + return this.signCustomTransaction( + stakedSystemTokenContractAddress, + stlosAbiDeposit, + [], + amount, + ); } async unstakeSystemTokens(amount: BigNumber): Promise { @@ -375,22 +345,14 @@ export class OreIdAuth extends EVMAuthenticator { // prepare variables const chainSettings = this.getChainSettings(); const stakedSystemTokenContractAddress = chainSettings.getStakedSystemToken().address as addressString; - const from = this.getAccountAddress(); const value = amount.toHexString(); - const abi = stlosAbiWithdraw; - - // transaction body: unstake system token - const unstakeTransaction = { - from, - to: stakedSystemTokenContractAddress, - 'contract': { - abi, - 'parameters': [value, from, from], - 'method': 'withdraw', - }, - } as unknown as JSONObject; + const from = this.getAccountAddress(); - return this.performOreIdTransaction(from, unstakeTransaction); + return this.signCustomTransaction( + stakedSystemTokenContractAddress, + stlosAbiWithdraw, + [value, from, from], + ); } async withdrawUnstakedTokens() : Promise { @@ -400,21 +362,36 @@ export class OreIdAuth extends EVMAuthenticator { // prepare variables const chainSettings = this.getChainSettings(); const escrowContractAddress = chainSettings.getEscrowContractAddress(); - const from = this.getAccountAddress(); - const abi = escrowAbiWithdraw; - // transaction body: withdraw staked tokens - const withdrawTransaction = { - from, - to: escrowContractAddress, - 'contract': { - abi, - 'parameters': [], - 'method': 'withdraw', - }, - } as unknown as JSONObject; + return this.signCustomTransaction( + escrowContractAddress, + escrowAbiWithdraw, + [], + ); + } - return this.performOreIdTransaction(from, withdrawTransaction); + async transferTokens(token: TokenClass, amount: ethers.BigNumber, to: addressString): Promise { + this.trace('transferTokens', token, amount, to); + this.checkIntegrity(); + + // prepare variables + const from = this.getAccountAddress(); + const value = amount.toHexString(); + const transferAbi = erc20Abi.filter(abi => abi.name === 'transfer'); + + if (token.isSystem) { + return this.performOreIdTransaction(from, { + from, + to, + value, + }); + } else { + return this.signCustomTransaction( + token.address, + transferAbi, + [to, value], + ); + } } async isConnectedTo(chainId: string): Promise { diff --git a/src/antelope/wallets/authenticators/WalletConnectAuth.ts b/src/antelope/wallets/authenticators/WalletConnectAuth.ts index 29b152c06..69b84b0c0 100644 --- a/src/antelope/wallets/authenticators/WalletConnectAuth.ts +++ b/src/antelope/wallets/authenticators/WalletConnectAuth.ts @@ -25,6 +25,7 @@ import { usePlatformStore } from 'src/antelope/stores/platform'; import { AntelopeError, EvmABI, + EvmFunctionParam, TokenClass, addressString, escrowAbiWithdraw, @@ -242,6 +243,22 @@ export class WalletConnectAuth extends EVMAuthenticator { return BigNumber.from(balance); } + async signCustomTransaction(contract: string, abi: EvmABI, parameters: EvmFunctionParam[], value?: BigNumber): Promise { + this.trace('signCustomTransaction', contract, [abi], parameters, value?.toString()); + // TODO: implement this method and remove this comment + // https://github.com/telosnetwork/telos-wallet/issues/626 + + const method = abi[0].name; + if (abi.length > 1) { + console.warn( + `signCustomTransaction: abi contains more than one function, + we asume the first one (${method}) is the one to be called`, + ); + } + + return Promise.resolve({} as SendTransactionResult); + } + async transferTokens(token: TokenClass, amount: BigNumber, to: addressString): Promise { this.trace('transferTokens', token, amount, to); if (!this.sendConfig) {