@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 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
- # perpcity-sdk
1
+ # PerpCity SDK
2
2
 
3
- TypeScript SDK to interact with Perp City
3
+ TypeScript SDK for interacting with Perp City perpetual futures contracts on Base.
4
4
 
5
- ### Installation
5
+ ## Installation
6
6
 
7
+ ```bash
8
+ pnpm add @strobelabs/perpcity-sdk
7
9
  ```
8
- pnpm i @strobelabs/perpcity-sdk
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
- ### Getting Started
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)