UNPKG

barterjs-sdk

Version:
294 lines (271 loc) 8.82 kB
import { Account, connect, ConnectedWalletAccount, KeyPair, Near, } from 'near-api-js'; import { NearNetworkConfig, TransferOutOptions, } from '../../types/requestTypes'; import { MCS_CONTRACT_ADDRESS_SET } from '../../constants/addresses'; import { ChainId, ID_TO_CHAIN_ID } from '../../constants/chains'; import { ADD_MCS_TOKEN_TO_CHAIN, ADD_NATIVE_TO_CHAIN, TRANSFER_OUT_NATIVE, TRANSFER_OUT_TOKEN, } from '../../constants/near_method_names'; import BN from 'bn.js'; import { ChangeFunctionCallOptions } from 'near-api-js/lib/account'; import { IMapCrossChainService } from '../interfaces/IMapCrossChainService'; import { hexToDecimalArray } from '../../utils'; import { BarterTransactionReceipt, BarterTransactionResponse, } from '../../types/responseTypes'; import { adaptNearReceipt, assembleNearTransactionResponse, } from '../../utils/responseUtil'; import { FinalExecutionOutcome } from 'near-api-js/lib/providers'; import { NearProviderType } from '../../types/paramTypes'; export class NearCrossChainService implements IMapCrossChainService { provider: NearProviderType; /** * we treat account as class member cuz to initialize a near account, async is required * @param provider */ constructor(provider: NearProviderType) { this.provider = provider; } /** * 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 see {@link TransferOutOptions} for more detail */ async doTransferOutToken( fromAddress: string, tokenAddress: string, amount: string, toAddress: string, toChainId: string, options: TransferOutOptions ): Promise<BarterTransactionResponse> { let mcsAccountId: string; let account: Account | ConnectedWalletAccount; if (this.provider instanceof NearNetworkConfig) { // get mcs contract address mcsAccountId = this.provider.networkId === 'testnet' ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; // prep near connection const near: Near = await connect(this.provider); account = await near.account(this.provider.fromAccount); } else { mcsAccountId = this.provider.getAccountId().endsWith('testnet') ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; account = this.provider.account(); } try { // the receiving address on Near need be in the format of number array as input const decimalArrayAddress: number[] = hexToDecimalArray( toAddress, toChainId ); // contract call option const nearCallOptions: ChangeFunctionCallOptions = { contractId: mcsAccountId, methodName: TRANSFER_OUT_TOKEN, args: { token: tokenAddress, to: decimalArrayAddress, amount: amount, to_chain: toChainId, }, attachedDeposit: new BN(amount, 10), }; // manual input gas if necessary if (options.gas != undefined) { nearCallOptions.gas = new BN(options.gas, 10); } const executionOutcome: FinalExecutionOutcome = await this._doNearFunctionCall(account, nearCallOptions); return assembleNearTransactionResponse(executionOutcome); } catch (error) { throw error; } } /** * 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 see {@link TransferOutOptions} for more detail */ async doTransferOutNative( fromAddress: string, toAddress: string, toChainId: string, amount: string, options: TransferOutOptions ): Promise<BarterTransactionResponse> { let mcsAccountId: string; let account: Account | ConnectedWalletAccount; if (this.provider instanceof NearNetworkConfig) { mcsAccountId = this.provider.networkId === 'testnet' ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; const near: Near = await connect(this.provider); account = await near.account(this.provider.fromAccount); } else { mcsAccountId = this.provider.getAccountId().endsWith('testnet') ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; account = this.provider.account(); } try { const decimalArrayAddress: number[] = hexToDecimalArray( toAddress, toChainId ); const nearCallOptions: ChangeFunctionCallOptions = { contractId: mcsAccountId, methodName: TRANSFER_OUT_NATIVE, args: { to: decimalArrayAddress, to_chain: Number.parseInt(toChainId), }, attachedDeposit: new BN(amount, 10), }; if (options.gas != undefined) { nearCallOptions.gas = new BN(options.gas, 10); } const executionOutcome: FinalExecutionOutcome = await this._doNearFunctionCall(account, nearCallOptions); return assembleNearTransactionResponse(executionOutcome); } catch (error) { throw error; } } /** * add tochain to allowed transfer out chains. * @param toChainId */ public async addNativeToChain(toChainId: string) { if (this.provider instanceof NearNetworkConfig) { const mcsAccountId: string = this.provider.networkId === 'testnet' ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; const near: Near = await connect(this.provider); const account = await near.account(this.provider.fromAccount); const nearCallOptions: ChangeFunctionCallOptions = { contractId: mcsAccountId, methodName: ADD_NATIVE_TO_CHAIN, args: { to_chain: toChainId, }, }; return await this._doNearFunctionCall(account, nearCallOptions); } } public async addTokenToChain(tokenAddress: string, toChainId: number) { if (this.provider instanceof NearNetworkConfig) { const mcsAccountId: string = this.provider.networkId === 'testnet' ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; const near: Near = await connect(this.provider); const account = await near.account(this.provider.fromAccount); const nearCallOptions: ChangeFunctionCallOptions = { contractId: mcsAccountId, methodName: ADD_MCS_TOKEN_TO_CHAIN, args: { token: tokenAddress, to_chain: toChainId, }, }; return await this._doNearFunctionCall(account, nearCallOptions); } } /** * call near smart contract * @param account * @param options * @private */ private async _doNearFunctionCall( account: Account | ConnectedWalletAccount, options: ChangeFunctionCallOptions ): Promise<FinalExecutionOutcome> { let outcome: FinalExecutionOutcome; try { outcome = await account.functionCall(options); } catch (e) { console.log(e); } return outcome!; } doDepositOutToken( tokenAddress: string, from: string, to: string, amount: string, options?: TransferOutOptions ): Promise<string> { return Promise.resolve(''); } gasEstimateTransferOutNative( fromAddress: string, toAddress: string, toChainId: string, amount: string, options?: TransferOutOptions ): Promise<string> { return Promise.resolve(''); } gasEstimateTransferOutToken( fromAddress: string, tokenAddress: string, amount: string, toAddress: string, toChainId: string, options?: TransferOutOptions ): Promise<string> { return Promise.resolve(''); } async addFungibleTokenToChain( tokenAddress: string, toChainId: string ): Promise<void> { if (this.provider instanceof NearNetworkConfig) { const mcsAccountId: string = this.provider.networkId === 'testnet' ? MCS_CONTRACT_ADDRESS_SET[ChainId.NEAR_TESTNET] : ''; const near: Near = await connect(this.provider); const account = await near.account(this.provider.fromAccount); const nearCallOptions: ChangeFunctionCallOptions = { contractId: mcsAccountId, methodName: 'add_fungible_token_to_chain', args: { token: tokenAddress, to_chain: toChainId, }, gas: new BN('300000000000000', 10), }; const executionOutcome: FinalExecutionOutcome = await this._doNearFunctionCall(account, nearCallOptions); } } }