UNPKG

juna

Version:

A cross platform NFT lending client for serious lenders

151 lines (139 loc) 5.18 kB
import { PrivateKeyAccount, createWalletClient, WalletClient, http } from "viem"; import { mainnet } from "viem/chains"; import { privateKeyToAccount } from "viem/accounts"; import { BlurLoan, BlurOffer } from "./support/types"; import { LendingPlatform, Offer, OfferType } from "../types"; import { BETH } from "../support/currencies"; import { config } from "../config"; import { Axios } from "axios"; export class GhostApi { private axios: Axios; private client: WalletClient; private account: PrivateKeyAccount; constructor( privateKey: `0x${string}`, rpcUrl: `https://${string}` = config.defaultRpc, apiKey: string, walletAddress?: string, ) { this.account = privateKeyToAccount(privateKey); this.client = createWalletClient({ account: this.account, chain: mainnet, transport: http(rpcUrl), }); this.axios = new Axios({ headers: { "x-api-key": apiKey, "x-wallet-address": walletAddress ?? this.account.address, }, }); } public async getLiens(address: `0x${string}`): Promise<BlurLoan[]> { const result = await this.axios.get(`${config.blur.baseUrlPortfolio}/${address.toLowerCase()}/liens`); return JSON.parse(result.data).liens; } public async getLoanOffers(accountAddress: `0x${string}`, collectionAddress?: `0x${string}`): Promise<BlurOffer[]> { const result = await this.axios.get( `${config.blur.baseUrlPortfolio}/${accountAddress.toLowerCase()}/loan-offers?contractAddress=${collectionAddress}`, ); return JSON.parse(result.data).loanOffers; } public async postLoanOffer( collectionAddress: `0x${string}`, principal: number, limit: number, apr: number, expiryInMinutes: number, ): Promise<Offer> { // Format the query const payload = { contractAddress: collectionAddress.toLowerCase(), orders: [ { contractAddress: collectionAddress.toLowerCase(), expirationTime: new Date(new Date().getTime() + expiryInMinutes * 60 * 1000).toISOString(), maxAmount: principal.toString(), rate: apr * 10000, totalAmount: limit.toString(), }, ], userAddress: this.account.address.toLowerCase(), }; const result = await this.axios.post(`${config.blur.baseUrlBlend}/loan-offer/format`, JSON.stringify(payload), { headers: { "Content-Type": "application/json" }, }); const format = JSON.parse(result.data); // Signing const signData = format.signatures[0].signData; signData.value.minAmount = BigInt(signData.value.minAmount.hex); signData.value.maxAmount = BigInt(signData.value.maxAmount.hex); signData.value.totalAmount = BigInt(signData.value.totalAmount.hex); signData.value.salt = BigInt(signData.value.salt.hex); signData.value.auctionDuration = BigInt(signData.value.auctionDuration.hex); signData.value.expirationTime = BigInt(signData.value.expirationTime.hex); const signature = await this.account.signTypedData({ domain: signData.domain, types: signData.types, primaryType: "LoanOffer", message: signData.value, }); // Submit the offer const payload2 = { contractAddress: collectionAddress.toLowerCase(), orders: [ { contractAddress: collectionAddress.toLowerCase(), expirationTime: new Date(new Date().getTime() + expiryInMinutes * 60 * 1000).toISOString(), maxAmount: principal.toString(), rate: apr * 10000, totalAmount: limit.toString(), signature: signature, marketplaceData: format.signatures[0].marketplaceData, }, ], userAddress: this.account.address.toLowerCase(), }; const result2 = await this.axios.post(`${config.blur.baseUrlBlend}/loan-offer/submit`, JSON.stringify(payload2), { headers: { "Content-Type": "application/json" }, }); const response = JSON.parse(result2.data); return { id: response.hashes[0], platform: LendingPlatform.blur, lender: this.account.address, offerDate: new Date(), expiryDate: new Date(new Date().getTime() + expiryInMinutes * 60 * 1000), type: OfferType.collectionOffer, currency: BETH, principal: principal, durationInDays: 0, apr: apr, collateral: { collectionAddress: collectionAddress, collectionName: "", nftId: "", }, }; } public async recallLoan(collectionAddress: `0x${string}`, loanId: string, nftId: string) { // Fetching the tx data const payload = { userAddress: this.account.address.toLowerCase(), contractAddress: collectionAddress.toLowerCase(), lienRequests: [ { lienId: loanId, tokenId: nftId, }, ], }; const result = await this.axios.post(`${config.blur.baseUrlBlend}/loan-offer/end`, JSON.stringify(payload), { headers: { "Content-Type": "application/json" }, }); const format = JSON.parse(result.data); // Sending the transaction const tx = format.data.actions[0].txnData; await this.client.sendTransaction(tx); } }