@positions/sdk
v0.1.0
Published
The official TypeScript SDK for interacting with the Positions Finance protocol.
Readme
Positions Finance SDK
The official TypeScript SDK for interacting with the Positions Finance protocol.
Table of Contents
- Installation
- Initialization
- Authentication
- Onboarding & Verification
- Market Discovery
- Core Interactions
- Polymarket CLOB Trading
- Monitoring & Analytics
Installation
The SDK relies on viem for Ethereum interactions.
npm install @positions/sdk viem
# or
yarn add @positions/sdk viem
# or
pnpm add @positions/sdk viem
# or
bun add @positions/sdk viemInitialization
The PositionsSDK is the main entry point. It requires an EIP-1193
compatible provider (like window.ethereum from Metamask, or a provider from Wagmi/RainbowKit).
import { PositionsSDK } from "@positions/sdk";
import { type EIP1193Provider } from "viem";
// Example with window.ethereum
const sdk = new PositionsSDK(window.ethereum as EIP1193Provider);
// The SDK automatically handles account changes from the provider.Authentication
The protocol uses Sign-In with Ethereum (SIWE) for secure authentication.
The SDK automatically handles login when you attempt to perform a protected action (like minting or depositing). However, you can also manage the session manually.
// Explicitly login (signs a SIWE message)
await sdk.login();
// Check if a session exists
const session = await sdk.getSession();
if (session) {
console.log("User is authenticated:", session.user);
}Onboarding & Verification
Before users can interact with the protocol (Deposit/Borrow), they must Mint the Positions NFT.
The invite-code gate has been removed. Anyone authenticated can mint and use the protocol.
NFT Verification & Minting
The Positions NFT acts as the user's identity and collateral manager within the protocol.
- Check for NFT: See if the connected wallet holds the NFT.
- Mint NFT: If not, mint one.
// 1. Get NFT details
const nft = await sdk.getNFT();
if (!nft) {
console.log("User needs to mint an NFT.");
// 2. Mint the NFT (Triggers a wallet transaction)
const txHash = await sdk.mint();
console.log("Mint transaction sent:", txHash);
} else {
console.log("User NFT ID:", nft.token.id);
}Referrals
Each user has a referral code, and may apply someone else's code once.
// Get your own referral code & stats
const referral = await sdk.getReferral();
console.log(referral.referralCode, referral.referralCount);
// Apply a referral code (one-time, cannot be your own)
await sdk.applyReferralCode("ABC123");Market Discovery
Lending Pool Assets
Retrieve the list of assets supported by the lending pool (e.g., USDC, WETH, WBTC). This provides necessary details like the token address and LTV (Loan-To-Value) ratio.
const assets = await sdk.getSupportedLendingPools();
assets.forEach((asset) => {
console.log(`${asset.symbol}: ${asset.address} (LTV: ${asset.ltv}%)`);
});Polymarket Events
Discover prediction markets from Polymarket that are supported by the protocol.
// Fetch active events
const events = await sdk.getPolyMarketEvents({
status: "active",
limit: 20
});
// Fetch events by tag
const sportsEvents = await sdk.getPolyMarketEvents({
tag: "Sports",
limit: 10
});
// Get specific market details by Token ID
const marketDetails = await sdk.getPolymarketEventByTokenId("TOKEN_ID_HERE");Featured & Watchlist
// Curated featured markets
const featured = await sdk.getFeaturedMarkets();
// Per-user watchlist (requires auth)
const watchlist = await sdk.getWatchlist();
await sdk.addToWatchlist(eventId);
await sdk.removeFromWatchlist(eventId);Market Filters
Discover markets live from Polymarket with sorting and fine-grained filters.
const markets = await sdk.filterMarkets({
sort: "trending", // trending | volume | liquidity | newest | endingSoon | topMovers | whaleActivity
probability: "60-80", // probability band
volume: ">100k",
liquidity: ">10k",
endDate: "<7d",
spread: "3c",
momentum: "gainers",
limit: 50
});Core Interactions
These interactions involve wallet transactions and smart contract calls. The SDK handles gas estimation, data encoding, and typing.
Depositing Assets
Deposits an Asset (e.g., USDC) into the lending pool.
Note: The SDK automatically handles approve transactions for the ERC-20 token before depositing if the allowance
is insufficient.
const usdcAddress = "0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174";
const amountToDeposit = 100; // Human-readable amount (e.g., 100 USDC)
try {
const tx = await sdk.deposit(usdcAddress, amountToDeposit);
console.log("Deposit successful:", tx);
} catch (err) {
console.error("Deposit failed:", err);
}Withdrawing Assets
Withdrawals are a two-step process for security and liquidity management: Queue -> Complete.
Step 1: Queue Withdrawal
Request to withdraw funds. This locks the request on-chain.
const amountToWithdraw = 50;
const txQueue = await sdk.queueWithdraw(usdcAddress, amountToWithdraw);
console.log("Withdrawal queued:", txQueue);Step 2: Complete Withdrawal
Once the protocol (or backend keeper) approves the withdrawal, the user must finalize it on-chain. You can find approved requests by filtering transactions.
// 1. Find approved withdrawal requests
const transactions = await sdk.getTransactions({
type: "withdraw",
status: "approved"
});
// 2. Complete them
for (const tx of transactions.data) {
if (tx.platform === "lending-pool") {
console.log(`Completing withdrawal for ${tx.amount} ${tx.asset}...`);
const txComplete = await sdk.completeWithdraw(
tx.asset as Address,
tx.requestId!
);
console.log("Withdrawal completed:", txComplete);
}
}Borrowing
Borrowing is an asynchronous process.
- User signs a borrow request and submits it to the PositionsRelayer (
requestCollateral). - Backend listens for the
CollateralRequestevent and validates collateral/health factor. - Backend fulfills the request on-chain, and funds are sent to the user.
const wbtcAddress = "0x1BFD67037B42CfDJ627031464303398BF7d6607";
const borrowAmount = 0.001;
// Triggers a signature request in the wallet
const tx = await sdk.borrowRequest(wbtcAddress, borrowAmount);
console.log("Borrow request signed and submitted:", tx);
// You can monitor the status via sdk.getTransactions({ type: 'borrow' })Repaying Debt
Repay borrowed assets to improve your health factor. Like deposits, this handles token approval automatically.
const repayAmount = 0.001;
const tx = await sdk.repayDebt(wbtcAddress, repayAmount);
console.log("Repayment transaction:", tx);Monitoring APY
Get the current Supply and Borrow APY for any asset.
depositApy and borrowApy are returned already expressed as percentages
(e.g. 5.25 means 5.25%).
const { depositApy, borrowApy } = await sdk.apy(usdcAddress);
console.log(`Supply APY: ${depositApy.toFixed(2)}%`);
console.log(`Borrow APY: ${borrowApy.toFixed(2)}%`);Polymarket Vault Interactions
Interact with the Polymarket Vault to deposit outcome tokens and manage withdrawals.
Deposit Polymarket Token
Deposits a Polymarket outcome token (ERC1155) into the vault. This automatically handles the setApprovalForAll
transaction if needed.
const conditionId = "0x..."; // Market condition ID
const tokenId = 123456789n; // Outcome token ID
const amount = 100; // Amount to deposit
const isNegRisk = false; // Whether the market is negative risk
const tx = await sdk.depositPolymarketToken(
conditionId,
tokenId,
amount,
isNegRisk
);
console.log("Deposit transaction:", tx);Withdraw Polymarket Token
Withdrawals from the Polymarket Vault also follow a two-step process: Request -> Claim.
Step 1: Request Withdrawal
const amountToWithdraw = 50;
const txRequest = await sdk.requestPolymarketWithdrawal(
tokenId,
amountToWithdraw
);
console.log("Withdrawal requested:", txRequest);Step 2: Claim Withdrawal
After the withdrawal request is processed (and the finalized request ID is available), you can claim the funds.
// 1. Find approved withdrawal requests
const transactions = await sdk.getTransactions({
type: "withdraw",
status: "approved"
});
// 2. Claim them
for (const tx of transactions.data) {
if (tx.platform === "polymarket") {
console.log(
`Claiming withdrawal for ${tx.amount} (Request ID: ${tx.requestId})...`
);
const txClaim = await sdk.claimPolymarketWithdrawal(BigInt(tx.requestId!));
console.log("Withdrawal claimed:", txClaim);
}
}Polymarket CLOB Trading
To acquire Polymarket outcome tokens (which you then deposit into the Positions
vault as collateral), users trade on the Polymarket CLOB. The SDK does not
place orders itself — use @polymarket/clob-client-v2
for that — but it provides everything needed to set the CLOB client up correctly:
proxy-wallet derivation, the right signature type, deployment, and collateral
approvals. All of this is available under sdk.polymarket.
v2 markets settle in PUSD (not the legacy USDC.e collateral).
Proxy Wallets & Signature Type
You can trade two ways:
- As the connected wallet (EOA, signature type
0) — funds & outcome tokens live on your own address. Perfectly valid if you are not using a Polymarket proxy account. - Through a Polymarket proxy wallet (signature type
1or2) — this is the account the Polymarket app uses; funds & outcome tokens live in a wallet derived from your EOA. Use this if you want to trade your existing Polymarket balance. In this mode orders must be signed with the proxy signature type and funded from the proxy address.
getClobAuth() returns the right { signerAddress, funderAddress, signatureType }
for whichever account you choose:
import { ClobClient, Chain } from "@polymarket/clob-client-v2";
// Polymarket proxy account (default: "safe", signature type 2 — browser wallets)
const { signerAddress, funderAddress, signatureType } =
await sdk.polymarket.getClobAuth();
// ...or trade directly as the connected wallet:
// const auth = await sdk.polymarket.getClobAuth("eoa"); // signatureType 0
const clob = new ClobClient(
signer,
Chain.POLYGON,
signatureType,
funderAddress
);You can also derive every wallet variant directly:
const wallets = await sdk.polymarket.deriveWallets();
// { eoa, safe, proxy, depositWallet }| getClobAuth(account) | Signature type | Funder | Used by |
| ---------------------- | -------------------- | ------------- | ---------------------------- |
| "eoa" | 0 EOA | EOA | Trading as your own wallet |
| "safe" (default) | 2 POLY_GNOSIS_SAFE | Gnosis Safe | Browser wallets |
| "proxy" | 1 POLY_PROXY | Magic proxy | Email / magic-link accounts |
| "depositWallet" | 2 | Deposit wallet | Polymarket v2 deposit wallet |
Deployment
A proxy wallet must be deployed before it can hold balances or approvals.
// Check
const deployed = await sdk.polymarket.isDeployed(); // "safe" by default
// Deploy (returns a relayer response — await .wait() to confirm)
if (!deployed) {
const res = await sdk.polymarket.deploy();
await res.wait();
}
// Or do both in one call
await sdk.polymarket.ensureDeployed();Collateral Approval
Before trading, approve the Conditional Tokens contract to move the proxy wallet's PUSD. The approval is executed through the proxy via the relayer.
const res = await sdk.polymarket.approveCollateral();
await res.wait();Monitoring & Analytics
Portfolio Health
Get a comprehensive overview of the user's financial position, including Health Factor and Loan-to-Value (LTV).
const portfolio = await sdk.getPortfolio();
console.log("Total Deposits (USD):", portfolio.deposit.total);
console.log("Total Debt (USD):", portfolio.borrow.total);
console.log("Health Factor:", portfolio.healthFactor); // Should be > 1.0
console.log("LTV:", portfolio.ltv, "%");
console.log("Max LTV:", portfolio.deposit.maxLtv, "%");
// Inspect individual assets
const usdcData = portfolio.deposit.assets[usdcAddress];
if (usdcData) {
console.log("USDC Deposited:", usdcData.amount);
console.log("Borrowing Power (USD):", usdcData.borrowingPower);
}
healthFactor,ltvandmaxLtvare computed server-side and returned directly — you no longer need to derive them on the client.
Transaction History
Fetch a paginated history of all user interactions (Deposits, Withdrawals, Borrows).
const history = await sdk.getTransactions({
page: 1,
limit: 10
// Optional filters
// type: 'deposit',
// status: 'completed'
});
console.log(`Found ${history.total} transactions.`);
console.table(history.data);Historical Data
Retrieve data for charting portfolio performance or protocol usage.
// Get daily transaction volume data
const graphData = await sdk.getTransactionGraphData({
interval: "day"
});
// Map for a charting library
const chartData = graphData.map((point) => ({
date: point.date,
volume: point.depositAmount + point.borrowAmount
}));
// Get historical APY / utilization for an asset
const apyData = await sdk.getApyGraphData({
interval: "day",
asset: usdcAddress
});Protocol Totals
Aggregated protocol-wide supplied and borrowed totals.
const totals = await sdk.getProtocolTotals();
console.log("Total Supplied (USD):", totals.supplied.total);
console.log("Total Borrowed (USD):", totals.borrowed.total);License
MIT
