@zebec-network/exchange-card-sdk
Version:
An sdk for purchasing silver card in zebec
197 lines (196 loc) • 8.47 kB
JavaScript
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();
}
}