@d8x/perpetuals-sdk
Version:
Node TypeScript SDK for D8X Perpetual Futures
154 lines • 6.75 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const ethers_1 = require("ethers");
const constants_1 = require("./constants");
const contracts_1 = require("./contracts");
const d8XMath_1 = require("./d8XMath");
const perpetualDataHandler_1 = __importDefault(require("./perpetualDataHandler"));
/**
* This is a parent class for the classes that require
* write access to the contracts.
* This class requires a private key and executes smart-contract interaction that
* require gas-payments.
* @extends PerpetualDataHandler
*/
class WriteAccessHandler extends perpetualDataHandler_1.default {
/**
* Constructor
* @param {string | Signer} signer Private key or ethers Signer of the account
*/
constructor(config, signer) {
super(config);
this.traderAddr = "";
this.signer = null;
this.gasLimit = 15000000;
if (typeof signer == "string") {
this.privateKey = signer;
}
else {
this.signer = signer;
}
if (config.gasLimit != undefined) {
this.gasLimit = config.gasLimit;
}
}
/**
* Initialize the writeAccessHandler-Class with this function
* to create instance of D8X perpetual contract and gather information
* about perpetual currencies
* @param provider optional provider
*/
async createProxyInstance(providerOrMarketData, overrides) {
await this.priceFeedGetter.init();
if (providerOrMarketData == undefined || !("createProxyInstance" in providerOrMarketData)) {
this.provider = providerOrMarketData ?? new ethers_1.JsonRpcProvider(this.nodeURL, this.network, { staticNetwork: true });
if (!this.signer) {
const wallet = new ethers_1.Wallet(this.privateKey);
this.signer = wallet.connect(this.provider);
}
await this.initContractsAndData(this.signer, overrides);
}
else {
const mktData = providerOrMarketData;
this.nodeURL = mktData.config.nodeURL;
this.provider = new ethers_1.JsonRpcProvider(mktData.config.nodeURL, mktData.network, { staticNetwork: true });
this.proxyContract = contracts_1.IPerpetualManager__factory.connect(mktData.getProxyAddress(), this.provider);
this.multicall = contracts_1.Multicall3__factory.connect(this.config.multicall ?? constants_1.MULTICALL_ADDRESS, this.provider);
({
nestedPerpetualIDs: this.nestedPerpetualIDs,
poolStaticInfos: this.poolStaticInfos,
symbolToTokenAddrMap: this.symbolToTokenAddrMap,
symbolToPerpStaticInfo: this.symbolToPerpStaticInfo,
perpetualIdToSymbol: this.perpetualIdToSymbol,
} = mktData.getAllMappings());
this.priceFeedGetter.setTriangulations(mktData.getTriangulations());
this.signerOrProvider = this.provider;
}
if (!this.signer) {
const wallet = new ethers_1.Wallet(this.privateKey);
this.signer = wallet.connect(this.provider);
}
this.traderAddr = await this.signer.getAddress();
}
/**
* Set allowance for ar margin token (e.g., MATIC, ETH, USDC)
* @param symbol token in 'long-form' such as MATIC, symbol also fine (ETH-USD-MATIC)
* @param amount optional, amount to approve if not 'infinity'
* @returns Contract Transaction
*/
async setAllowance(symbol, amount, overrides) {
// extract margin-currency name
let symbolarr = symbol.split("-");
symbol = symbol.length == 3 ? symbolarr[2] : symbolarr[0];
//
let settleTokenAddr = this.getSettlementTokenFromSymbol(symbol);
if (settleTokenAddr == undefined || this.signer == null) {
throw Error("No margin token or signer defined, call createProxyInstance");
}
let amountDec18;
if (amount == undefined) {
amountDec18 = constants_1.MAX_UINT_256;
}
else {
amountDec18 = (0, d8XMath_1.floatToDecN)(amount, this.getSettlementTokenDecimalsFromSymbol(symbol));
}
return WriteAccessHandler._setAllowance(settleTokenAddr, this.proxyAddr, this.signer, amountDec18, overrides);
}
static async _setAllowance(tokenAddr, proxyAddr, signer, amount, overrides) {
const marginToken = contracts_1.ERC20__factory.connect(tokenAddr, signer);
return await marginToken.approve(proxyAddr, amount, overrides || {});
}
/**
* Address corresponding to the private key used to instantiate this class.
* @returns {string} Address of this wallet.
*/
getAddress() {
return this.traderAddr;
}
_getFeeData(overrides) {
// handle legacy and eip-1552 (ensure at most one is specified)
if (overrides?.maxFeePerGas) {
return {
maxFeePerGas: overrides.maxFeePerGas,
maxPriorityFeePerGas: overrides.maxPriorityFeePerGas ?? overrides.maxFeePerGas,
};
}
else {
return { gasPrice: overrides?.gasPrice };
}
}
/**
* Converts a given amount of chain native currency (test MATIC)
* into a mock token used for trading on testnet, with a rate of 1:100_000
* @param symbol Pool margin token e.g. MATIC
* @param amountToPay Amount in chain currency, e.g. "0.1" for 0.1 MATIC
* @returns Transaction object
*/
async swapForMockToken(symbol, amountToPay, overrides) {
if (this.signer == null) {
throw Error("no wallet initialized. Use createProxyInstance().");
}
let tokenAddress = this.getMarginTokenFromSymbol(symbol);
if (tokenAddress == undefined) {
throw Error("symbols not found");
}
let tokenToSwap = new Map(Object.entries(require("./config/mockSwap.json")));
let swapAddress = tokenToSwap.get(tokenAddress);
if (swapAddress == undefined) {
throw Error("No swap contract found for symbol.");
}
let contract = contracts_1.MockTokenSwap__factory.connect(swapAddress, this.signer);
if (overrides && overrides.value !== undefined) {
throw Error("Pass value to send in function call, not overrides.");
}
return await contract.swapToMockToken({
value: (0, ethers_1.parseEther)(amountToPay),
...overrides,
});
}
}
exports.default = WriteAccessHandler;
//# sourceMappingURL=writeAccessHandler.js.map