UNPKG

@zebec-network/exchange-card-sdk

Version:
197 lines (196 loc) 8.47 kB
import assert from "assert"; import { BigNumber } from "bignumber.js"; import { JsonRpcProvider } from "@near-js/providers"; import { parseNearAmount } from "@near-js/utils"; import { NEAR_RPC_URL } from "../constants"; import { ZebecCardAPIService } from "../helpers/apiHelpers"; /** * Makes action payload for function call in near contract * @param methodName method name * @param args an object that will be passed as argument to method * @param gas gas fee * @param deposit deposit amount */ export function createFunctionCall(methodName, args, gas, deposit) { return { type: "FunctionCall", params: { args, deposit, gas, methodName, }, }; } export class NearService { wallet; apiService; provider; constructor(wallet, options) { this.wallet = wallet; const sandbox = options?.sandbox ? options.sandbox : false; this.apiService = new ZebecCardAPIService(sandbox); const url = sandbox ? NEAR_RPC_URL.Sandbox : NEAR_RPC_URL.Production; this.provider = new JsonRpcProvider({ url }); } /** * Fetches the Bitcoin vault address. * * @returns {Promise<{ address: string }>} A promise that resolves to the vault address. */ async fetchVault(symbol = "NEAR") { const data = await this.apiService.fetchVault(symbol); return data; } async transferNear(params) { const signerId = params.signerId ? params.signerId : this.wallet.signerId; const fetchVault = await this.fetchVault(); const destination = fetchVault.address; console.debug("destination:", destination); const parsedAmount = parseNearAmount(params.amount); assert(parsedAmount, "Amount might be missing."); const action = { type: "Transfer", params: { deposit: parsedAmount, }, }; const outcome = await this.wallet.signAndSendTransaction({ signerId: signerId, receiverId: destination, actions: [action], }); return outcome; } async registerAccountInTokenContract(params) { const signerId = params.signerId ? params.signerId : this.wallet.signerId; const storageBalanceBoundsResult = await this.provider.query({ request_type: "call_function", account_id: params.tokenContractId, method_name: "storage_balance_bounds", args_base64: Buffer.from(JSON.stringify({})).toString("base64"), finality: "optimistic", }); const storageBalanceBounds = JSON.parse(Buffer.from(storageBalanceBoundsResult.result).toString()); console.debug("storageBalanceBounds:", storageBalanceBounds); const storageBalanceResult = await this.provider.query({ request_type: "call_function", account_id: params.tokenContractId, method_name: "storage_balance_of", args_base64: Buffer.from(JSON.stringify({ account_id: signerId })).toString("base64"), finality: "optimistic", }); const storageBalance = JSON.parse(Buffer.from(storageBalanceResult.result).toString()); console.debug("storageBalance:", storageBalance); const GAS = "30000000000000"; if (!storageBalance || BigNumber(storageBalance.available).isLessThan(storageBalanceBounds.min)) { const action = createFunctionCall("storage_deposit", { account_id: signerId, registration_only: false, }, GAS, storageBalanceBounds.min); const outcome = await this.wallet.signAndSendTransaction({ signerId: signerId, receiverId: params.tokenContractId, actions: [action], }); return outcome; } return null; } async transferTokens(params) { const signerId = params.signerId ? params.signerId : this.wallet.signerId; console.log("signerId:", signerId); const fetchVault = await this.fetchVault("NEAR-USDC"); const destination = fetchVault.address; console.debug("destination:", destination); let actions = []; const GAS = "30000000000000"; const storageBalanceBoundsResult = await this.provider.query({ request_type: "call_function", account_id: params.tokenContractId, method_name: "storage_balance_bounds", args_base64: Buffer.from(JSON.stringify({})).toString("base64"), finality: "optimistic", }); const storageBalanceBounds = JSON.parse(Buffer.from(storageBalanceBoundsResult.result).toString()); console.debug("storageBalanceBounds:", storageBalanceBounds); const storageBalanceResult = await this.provider.query({ request_type: "call_function", account_id: params.tokenContractId, method_name: "storage_balance_of", args_base64: Buffer.from(JSON.stringify({ account_id: destination })).toString("base64"), finality: "optimistic", }); const storageBalance = JSON.parse(Buffer.from(storageBalanceResult.result).toString()); console.debug("storageBalance:", storageBalance); if (!storageBalance || BigNumber(storageBalance.available).isLessThan(storageBalanceBounds.min)) { const action = createFunctionCall("storage_deposit", { account_id: destination, registration_only: false, }, GAS, storageBalanceBounds.max ? storageBalanceBounds.max : storageBalanceBounds.min); actions.push(action); } const metadataResult = await this.provider.query({ request_type: "call_function", finality: "final", account_id: params.tokenContractId, method_name: "ft_metadata", args_base64: Buffer.from(JSON.stringify({})).toString("base64"), }); const metadata = JSON.parse(Buffer.from(metadataResult.result).toString()); const tokenDecimals = metadata.decimals; const parsedAmount = BigNumber(params.amount) .times(BigNumber(10).pow(tokenDecimals)) .toFixed(0); const secutityDeposit = "1"; const transferAction = createFunctionCall("ft_transfer", { receiver_id: destination, amount: parsedAmount, memo: null, }, GAS, secutityDeposit); actions.push(transferAction); const outcome = await this.wallet.signAndSendTransaction({ signerId: signerId, receiverId: params.tokenContractId, actions, }); return outcome; } async getNearBalance(params) { const signerId = params.signerId ? params.signerId : this.wallet.signerId; const result = await this.provider.query({ request_type: "view_account", account_id: signerId, finality: "final", }); assert("amount" in result, "Amount field is missing in the account data."); assert(typeof result.amount === "string", "Amount field is not a string."); const nearDecimals = 24; return BigNumber(result.amount).div(BigNumber(10).pow(nearDecimals)).toFixed(); } async getTokenBalance(params) { const signerId = params.signerId ? params.signerId : this.wallet.signerId; const metadataResult = await this.provider.query({ request_type: "call_function", finality: "final", account_id: params.tokenContractId, method_name: "ft_metadata", args_base64: Buffer.from(JSON.stringify({})).toString("base64"), }); const result = await this.provider.query({ request_type: "call_function", finality: "final", account_id: params.tokenContractId, method_name: "ft_balance_of", args_base64: Buffer.from(JSON.stringify({ account_id: signerId, })).toString("base64"), }); const metadata = JSON.parse(Buffer.from(metadataResult.result).toString()); const decimals = metadata.decimals; const data = JSON.parse(Buffer.from(result.result).toString()); return BigNumber(data).div(BigNumber(10).pow(decimals)).toFixed(); } }