@strobelabs/perpcity-sdk 0.1.7 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +339 -5
- package/dist/index.d.mts +295 -193
- package/dist/index.d.ts +295 -193
- package/dist/index.js +1057 -452
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1008 -446
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -4
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Strobe Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,12 +1,346 @@
|
|
|
1
|
-
#
|
|
1
|
+
# PerpCity SDK
|
|
2
2
|
|
|
3
|
-
TypeScript SDK
|
|
3
|
+
TypeScript SDK for interacting with Perp City perpetual futures contracts on Base.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @strobelabs/perpcity-sdk
|
|
7
9
|
```
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The SDK requires configuration via environment variables. Create a `.env` file:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Blockchain RPC endpoint
|
|
17
|
+
RPC_URL=https://sepolia.base.org
|
|
18
|
+
|
|
19
|
+
# Your private key (only for write operations)
|
|
20
|
+
PRIVATE_KEY=0x...
|
|
21
|
+
|
|
22
|
+
# Goldsky GraphQL API endpoint
|
|
23
|
+
GOLDSKY_ENDPOINT=https://api.goldsky.com/api/private/project_xxx/subgraphs/perp-city/xxx/gn
|
|
24
|
+
|
|
25
|
+
# Goldsky bearer token
|
|
26
|
+
GOLDSKY_BEARER_TOKEN=your_token_here
|
|
27
|
+
|
|
28
|
+
# Contract addresses
|
|
29
|
+
PERP_MANAGER_ADDRESS=0x59F1766b77fd67af6c80217C2025A0D536998000
|
|
30
|
+
USDC_ADDRESS=0xC1a5D4E99BB224713dd179eA9CA2Fa6600706210
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { PerpCityContext } from '@strobelabs/perpcity-sdk';
|
|
37
|
+
import { createWalletClient, http } from 'viem';
|
|
38
|
+
import { privateKeyToAccount } from 'viem/accounts';
|
|
39
|
+
import { baseSepolia } from 'viem/chains';
|
|
40
|
+
|
|
41
|
+
// Create wallet client
|
|
42
|
+
const account = privateKeyToAccount(process.env.PRIVATE_KEY);
|
|
43
|
+
const walletClient = createWalletClient({
|
|
44
|
+
account,
|
|
45
|
+
chain: baseSepolia,
|
|
46
|
+
transport: http(process.env.RPC_URL)
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Initialize context with configuration
|
|
50
|
+
const context = new PerpCityContext({
|
|
51
|
+
walletClient,
|
|
52
|
+
goldskyBearerToken: process.env.GOLDSKY_BEARER_TOKEN,
|
|
53
|
+
goldskyEndpoint: process.env.GOLDSKY_ENDPOINT,
|
|
54
|
+
deployments: {
|
|
55
|
+
perpManager: process.env.PERP_MANAGER_ADDRESS as `0x${string}`,
|
|
56
|
+
usdc: process.env.USDC_ADDRESS as `0x${string}`,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage with Wagmi (React + Privy)
|
|
62
|
+
|
|
63
|
+
The SDK is fully compatible with [wagmi](https://wagmi.sh) and works seamlessly with [Privy](https://privy.io) wallets.
|
|
64
|
+
|
|
65
|
+
### Setup
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { WagmiProvider, createConfig, http } from 'wagmi';
|
|
69
|
+
import { PrivyProvider } from '@privy-io/react-auth';
|
|
70
|
+
import { baseSepolia } from 'wagmi/chains';
|
|
71
|
+
|
|
72
|
+
// Configure wagmi
|
|
73
|
+
const wagmiConfig = createConfig({
|
|
74
|
+
chains: [baseSepolia],
|
|
75
|
+
transports: {
|
|
76
|
+
[baseSepolia.id]: http(),
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
// Wrap your app
|
|
81
|
+
<PrivyProvider appId="your-privy-app-id">
|
|
82
|
+
<WagmiProvider config={wagmiConfig}>
|
|
83
|
+
<App />
|
|
84
|
+
</WagmiProvider>
|
|
85
|
+
</PrivyProvider>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Use SDK with Wagmi
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import { useWalletClient, useChainId } from 'wagmi';
|
|
92
|
+
import { useMemo } from 'react';
|
|
93
|
+
import { PerpCityContext, openTakerPosition } from '@strobelabs/perpcity-sdk';
|
|
94
|
+
import { GraphQLClient } from 'graphql-request';
|
|
95
|
+
|
|
96
|
+
function usePerpCity() {
|
|
97
|
+
const { data: walletClient } = useWalletClient();
|
|
98
|
+
const chainId = useChainId();
|
|
99
|
+
|
|
100
|
+
return useMemo(() => {
|
|
101
|
+
if (!walletClient) return null;
|
|
102
|
+
|
|
103
|
+
// Wagmi's WalletClient is viem-compatible - works directly with SDK!
|
|
104
|
+
return new PerpCityContext({
|
|
105
|
+
walletClient,
|
|
106
|
+
goldskyBearerToken: process.env.GOLDSKY_BEARER_TOKEN,
|
|
107
|
+
goldskyEndpoint: process.env.GOLDSKY_ENDPOINT,
|
|
108
|
+
deployments: {
|
|
109
|
+
perpManager: process.env.PERP_MANAGER_ADDRESS as `0x${string}`,
|
|
110
|
+
usdc: process.env.USDC_ADDRESS as `0x${string}`,
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
}, [walletClient, chainId]);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// In your component
|
|
117
|
+
function TradingComponent({ perpId }) {
|
|
118
|
+
const context = usePerpCity();
|
|
119
|
+
|
|
120
|
+
const handleOpenLong = async () => {
|
|
121
|
+
if (!context) return;
|
|
122
|
+
|
|
123
|
+
const position = await openTakerPosition(context, perpId, {
|
|
124
|
+
isLong: true,
|
|
125
|
+
margin: 100, // $100 USDC
|
|
126
|
+
leverage: 2, // 2x leverage
|
|
127
|
+
unspecifiedAmountLimit: 0,
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
console.log('Position opened:', position.positionId);
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
return <button onClick={handleOpenLong}>Open Long 2x</button>;
|
|
134
|
+
}
|
|
9
135
|
```
|
|
10
136
|
|
|
11
|
-
|
|
137
|
+
See `examples/wagmi-integration.ts` for complete example with React components.
|
|
138
|
+
|
|
139
|
+
## Features
|
|
140
|
+
|
|
141
|
+
### Optimized Data Fetching
|
|
142
|
+
The SDK batches multiple GraphQL queries into single requests, dramatically improving performance:
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
// Fetch perp data with all related information in one call
|
|
146
|
+
const perpData = await context.getPerpData(perpId);
|
|
147
|
+
|
|
148
|
+
console.log(perpData.mark); // Current mark price
|
|
149
|
+
console.log(perpData.index); // Current index price
|
|
150
|
+
console.log(perpData.fundingRate); // Current funding rate
|
|
151
|
+
console.log(perpData.openInterest); // Open interest
|
|
152
|
+
console.log(perpData.markTimeSeries); // Historical mark prices
|
|
153
|
+
console.log(perpData.indexTimeSeries); // Historical index prices
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Functional API
|
|
157
|
+
Pure functions for data extraction:
|
|
158
|
+
|
|
159
|
+
```typescript
|
|
160
|
+
import {
|
|
161
|
+
getPerpMark,
|
|
162
|
+
getPerpIndex,
|
|
163
|
+
getPerpFundingRate,
|
|
164
|
+
getPerpBounds,
|
|
165
|
+
getPerpFees
|
|
166
|
+
} from '@strobelabs/perpcity-sdk';
|
|
167
|
+
|
|
168
|
+
// Use functional API for clean, composable code
|
|
169
|
+
const mark = getPerpMark(perpData);
|
|
170
|
+
const index = getPerpIndex(perpData);
|
|
171
|
+
const fundingRate = getPerpFundingRate(perpData);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Create and Manage Perps
|
|
175
|
+
|
|
176
|
+
```typescript
|
|
177
|
+
import { createPerp, getPerps } from '@strobelabs/perpcity-sdk';
|
|
178
|
+
|
|
179
|
+
// Create a new perpetual market
|
|
180
|
+
const perpId = await createPerp(context, {
|
|
181
|
+
startingPrice: 3000,
|
|
182
|
+
beacon: '0x...' // Beacon address for price oracle
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Get all perps
|
|
186
|
+
const allPerps = await getPerps(context);
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
### Manage Positions
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { OpenPosition, getAllTakerPositions, getAllMakerPositions } from '@strobelabs/perpcity-sdk';
|
|
193
|
+
|
|
194
|
+
// Get all taker positions for a perp
|
|
195
|
+
const takerPositions = await getAllTakerPositions(context, perpId);
|
|
196
|
+
for (const position of takerPositions) {
|
|
197
|
+
const liveDetails = await position.liveDetails();
|
|
198
|
+
console.log('Position PnL:', liveDetails.pnl);
|
|
199
|
+
console.log('Funding Payment:', liveDetails.fundingPayment);
|
|
200
|
+
console.log('Is Liquidatable:', liveDetails.isLiquidatable);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Get all maker positions for a perp
|
|
204
|
+
const makerPositions = await getAllMakerPositions(context, perpId);
|
|
205
|
+
|
|
206
|
+
// Close a position
|
|
207
|
+
const closedPosition = await takerPositions[0].closePosition({
|
|
208
|
+
margin: 0, // Full close
|
|
209
|
+
unspecifiedAmountLimit: 1000000
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
// Note: To open new positions, call the PerpManager contract directly using viem:
|
|
213
|
+
// const txHash = await context.walletClient.writeContract({
|
|
214
|
+
// address: context.deployments().perpManager,
|
|
215
|
+
// abi: PERP_MANAGER_ABI,
|
|
216
|
+
// functionName: 'openTakerPosition',
|
|
217
|
+
// args: [perpId, isLong, margin, leverage, unspecifiedAmountLimit]
|
|
218
|
+
// });
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
### Close Positions
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
// Close a position
|
|
225
|
+
const closedPosition = await position.closePosition({
|
|
226
|
+
minAmt0Out: 0,
|
|
227
|
+
minAmt1Out: 0,
|
|
228
|
+
maxAmt1In: 1000000
|
|
229
|
+
});
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### User Data
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
// Fetch comprehensive user data
|
|
236
|
+
const userData = await context.getUserData(userAddress);
|
|
237
|
+
|
|
238
|
+
console.log(userData.usdcBalance);
|
|
239
|
+
console.log(userData.openPositions);
|
|
240
|
+
console.log(userData.closedPositions);
|
|
241
|
+
console.log(userData.realizedPnl);
|
|
242
|
+
console.log(userData.unrealizedPnl);
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
## API Reference
|
|
246
|
+
|
|
247
|
+
### Core Classes
|
|
248
|
+
|
|
249
|
+
#### `PerpCityContext`
|
|
250
|
+
Base context for all SDK operations.
|
|
251
|
+
|
|
252
|
+
#### `GlobalPerpCityContext`
|
|
253
|
+
Optimized context that batches GraphQL queries for better performance.
|
|
254
|
+
|
|
255
|
+
### Main Functions
|
|
256
|
+
|
|
257
|
+
#### Perp Manager
|
|
258
|
+
- `getPerps(context)` - Get all perp IDs
|
|
259
|
+
- `createPerp(context, params)` - Create a new perp market
|
|
260
|
+
|
|
261
|
+
#### Perp Data (Pure Functions)
|
|
262
|
+
- `getPerpMark(perpData)` - Get mark price
|
|
263
|
+
- `getPerpIndex(perpData)` - Get index price
|
|
264
|
+
- `getPerpFundingRate(perpData)` - Get funding rate
|
|
265
|
+
- `getPerpBounds(perpData)` - Get margin and leverage bounds
|
|
266
|
+
- `getPerpFees(perpData)` - Get fee structure
|
|
267
|
+
- `getPerpOpenInterest(perpData)` - Get open interest
|
|
268
|
+
- `getPerpMarkTimeSeries(perpData)` - Get historical mark prices
|
|
269
|
+
- `getPerpIndexTimeSeries(perpData)` - Get historical index prices
|
|
270
|
+
|
|
271
|
+
#### Position Functions
|
|
272
|
+
- `getPositionPnl(positionData)` - Get position PnL
|
|
273
|
+
- `getPositionFundingPayment(positionData)` - Get funding payment
|
|
274
|
+
- `getPositionEffectiveMargin(positionData)` - Get effective margin
|
|
275
|
+
- `getPositionIsLiquidatable(positionData)` - Check if liquidatable
|
|
276
|
+
- `closePosition(context, perpId, positionId, params)` - Close a position
|
|
277
|
+
|
|
278
|
+
#### User Functions
|
|
279
|
+
- `getUserUsdcBalance(userData)` - Get USDC balance
|
|
280
|
+
- `getUserOpenPositions(userData)` - Get open positions
|
|
281
|
+
- `getUserClosedPositions(userData)` - Get closed positions
|
|
282
|
+
- `getUserRealizedPnl(userData)` - Get realized PnL
|
|
283
|
+
- `getUserUnrealizedPnl(userData)` - Get unrealized PnL
|
|
284
|
+
|
|
285
|
+
## Examples
|
|
286
|
+
|
|
287
|
+
Check the `/examples` directory for complete working examples:
|
|
288
|
+
|
|
289
|
+
- `create-perp.ts` - Create a new perpetual market
|
|
290
|
+
- `maker.ts` - Open a maker (liquidity provider) position
|
|
291
|
+
- `taker.ts` - Open a taker (long/short) position
|
|
292
|
+
- `close.ts` - Close an existing position
|
|
293
|
+
- `view.ts` - View perp and position data
|
|
294
|
+
- `optimized-view.ts` - Use optimized batch fetching
|
|
295
|
+
|
|
296
|
+
## Development
|
|
297
|
+
|
|
298
|
+
### Build
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
pnpm build
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### Test
|
|
305
|
+
|
|
306
|
+
```bash
|
|
307
|
+
# Run unit tests
|
|
308
|
+
pnpm test:unit
|
|
309
|
+
|
|
310
|
+
# Run integration tests (requires .env.local with GOLDSKY_BEARER_TOKEN)
|
|
311
|
+
pnpm test:integration
|
|
312
|
+
|
|
313
|
+
# Run all tests
|
|
314
|
+
pnpm test:all
|
|
315
|
+
|
|
316
|
+
# Watch mode
|
|
317
|
+
pnpm test:watch
|
|
318
|
+
|
|
319
|
+
# UI mode
|
|
320
|
+
pnpm test:ui
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### CI
|
|
324
|
+
|
|
325
|
+
```bash
|
|
326
|
+
# Run CI checks (build + unit tests)
|
|
327
|
+
pnpm ci
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Environment Setup
|
|
331
|
+
|
|
332
|
+
Create a `.env.local` file:
|
|
333
|
+
|
|
334
|
+
```env
|
|
335
|
+
PRIVATE_KEY=your_private_key_here
|
|
336
|
+
GOLDSKY_BEARER_TOKEN=your_goldsky_api_key_here
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
## License
|
|
340
|
+
|
|
341
|
+
GPL-3.0
|
|
342
|
+
|
|
343
|
+
## Links
|
|
12
344
|
|
|
345
|
+
- [Perp City Documentation](https://docs.perpcity.io)
|
|
346
|
+
- [Strobe Labs](https://strobelabs.io)
|