butterjs-sdk
Version:
Butter Network SDK
475 lines (453 loc) • 13.3 kB
text/typescript
import {
BigNumber,
Contract as EthersContract,
ContractInterface,
ContractTransaction,
ethers,
Signer,
} from 'ethers';
import { Contract as Web3Contract } from 'web3-eth-contract';
import { TransactionReceipt as Web3TransactionReceipt } from 'web3-core';
import { IMapOmnichainService } from '../interfaces/IMapOmnichainService';
import {
ButterTransactionReceipt,
ButterTransactionResponse,
} from '../../types/responseTypes';
import {
adaptEthReceipt,
assembleEVMTransactionResponse,
} from '../../utils/responseUtil';
import { Provider } from '@ethersproject/abstract-provider';
import { Eth } from 'web3-eth';
import { TransactionOptions } from '../../types';
import { ButterProviderType } from '../../types/paramTypes';
import { PromiEvent } from 'web3-core';
export class RelayOmnichainService implements IMapOmnichainService {
contract: EthersContract | Web3Contract;
provider: ButterProviderType;
constructor(
contractAddress: string,
abi: any,
signerOrProvider: ButterProviderType
) {
if (
signerOrProvider instanceof Signer ||
signerOrProvider instanceof Provider
) {
this.contract = new ethers.Contract(
contractAddress,
abi,
signerOrProvider
);
} else {
this.contract = new signerOrProvider.Contract(abi, contractAddress);
}
this.provider = signerOrProvider;
}
/**
* transfer out token(not native coin) from source chain to designated token on target chain
* @param fromAddress
* @param tokenAddress input token address
* @param amount amount in minimal unit
* @param toAddress target chain receiving address
* @param toChainId target chain id
* @param options
*/
async doTransferOutToken(
fromAddress: string,
tokenAddress: string,
amount: string,
toAddress: string,
toChainId: string,
options: TransactionOptions
): Promise<ButterTransactionResponse> {
let txHash;
if (this.contract instanceof EthersContract) {
const transferOutTx: ContractTransaction =
await this.contract.transferOutToken(
tokenAddress,
toAddress,
amount,
toChainId,
{ gasLimit: options.gas }
);
txHash = transferOutTx.hash;
return assembleEVMTransactionResponse(txHash!, this.provider);
} else {
const promiReceipt: PromiEvent<Web3TransactionReceipt> =
this.contract.methods
.transferOutToken(tokenAddress, toAddress, amount, toChainId)
.send({
from: fromAddress,
gas: options.gas,
});
return <ButterTransactionResponse>{
promiReceipt: promiReceipt,
};
}
}
/**
* transfer out native coin from source chain to designated token on target chain
* @param fromAddress
* @param toAddress target chain receiving address
* @param toChainId target chain id
* @param amount amount to bridge in minimal unit
* @param options
*/
async doTransferOutNative(
fromAddress: string,
toAddress: string,
toChainId: string,
amount: string,
options: TransactionOptions
): Promise<ButterTransactionResponse> {
let txHash;
if (this.contract instanceof EthersContract) {
const transferOutTx: ContractTransaction =
await this.contract.transferOutNative(toAddress, toChainId, {
value: amount,
});
txHash = transferOutTx.hash;
return assembleEVMTransactionResponse(txHash!, this.provider);
} else {
const promiReceipt: PromiEvent<Web3TransactionReceipt> =
this.contract.methods.transferOutNative(toAddress, toChainId).send({
value: amount,
from: fromAddress,
gas: options.gas,
});
return <ButterTransactionResponse>{
promiReceipt: promiReceipt,
};
}
}
/**
* transfer out token(not native coin) from source chain to designated token on target chain
* @param fromAddress
* @param tokenAddress input token address
* @param amount amount in minimal unit
* @param toAddress target chain receiving address
* @param toChainId target chain id
* @param swapData
* @param options
*/
async doSwapOutToken(
fromAddress: string,
tokenAddress: string,
amount: string,
toAddress: string,
toChainId: string,
swapData: string,
options: TransactionOptions
): Promise<ButterTransactionResponse> {
let txHash: string;
if (this.contract instanceof EthersContract) {
const SwapOutTx: ContractTransaction = await this.contract.swapOutToken(
fromAddress,
tokenAddress,
toAddress,
amount,
toChainId,
swapData,
{ gasLimit: options.gas }
);
txHash = SwapOutTx.hash;
return assembleEVMTransactionResponse(txHash!, this.provider);
// receipt = await SwapOutTx.wait();
} else {
const promiReceipt: PromiEvent<Web3TransactionReceipt> =
this.contract.methods
.swapOutToken(
fromAddress,
tokenAddress,
toAddress,
amount,
toChainId,
swapData
)
.send({
from: fromAddress,
gas: Number.parseInt(options.gas!.toString()),
});
return <ButterTransactionResponse>{
promiReceipt: promiReceipt,
};
}
}
/**
* transfer out native coin from source chain to designated token on target chain
* @param fromAddress
* @param toAddress target chain receiving address
* @param toChainId target chain id
* @param amount amount to bridge in minimal unit
* @param swapData
* @param options
*/
async doSwapOutNative(
fromAddress: string,
toAddress: string,
toChainId: string,
amount: string,
swapData: string,
options: TransactionOptions
): Promise<ButterTransactionResponse> {
let txHash: string;
if (this.contract instanceof EthersContract) {
const SwapOutTx: ContractTransaction = await this.contract.swapOutNative(
fromAddress,
toAddress,
toChainId,
swapData,
{
// gasLimit: options.gas,
value: amount,
}
);
txHash = SwapOutTx.hash;
return assembleEVMTransactionResponse(txHash!, this.provider);
} else {
const promiReceipt: PromiEvent<Web3TransactionReceipt> =
this.contract.methods
.swapOutNative(fromAddress, toAddress, toChainId, swapData)
.send({
value: amount,
from: fromAddress,
gas: Number.parseInt(options.gas!.toString()),
});
return <ButterTransactionResponse>{
promiReceipt: promiReceipt,
};
}
}
async gasEstimateTransferOutToken(
fromAddress: string,
tokenAddress: string,
amount: string,
toAddress: string,
toChainId: string
): Promise<string> {
// gas estimation
let estimatedGas = '';
if (this.contract instanceof EthersContract) {
const gas: BigNumber = await this.contract.estimateGas.transferOutToken!(
tokenAddress,
toAddress,
amount,
toChainId
);
estimatedGas = gas.toString();
} else {
const gas = await this.contract.methods
.transferOutToken(tokenAddress, toAddress, amount, toChainId)
.estimateGas({ from: fromAddress });
estimatedGas = gas.toString();
}
return estimatedGas;
}
async gasEstimateTransferOutNative(
fromAddress: string,
toAddress: string,
toChainId: string,
amount: string
): Promise<string> {
// gas estimation
let estimatedGas;
if (this.contract instanceof EthersContract) {
const gas = await this.contract.estimateGas.transferOutNative!(
fromAddress,
toAddress,
toChainId,
{
value: amount,
from: fromAddress,
}
);
estimatedGas = gas.toString();
} else {
const gas = await this.contract.methods
.transferOutNative(toAddress, toChainId)
.estimateGas({ from: fromAddress, value: amount });
estimatedGas = gas.toString();
}
return estimatedGas;
}
async gasEstimateSwapOutToken(
fromAddress: string,
tokenAddress: string,
amount: string,
toAddress: string,
toChainId: string,
swapData: string
): Promise<string> {
// gas estimation
let estimatedGas = '';
if (this.contract instanceof EthersContract) {
const gas: BigNumber = await this.contract.estimateGas.swapOutToken!(
fromAddress,
tokenAddress,
toAddress,
amount,
toChainId,
swapData
);
estimatedGas = gas.toString();
} else {
const gas = await this.contract.methods
.swapOutToken(fromAddress, tokenAddress, toAddress, amount, toChainId)
.estimateGas({ from: fromAddress });
estimatedGas = gas.toString();
}
return estimatedGas;
}
async gasEstimateSwapOutNative(
fromAddress: string,
toAddress: string,
toChainId: string,
amount: string,
swapData: string
): Promise<string> {
// gas estimation
let estimatedGas;
if (this.contract instanceof EthersContract) {
const gas = await this.contract.estimateGas.swapOutNative!(
fromAddress,
toAddress,
toChainId,
swapData,
{
value: amount,
}
);
estimatedGas = gas.toString();
} else {
const gas = await this.contract.methods
.swapOutNative(fromAddress, toAddress, toChainId)
.estimateGas({ value: amount });
estimatedGas = gas.toString();
}
return estimatedGas;
}
async doDepositOutToken(
tokenAddress: string,
from: string,
to: string,
amount: string
): Promise<string> {
if (this.contract instanceof EthersContract) {
const depositOutTx: ContractTransaction =
await this.contract.depositOutToken(tokenAddress, from, to, amount);
const receipt = await depositOutTx.wait();
return receipt.transactionHash;
} else {
throw new Error('provider not supported');
}
}
/**
* set id table
* @param chainId
* @param id
*/
// async doSetIdTable(chainId: string, id: string): Promise<string> {
// const setIdTableTx: ContractTransaction = await this.contract.setIdTable(
// chainId,
// id
// );
//
// const receipt = await setIdTableTx.wait();
// return receipt.transactionHash;
// }
//
// async doSetNearHash(hash: string): Promise<string> {
// const setNearHashTx: ContractTransaction = await this.contract.setNearHash(
// hash
// );
//
// const receipt = await setNearHashTx.wait();
// return receipt.transactionHash;
// }
/**
* specify token decimal for the convertion of different token on different chain
* @param selfTokenAddress
* @param chainId
* @param decimals
*/
async doSetTokenOtherChainDecimals(
selfTokenAddress: string,
chainId: string,
decimals: number
): Promise<string> {
if (this.contract instanceof EthersContract) {
const tx: ContractTransaction =
await this.contract.setTokenOtherChainDecimals(
selfTokenAddress,
chainId,
decimals
);
const receipt = await tx.wait();
return receipt.transactionHash;
} else {
throw new Error('need ethers provider');
}
}
async doAddAuthToken(tokens: string[]): Promise<string> {
if (this.contract instanceof EthersContract) {
const addAuthTokenTx: ContractTransaction =
await this.contract.addAuthToken(tokens);
const receipt = await addAuthTokenTx.wait();
return receipt.transactionHash;
} else {
throw new Error('need ethers provider');
}
}
/**
* set accepted bridge address
* @param chainId chain id of the bridge address is residing on
* @param bridgeAddress bridge address
*/
async doSetBridgeAddress(
chainId: string,
bridgeAddress: string
): Promise<string> {
if (this.contract instanceof EthersContract) {
const tx: ContractTransaction = await this.contract.setBridgeAddress(
chainId,
bridgeAddress
);
const receipt = await tx.wait();
return receipt.transactionHash;
} else {
throw new Error('need ethers provider');
}
}
async setVaultBalance(
toChain: number,
address: string,
amount: string
): Promise<string> {
if (this.contract instanceof EthersContract) {
const tx: ContractTransaction = await this.contract.setVaultBalance(
toChain,
address,
amount
);
const receipt = await tx.wait();
return receipt.transactionHash;
} else {
throw new Error('need ethers provider');
}
}
async getVaultBalance(
toChainId: number,
tokenAddress: string
): Promise<string> {
if (this.contract instanceof EthersContract) {
const balance: BigNumber = await this.contract.vaultBalance(
toChainId,
tokenAddress
);
return Promise.resolve(balance.toString());
} else {
throw new Error('need ethers provider');
}
}
}