@velumx/sdk 2.0.0 → 2.1.0

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/README.md CHANGED
@@ -1,41 +1,39 @@
1
- # VelumX SDK
1
+ # @velumx/sdk
2
2
 
3
- The first Paymaster infrastructure on Stacks blockchain. Enable gasless transactions in your dApp - users pay gas fees in USDCx instead of STX.
3
+ > Gasless transaction SDK for Stacks - Pay fees in USDCx, not STX
4
4
 
5
- ## 🚀 Features
5
+ [![npm version](https://img.shields.io/npm/v/@velumx/sdk.svg)](https://www.npmjs.com/package/@velumx/sdk)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- - **Gasless Transactions**: Users pay fees in USDCx, not STX
8
- - **Account Abstraction**: Smart Wallet pattern with SIP-018 signing
9
- - **Simple Integration**: 3 lines of code to add gasless support
10
- - **Production Ready**: Battle-tested relayer infrastructure
11
- - **Developer Friendly**: TypeScript SDK with full type safety
8
+ ## Overview
12
9
 
13
- ## 📦 Installation
10
+ VelumX SDK enables gasless transactions on Stacks blockchain. Users pay transaction fees in USDCx instead of STX using Stacks' native sponsored transaction feature.
11
+
12
+ ### Key Features
13
+
14
+ - � **Zero STX Required** - Users only need USDCx
15
+ - ⚡ **Native Sponsorship** - Uses Stacks' built-in `sponsored` flag
16
+ - 🔧 **Simple Integration** - 3 lines of code
17
+ - 📦 **Lightweight** - ~50KB minified
18
+ - � **Secure** - No smart wallet complexity
19
+
20
+ ## Installation
14
21
 
15
22
  ```bash
16
23
  npm install @velumx/sdk
17
24
  ```
18
25
 
19
- ## 🔧 Quick Start
20
-
21
- ### 1. Get API Key
26
+ ## Quick Start
22
27
 
23
- Register your dApp at [dashboard.velumx.com](https://dashboard.velumx.com) to get your API key.
24
-
25
- ### 2. Initialize Client
28
+ ### 1. Initialize Client
26
29
 
27
30
  ```typescript
28
- import { VelumXClient } from '@velumx/sdk';
31
+ import { getVelumXClient } from '@velumx/sdk';
29
32
 
30
- const velumx = new VelumXClient({
31
- coreApiUrl: 'https://api.testnet.hiro.so',
32
- network: 'testnet',
33
- paymasterUrl: 'https://relayer.velumx.com/api/v1',
34
- apiKey: 'your-api-key-here'
35
- });
33
+ const velumx = getVelumXClient();
36
34
  ```
37
35
 
38
- ### 3. Estimate Fee
36
+ ### 2. Estimate Fee
39
37
 
40
38
  ```typescript
41
39
  const estimate = await velumx.estimateFee({
@@ -43,263 +41,675 @@ const estimate = await velumx.estimateFee({
43
41
  });
44
42
 
45
43
  console.log(`Fee: ${estimate.maxFeeUSDCx} micro-USDCx`);
44
+ // Output: Fee: 540000 micro-USDCx (0.54 USDCx)
46
45
  ```
47
46
 
48
- ### 4. Submit Gasless Transaction
47
+ ### 3. Execute Gasless Transaction
49
48
 
50
49
  ```typescript
51
- import { tupleCV, uintCV, bufferCV, serializeCV } from '@stacks/transactions';
52
-
53
- // Create your transaction payload
54
- const payload = tupleCV({
55
- amount: uintCV(1000000), // 1 USDCx
56
- recipient: bufferCV(recipientBytes)
50
+ import { openContractCall } from '@stacks/connect';
51
+ import { Cl } from '@stacks/transactions';
52
+
53
+ // Call paymaster contract with sponsored=true
54
+ const result = await openContractCall({
55
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
56
+ contractName: 'simple-paymaster-v1',
57
+ functionName: 'bridge-gasless',
58
+ functionArgs: [
59
+ Cl.uint(10000000), // 10 USDCx
60
+ Cl.buffer(recipientBytes),
61
+ Cl.uint(estimate.maxFeeUSDCx),
62
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
63
+ Cl.principal('ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx')
64
+ ],
65
+ sponsored: true, // Enable gasless mode
66
+ network: 'testnet',
67
+ onFinish: async (data) => {
68
+ // Submit to relayer for sponsorship
69
+ const tx = await velumx.submitRawTransaction(data.txRaw);
70
+ console.log(`Transaction: ${tx.txid}`);
71
+ }
57
72
  });
73
+ ```
58
74
 
59
- // Create intent
60
- const intent = {
61
- target: 'ST...CONTRACT.paymaster-module-v10',
62
- payload: serializeCV(payload),
63
- maxFeeUSDCx: estimate.maxFeeUSDCx,
64
- nonce: currentNonce
65
- };
66
-
67
- // Sign with user's wallet (SIP-018)
68
- const signature = await signWithWallet(intent);
69
-
70
- // Submit to relayer
71
- const result = await velumx.submitIntent({
72
- ...intent,
73
- signature
74
- });
75
+ ## How It Works
76
+
77
+ ### Architecture
75
78
 
76
- console.log(`Transaction ID: ${result.txid}`);
79
+ ```
80
+ ┌──────────┐ ┌──────────┐
81
+ │ User │ │ Relayer │
82
+ └────┬─────┘ └────┬─────┘
83
+ │ │
84
+ │ 1. Request fee estimate │
85
+ ├──────────────────────────────────────────────► │
86
+ │ │
87
+ │ 2. Return fee in USDCx │
88
+ │ ◄──────────────────────────────────────────────┤
89
+ │ │
90
+ │ 3. Sign transaction (sponsored=true) │
91
+ │ │
92
+ │ 4. Submit signed transaction │
93
+ ├──────────────────────────────────────────────► │
94
+ │ │
95
+ │ │ 5. Sponsor with STX
96
+ │ │ & broadcast
97
+ │ │
98
+ │ 6. Return transaction ID │
99
+ │ ◄──────────────────────────────────────────────┤
100
+ │ │
101
+ ▼ ▼
102
+
103
+ ┌─────────────────────────────────────────────────────┐
104
+ │ Stacks Blockchain │
105
+ │ │
106
+ │ simple-paymaster-v1::bridge-gasless │
107
+ │ • Transfer USDCx fee from user to relayer │
108
+ │ • Execute core logic (burn/swap) │
109
+ │ • Transaction confirmed ✓ │
110
+ └─────────────────────────────────────────────────────┘
111
+ ```
112
+
113
+ ### Fee Calculation
114
+
115
+ ```
116
+ Fee in any SIP-010 token = (Gas Cost in STX × STX/USD Rate × 1.08) / Token/USD Rate
117
+
118
+ Example with USDCx:
119
+ - Gas: 100,000 units = 1 STX
120
+ - STX/USD: $0.50
121
+ - USDC/USD: $1.00
122
+ - Markup: 8%
123
+ - Fee: 1 × $0.50 × 1.08 / $1.00 = 0.54 USDCx
124
+
125
+ Example with sBTC:
126
+ - Gas: 100,000 units = 1 STX
127
+ - STX/USD: $0.50
128
+ - BTC/USD: $45,000
129
+ - Markup: 8%
130
+ - Fee: 1 × $0.50 × 1.08 / $45,000 = 0.000012 BTC (1,200 sats)
131
+
132
+ Example with ALEX:
133
+ - Gas: 100,000 units = 1 STX
134
+ - STX/USD: $0.50
135
+ - ALEX/USD: $0.10
136
+ - Markup: 8%
137
+ - Fee: 1 × $0.50 × 1.08 / $0.10 = 5.4 ALEX
77
138
  ```
78
139
 
79
- ## 📚 API Reference
140
+ ## API Reference
80
141
 
81
142
  ### VelumXClient
82
143
 
83
- #### Constructor
144
+ #### Configuration
84
145
 
85
146
  ```typescript
86
- new VelumXClient(config: NetworkConfig)
147
+ interface NetworkConfig {
148
+ coreApiUrl: string; // Stacks API URL
149
+ network: 'mainnet' | 'testnet' | 'devnet';
150
+ paymasterUrl?: string; // Relayer URL (optional)
151
+ }
87
152
  ```
88
153
 
89
- **NetworkConfig:**
90
- - `coreApiUrl`: Stacks API URL (mainnet/testnet)
91
- - `network`: 'mainnet' | 'testnet' | 'devnet'
92
- - `paymasterUrl`: VelumX relayer URL
93
- - `apiKey`: Your dApp API key (optional for testnet)
154
+ **Default Configuration**:
155
+ ```typescript
156
+ {
157
+ coreApiUrl: 'https://api.testnet.hiro.so',
158
+ network: 'testnet',
159
+ paymasterUrl: 'https://sgal-relayer.onrender.com/api/v1'
160
+ }
161
+ ```
94
162
 
95
163
  #### Methods
96
164
 
97
165
  ##### estimateFee()
98
166
 
167
+ Get fee estimate in USDCx for a transaction.
168
+
99
169
  ```typescript
100
- estimateFee(intent: { estimatedGas: number }): Promise<{
101
- maxFeeUSDCx: string;
102
- estimatedGas: number;
103
- }>
170
+ estimateFee(params: {
171
+ estimatedGas: number
172
+ }): Promise<FeeEstimate>
104
173
  ```
105
174
 
106
- Get fee estimate in USDCx for a transaction.
107
-
108
- ##### submitIntent()
175
+ **Parameters**:
176
+ - `estimatedGas`: Estimated gas units (e.g., 100000)
109
177
 
178
+ **Returns**:
110
179
  ```typescript
111
- submitIntent(signedIntent: SignedIntent): Promise<{
112
- txid: string;
113
- status: string;
114
- }>
180
+ interface FeeEstimate {
181
+ maxFeeUSDCx: string; // Fee in micro-USDCx
182
+ estimatedGas: number; // Gas units
183
+ stxToUsd?: number; // Exchange rate
184
+ markup?: number; // Fee markup (0.08 = 8%)
185
+ }
115
186
  ```
116
187
 
117
- Submit a signed intent for gasless execution.
188
+ **Example**:
189
+ ```typescript
190
+ const estimate = await velumx.estimateFee({
191
+ estimatedGas: 100000
192
+ });
118
193
 
119
- **SignedIntent:**
120
- - `target`: Contract principal to call
121
- - `payload`: Hex-encoded transaction payload
122
- - `maxFeeUSDCx`: Maximum fee in micro-USDCx
123
- - `nonce`: Smart Wallet nonce
124
- - `signature`: SIP-018 signature
194
+ console.log(`Fee: ${estimate.maxFeeUSDCx} micro-USDCx`);
195
+ // Fee: 540000 micro-USDCx (0.54 USDCx)
196
+ ```
125
197
 
126
198
  ##### submitRawTransaction()
127
199
 
200
+ Submit a signed transaction for sponsorship.
201
+
128
202
  ```typescript
129
- submitRawTransaction(txHex: string): Promise<{
130
- txid: string;
131
- status: string;
132
- }>
203
+ submitRawTransaction(txRaw: string): Promise<TransactionResult>
133
204
  ```
134
205
 
135
- Submit a raw Stacks transaction for sponsorship.
206
+ **Parameters**:
207
+ - `txRaw`: Hex-encoded signed transaction from wallet
136
208
 
137
- ## 🎯 Use Cases
138
-
139
- ### Bridge Transactions
209
+ **Returns**:
210
+ ```typescript
211
+ interface TransactionResult {
212
+ txid: string; // Transaction ID
213
+ status: string; // Status (pending/success/failed)
214
+ }
215
+ ```
140
216
 
217
+ **Example**:
141
218
  ```typescript
142
- // User bridges USDC from Ethereum to Stacks
143
- // Pays gas fee in USDCx instead of STX
144
- const payload = tupleCV({
145
- amount: uintCV(5000000), // 5 USDCx
146
- fee: uintCV(250000), // 0.25 USDCx fee
147
- recipient: bufferCV(ethAddressBytes)
148
- });
219
+ const result = await velumx.submitRawTransaction(data.txRaw);
220
+ console.log(`Transaction ID: ${result.txid}`);
221
+ ```
149
222
 
150
- const result = await velumx.submitIntent({
151
- target: 'ST...ADMIN.paymaster-module-v10',
152
- payload: serializeCV(payload),
153
- maxFeeUSDCx: '250000',
154
- nonce: 0,
155
- signature: userSignature
156
- });
223
+ ##### sponsorTransaction()
224
+
225
+ High-level helper to make any transaction gasless.
226
+
227
+ ```typescript
228
+ sponsorTransaction(params: {
229
+ transaction: any;
230
+ network: 'mainnet' | 'testnet';
231
+ }): Promise<any>
157
232
  ```
158
233
 
159
- ### Token Swaps
234
+ **Parameters**:
235
+ - `transaction`: Unsigned Stacks transaction
236
+ - `network`: Target network
237
+
238
+ **Returns**: Transaction with `sponsored: true` flag
160
239
 
240
+ **Example**:
161
241
  ```typescript
162
- // User swaps tokens without needing STX
163
- const payload = tupleCV({
164
- tokenIn: principalCV('ST...TOKEN-A'),
165
- tokenOut: principalCV('ST...TOKEN-B'),
166
- amountIn: uintCV(1000000),
167
- minOut: uintCV(950000),
168
- fee: uintCV(200000)
169
- });
242
+ import { makeContractCall } from '@stacks/transactions';
243
+
244
+ const unsignedTx = await makeContractCall({...});
170
245
 
171
- const result = await velumx.submitIntent({
172
- target: 'ST...ADMIN.swap-contract',
173
- payload: serializeCV(payload),
174
- maxFeeUSDCx: '200000',
175
- nonce: 1,
176
- signature: userSignature
246
+ const sponsored = await velumx.sponsorTransaction({
247
+ transaction: unsignedTx,
248
+ network: 'testnet'
177
249
  });
250
+
251
+ // User signs and broadcasts
252
+ const result = await openContractCall(sponsored);
178
253
  ```
179
254
 
180
- ### NFT Minting
255
+ ## Use Cases
256
+
257
+ ### 1. Gasless Bridge
258
+
259
+ Bridge USDC from Ethereum to Stacks without needing STX.
181
260
 
182
261
  ```typescript
183
- // User mints NFT paying gas in USDCx
184
- const payload = tupleCV({
185
- recipient: principalCV(userAddress),
186
- tokenId: uintCV(42),
187
- fee: uintCV(300000)
188
- });
262
+ import { getVelumXClient } from '@velumx/sdk';
263
+ import { openContractCall } from '@stacks/connect';
264
+ import { Cl } from '@stacks/transactions';
265
+ import { parseUnits } from 'viem';
266
+
267
+ async function gaslessBridge(amount: string, recipient: string) {
268
+ const velumx = getVelumXClient();
269
+
270
+ // 1. Estimate fee
271
+ const estimate = await velumx.estimateFee({
272
+ estimatedGas: 100000
273
+ });
274
+
275
+ // 2. Encode Ethereum address
276
+ const recipientBytes = encodeEthereumAddress(recipient);
277
+
278
+ // 3. Execute gasless bridge
279
+ const result = await openContractCall({
280
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
281
+ contractName: 'simple-paymaster-v1',
282
+ functionName: 'bridge-gasless',
283
+ functionArgs: [
284
+ Cl.uint(parseUnits(amount, 6)),
285
+ Cl.buffer(recipientBytes),
286
+ Cl.uint(estimate.maxFeeUSDCx),
287
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
288
+ Cl.principal('ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx')
289
+ ],
290
+ sponsored: true,
291
+ network: 'testnet',
292
+ onFinish: async (data) => {
293
+ const tx = await velumx.submitRawTransaction(data.txRaw);
294
+ console.log(`Bridge transaction: ${tx.txid}`);
295
+ }
296
+ });
297
+ }
189
298
 
190
- const result = await velumx.submitIntent({
191
- target: 'ST...ADMIN.nft-contract',
192
- payload: serializeCV(payload),
193
- maxFeeUSDCx: '300000',
194
- nonce: 2,
195
- signature: userSignature
196
- });
299
+ // Helper function
300
+ function encodeEthereumAddress(address: string): Uint8Array {
301
+ const hex = address.startsWith('0x') ? address.slice(2) : address;
302
+ const paddedHex = hex.padStart(64, '0');
303
+ const bytes = new Uint8Array(32);
304
+ for (let i = 0; i < 32; i++) {
305
+ bytes[i] = parseInt(paddedHex.substring(i * 2, i * 2 + 2), 16);
306
+ }
307
+ return bytes;
308
+ }
309
+ ```
310
+
311
+ ### 2. Gasless Swap
312
+
313
+ Swap tokens without holding STX.
314
+
315
+ ```typescript
316
+ async function gaslessSwap(
317
+ tokenIn: string,
318
+ tokenOut: string,
319
+ amountIn: string,
320
+ minOut: string
321
+ ) {
322
+ const velumx = getVelumXClient();
323
+
324
+ // 1. Estimate fee
325
+ const estimate = await velumx.estimateFee({
326
+ estimatedGas: 150000
327
+ });
328
+
329
+ // 2. Execute gasless swap
330
+ const result = await openContractCall({
331
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
332
+ contractName: 'simple-paymaster-v1',
333
+ functionName: 'swap-gasless',
334
+ functionArgs: [
335
+ Cl.principal(tokenIn),
336
+ Cl.principal(tokenOut),
337
+ Cl.uint(parseUnits(amountIn, 6)),
338
+ Cl.uint(parseUnits(minOut, 6)),
339
+ Cl.uint(estimate.maxFeeUSDCx),
340
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
341
+ Cl.principal('ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx')
342
+ ],
343
+ sponsored: true,
344
+ network: 'testnet',
345
+ onFinish: async (data) => {
346
+ const tx = await velumx.submitRawTransaction(data.txRaw);
347
+ console.log(`Swap transaction: ${tx.txid}`);
348
+ }
349
+ });
350
+ }
197
351
  ```
198
352
 
199
- ## 🔐 Smart Wallet Setup
353
+ ### 3. Custom Gasless Transaction
200
354
 
201
- Users need a Smart Wallet to use gasless transactions. The SDK handles this automatically:
355
+ Make any contract call gasless.
202
356
 
203
357
  ```typescript
204
- import { getSmartWalletManager } from '@velumx/sdk';
358
+ async function customGaslessTransaction() {
359
+ const velumx = getVelumXClient();
360
+
361
+ // 1. Estimate fee
362
+ const estimate = await velumx.estimateFee({
363
+ estimatedGas: 120000
364
+ });
365
+
366
+ // 2. Your custom contract call
367
+ const result = await openContractCall({
368
+ contractAddress: 'YOUR_CONTRACT_ADDRESS',
369
+ contractName: 'your-contract',
370
+ functionName: 'your-function',
371
+ functionArgs: [
372
+ // Your function args
373
+ Cl.uint(estimate.maxFeeUSDCx), // Include fee
374
+ // More args...
375
+ ],
376
+ sponsored: true, // Enable gasless
377
+ network: 'testnet',
378
+ onFinish: async (data) => {
379
+ const tx = await velumx.submitRawTransaction(data.txRaw);
380
+ console.log(`Transaction: ${tx.txid}`);
381
+ }
382
+ });
383
+ }
384
+ ```
385
+
386
+ ### 4. Using Different Fee Tokens
205
387
 
206
- const manager = getSmartWalletManager();
388
+ Pay fees in sBTC, ALEX, or any SIP-010 token.
207
389
 
208
- // Check if user has Smart Wallet
209
- const hasWallet = await manager.hasSmartWallet(userAddress);
390
+ ```typescript
391
+ async function gaslessWithSBTC(amount: string) {
392
+ const velumx = getVelumXClient();
393
+
394
+ // 1. Estimate fee (returns USDCx equivalent)
395
+ const estimate = await velumx.estimateFee({
396
+ estimatedGas: 100000
397
+ });
398
+
399
+ // 2. Convert fee to sBTC (example: 0.54 USDCx → 0.000012 BTC)
400
+ const feeInSBTC = convertToSBTC(estimate.maxFeeUSDCx);
401
+
402
+ // 3. Execute with sBTC as fee token
403
+ const result = await openContractCall({
404
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
405
+ contractName: 'simple-paymaster-v1',
406
+ functionName: 'bridge-gasless',
407
+ functionArgs: [
408
+ Cl.uint(parseUnits(amount, 6)),
409
+ Cl.buffer(recipientBytes),
410
+ Cl.uint(feeInSBTC), // Fee in sBTC
411
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
412
+ Cl.principal('SM3KNVZS30WM7F89SXKVVFY4SN9RMPZZ9FX929N0V.sbtc') // sBTC token
413
+ ],
414
+ sponsored: true,
415
+ network: 'testnet',
416
+ onFinish: async (data) => {
417
+ const tx = await velumx.submitRawTransaction(data.txRaw);
418
+ console.log(`Transaction: ${tx.txid}`);
419
+ }
420
+ });
421
+ }
422
+
423
+ // Helper: Convert USDCx fee to sBTC
424
+ function convertToSBTC(feeInUSDCx: string): string {
425
+ // Example conversion (fetch real rates from API)
426
+ const usdcAmount = Number(feeInUSDCx) / 1_000_000; // 0.54 USDC
427
+ const btcPrice = 45000; // $45,000 per BTC
428
+ const btcAmount = usdcAmount / btcPrice; // 0.000012 BTC
429
+ const satoshis = Math.ceil(btcAmount * 100_000_000); // 1,200 sats
430
+ return satoshis.toString();
431
+ }
210
432
 
211
- if (!hasWallet) {
212
- // Auto-register (one-time setup)
213
- const result = await manager.ensureSmartWallet(userAddress);
214
- console.log(`Smart Wallet: ${result}`);
433
+ // Using ALEX token
434
+ async function gaslessWithALEX(amount: string) {
435
+ const velumx = getVelumXClient();
436
+
437
+ const estimate = await velumx.estimateFee({
438
+ estimatedGas: 100000
439
+ });
440
+
441
+ // Convert to ALEX (example: 0.54 USDCx → 5.4 ALEX)
442
+ const feeInALEX = convertToALEX(estimate.maxFeeUSDCx);
443
+
444
+ const result = await openContractCall({
445
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
446
+ contractName: 'simple-paymaster-v1',
447
+ functionName: 'bridge-gasless',
448
+ functionArgs: [
449
+ Cl.uint(parseUnits(amount, 6)),
450
+ Cl.buffer(recipientBytes),
451
+ Cl.uint(feeInALEX), // Fee in ALEX
452
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
453
+ Cl.principal('ALEX_TOKEN_ADDRESS') // ALEX token
454
+ ],
455
+ sponsored: true,
456
+ network: 'testnet',
457
+ onFinish: async (data) => {
458
+ const tx = await velumx.submitRawTransaction(data.txRaw);
459
+ console.log(`Transaction: ${tx.txid}`);
460
+ }
461
+ });
215
462
  }
216
463
  ```
217
464
 
218
- ## 💰 Fee Structure
465
+ ## Smart Contract Integration
466
+
467
+ To make your contract gasless-compatible, accept a fee parameter and transfer it to the relayer:
468
+
469
+ ```clarity
470
+ (define-public (your-gasless-function
471
+ (amount uint)
472
+ (fee-usdcx uint)
473
+ (relayer principal)
474
+ (fee-token <sip-010-trait>))
475
+ (begin
476
+ ;; 1. Transfer fee from user to relayer
477
+ (try! (contract-call? fee-token transfer
478
+ fee-usdcx tx-sender relayer none))
479
+
480
+ ;; 2. Your contract logic
481
+ (try! (your-logic amount))
482
+
483
+ (ok true)
484
+ )
485
+ )
486
+ ```
219
487
 
220
- - **Base Fee**: Actual STX gas cost converted to USDCx
221
- - **Markup**: 8% (configurable by relayer)
222
- - **Example**: 0.005 STX gas = ~$0.0025 = 0.0025 USDCx + 8% = 0.0027 USDCx
488
+ ## Configuration
223
489
 
224
- ## 🌐 Network Support
490
+ ### Supported Fee Tokens
225
491
 
226
- ### Testnet
227
- - Relayer: `https://relayer.velumx.com/api/v1`
228
- - Stacks API: `https://api.testnet.hiro.so`
229
- - Free for development (no API key required)
492
+ VelumX accepts ANY SIP-010 token for gas fees. The paymaster contract uses the `<sip-010-trait>` parameter for universal compatibility.
230
493
 
231
- ### Mainnet
232
- - Relayer: `https://mainnet-relayer.velumx.com/api/v1`
233
- - Stacks API: `https://api.mainnet.hiro.so`
234
- - Requires API key from dashboard
494
+ **Popular Tokens:**
235
495
 
236
- ## 🛠️ Advanced Usage
496
+ | Token | Contract Address | Decimals | Use Case |
497
+ |-------|-----------------|----------|----------|
498
+ | USDCx | `ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx` | 6 | Stablecoin fees |
499
+ | sBTC | `SM3KNVZS30WM7F89SXKVVFY4SN9RMPZZ9FX929N0V.sbtc` | 8 | Bitcoin fees |
500
+ | ALEX | `ALEX_TOKEN_ADDRESS` | 6 | DeFi token fees |
501
+ | STX | Native | 6 | Native token fees |
237
502
 
238
- ### Custom Fee Calculation
503
+ **Exchange Rate Calculation:**
239
504
 
240
505
  ```typescript
241
- // Get exchange rates
242
- const rates = await velumx.getExchangeRates();
243
- console.log(`STX/USD: ${rates.stxToUsd}`);
506
+ // Fetch real-time exchange rates
507
+ async function calculateFeeInToken(
508
+ feeInUSDCx: string,
509
+ targetToken: 'sBTC' | 'ALEX' | 'STX'
510
+ ): Promise<string> {
511
+ const usdcAmount = Number(feeInUSDCx) / 1_000_000;
512
+
513
+ // Fetch rates from price oracle or API
514
+ const rates = await fetchExchangeRates();
515
+
516
+ switch (targetToken) {
517
+ case 'sBTC':
518
+ const btcAmount = usdcAmount / rates.BTC_USD;
519
+ return Math.ceil(btcAmount * 100_000_000).toString(); // Convert to satoshis
520
+
521
+ case 'ALEX':
522
+ const alexAmount = usdcAmount / rates.ALEX_USD;
523
+ return Math.ceil(alexAmount * 1_000_000).toString(); // Convert to micro-ALEX
524
+
525
+ case 'STX':
526
+ const stxAmount = usdcAmount / rates.STX_USD;
527
+ return Math.ceil(stxAmount * 1_000_000).toString(); // Convert to micro-STX
528
+
529
+ default:
530
+ return feeInUSDCx;
531
+ }
532
+ }
244
533
 
245
- // Calculate custom fee
246
- const gasInStx = 0.005;
247
- const gasInUsd = gasInStx * rates.stxToUsd;
248
- const feeInUsdcx = gasInUsd * 1.08; // 8% markup
534
+ // Example usage
535
+ const estimate = await velumx.estimateFee({ estimatedGas: 100000 });
536
+ const feeInSBTC = await calculateFeeInToken(estimate.maxFeeUSDCx, 'sBTC');
249
537
  ```
250
538
 
251
- ### Transaction Monitoring
539
+ ### Environment Variables
252
540
 
253
- ```typescript
254
- // Submit transaction
255
- const result = await velumx.submitIntent(signedIntent);
541
+ ```bash
542
+ # Frontend (.env.local)
543
+ NEXT_PUBLIC_STACKS_NETWORK=testnet
544
+ NEXT_PUBLIC_STACKS_API_URL=https://api.testnet.hiro.so
545
+ NEXT_PUBLIC_VELUMX_RELAYER_URL=https://sgal-relayer.onrender.com/api/v1
546
+
547
+ # Contracts
548
+ NEXT_PUBLIC_STACKS_PAYMASTER_ADDRESS=STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P.simple-paymaster-v1
549
+ NEXT_PUBLIC_STACKS_USDCX_ADDRESS=ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx
550
+ ```
551
+
552
+ ### Network Configuration
256
553
 
257
- // Monitor status
258
- const status = await fetch(
259
- `https://api.testnet.hiro.so/extended/v1/tx/${result.txid}`
260
- );
554
+ ```typescript
555
+ // Testnet (default)
556
+ const velumx = getVelumXClient();
261
557
 
262
- const data = await status.json();
263
- console.log(`Status: ${data.tx_status}`);
558
+ // Mainnet
559
+ const velumx = new VelumXClient({
560
+ coreApiUrl: 'https://api.mainnet.hiro.so',
561
+ network: 'mainnet',
562
+ paymasterUrl: 'https://mainnet-relayer.velumx.com/api/v1'
563
+ });
264
564
  ```
265
565
 
266
- ### Error Handling
566
+ ## Error Handling
267
567
 
268
568
  ```typescript
269
569
  try {
270
- const result = await velumx.submitIntent(signedIntent);
570
+ const estimate = await velumx.estimateFee({
571
+ estimatedGas: 100000
572
+ });
573
+
574
+ const result = await openContractCall({
575
+ // ... transaction params
576
+ onFinish: async (data) => {
577
+ try {
578
+ const tx = await velumx.submitRawTransaction(data.txRaw);
579
+ console.log(`Success: ${tx.txid}`);
580
+ } catch (error) {
581
+ if (error.message.includes('insufficient balance')) {
582
+ console.error('User needs more USDCx for fees');
583
+ } else if (error.message.includes('invalid signature')) {
584
+ console.error('Signature verification failed');
585
+ } else {
586
+ console.error('Transaction failed:', error);
587
+ }
588
+ }
589
+ },
590
+ onCancel: () => {
591
+ console.log('User cancelled transaction');
592
+ }
593
+ });
271
594
  } catch (error) {
272
- if (error.message.includes('insufficient balance')) {
273
- console.error('User needs more USDCx for fees');
274
- } else if (error.message.includes('invalid signature')) {
275
- console.error('Signature verification failed');
276
- } else {
277
- console.error('Transaction failed:', error);
278
- }
595
+ console.error('Failed to estimate fee:', error);
279
596
  }
280
597
  ```
281
598
 
282
- ## 📖 Examples
599
+ ## Testing
600
+
601
+ ### Unit Tests
602
+
603
+ ```bash
604
+ npm test
605
+ ```
606
+
607
+ ### Integration Tests
608
+
609
+ ```bash
610
+ npm run test:integration
611
+ ```
612
+
613
+ ### Example Test
614
+
615
+ ```typescript
616
+ import { getVelumXClient } from '@velumx/sdk';
617
+
618
+ describe('VelumX SDK', () => {
619
+ it('should estimate fee correctly', async () => {
620
+ const velumx = getVelumXClient();
621
+
622
+ const estimate = await velumx.estimateFee({
623
+ estimatedGas: 100000
624
+ });
625
+
626
+ expect(estimate.maxFeeUSDCx).toBeDefined();
627
+ expect(Number(estimate.maxFeeUSDCx)).toBeGreaterThan(0);
628
+ });
629
+ });
630
+ ```
631
+
632
+ ## Deployed Contracts
633
+
634
+ ### Testnet
635
+
636
+ **Simple Paymaster**
637
+ ```
638
+ Address: STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P.simple-paymaster-v1
639
+ Network: Stacks Testnet
640
+ Explorer: https://explorer.hiro.so/txid/0x90c134205b04599405e3cccae6c86ed496ae2d81ef0392970e2c9a7acd3b2138?chain=testnet
641
+ ```
283
642
 
284
- Check out complete examples:
285
- - [Bridge dApp](../examples/bridge)
286
- - [DEX Integration](../examples/swap)
287
- - [NFT Marketplace](../examples/nft)
643
+ **USDCx Token**
644
+ ```
645
+ Address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx
646
+ Standard: SIP-010
647
+ Decimals: 6
648
+ ```
288
649
 
289
- ## 🤝 Support
650
+ **Relayer**
651
+ ```
652
+ URL: https://sgal-relayer.onrender.com/api/v1
653
+ Status: https://sgal-relayer.onrender.com/api/v1/health
654
+ ```
655
+
656
+ ## FAQ
657
+
658
+ ### Q: Do users need STX?
659
+ **A:** No! Users only need any SIP-010 token (USDCx, sBTC, ALEX, etc.). The relayer pays STX fees.
660
+
661
+ ### Q: What tokens can I use for fees?
662
+ **A:** Any SIP-010 compliant token! Popular options include USDCx, sBTC, ALEX, and STX. The paymaster contract uses the `<sip-010-trait>` parameter for universal compatibility.
663
+
664
+ ### Q: How much does it cost?
665
+ **A:** Fees are calculated in real-time based on STX/USD rates with an 8% markup. Typically 0.001-0.01 USDCx (or equivalent in other tokens) per transaction.
666
+
667
+ ### Q: Is it secure?
668
+ **A:** Yes! Uses Stacks' native sponsored transaction feature. No smart wallet complexity.
669
+
670
+ ### Q: What wallets are supported?
671
+ **A:** Any Stacks wallet (Xverse, Leather, Hiro) that supports sponsored transactions.
672
+
673
+ ### Q: Can I use this in production?
674
+ **A:** Currently on testnet. Mainnet launch pending security audit.
675
+
676
+ ### Q: How do I get an API key?
677
+ **A:** Visit [https://velum-x-ssum.vercel.app](https://velum-x-ssum.vercel.app) to sign up and generate API keys.
678
+
679
+ ## Examples
680
+
681
+ Complete examples available in the repository:
682
+
683
+ - [Bridge Example](../examples/bridge)
684
+ - [Swap Example](../examples/swap)
685
+ - [Custom Integration](../examples/custom)
686
+
687
+ ## Support
290
688
 
291
689
  - **Documentation**: [docs.velumx.com](https://docs.velumx.com)
292
- - **Dashboard**: [dashboard.velumx.com](https://dashboard.velumx.com)
690
+ - **Dashboard**: [https://velum-x-ssum.vercel.app](https://velum-x-ssum.vercel.app)
293
691
  - **Discord**: [discord.gg/velumx](https://discord.gg/velumx)
294
692
  - **Email**: support@velumx.com
693
+ - **GitHub Issues**: [github.com/velumx/sdk/issues](https://github.com/velumx/sdk/issues)
694
+
695
+ ## Contributing
696
+
697
+ Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
698
+
699
+ ## License
295
700
 
296
- ## 📄 License
701
+ MIT License - see [LICENSE](./LICENSE) for details.
297
702
 
298
- MIT License - see [LICENSE](./LICENSE) for details
703
+ ## Changelog
299
704
 
300
- ## 🎉 Contributing
705
+ ### v2.0.0 (Current)
706
+ - ✅ Simplified architecture (removed smart wallets)
707
+ - ✅ Native Stacks sponsored transactions
708
+ - ✅ Simple paymaster contract
709
+ - ✅ Improved performance and reliability
301
710
 
302
- We welcome contributions! See [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
711
+ ### v1.0.0
712
+ - Initial release with smart wallet pattern
303
713
 
304
714
  ---
305
715
 
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VelumXClient = void 0;
4
4
  class VelumXClient {
5
5
  constructor(config) {
6
+ if (!config.apiKey) {
7
+ throw new Error("VelumX Client Error: API Key is required. Please obtain your key from the VelumX Developer Dashboard.");
8
+ }
6
9
  this.config = config;
7
10
  // Default to a hosted relayer if not provided
8
11
  this.relayerUrl = config.paymasterUrl || 'https://relayer.velumx.com/api/v1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velumx/sdk",
3
- "version": "2.0.0",
3
+ "version": "2.1.0",
4
4
  "description": "VelumX Gas Abstraction Layer SDK for dApps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -32,4 +32,4 @@
32
32
  "@types/node": "^25.3.2",
33
33
  "typescript": "^5.9.3"
34
34
  }
35
- }
35
+ }
@@ -5,6 +5,9 @@ export class VelumXClient {
5
5
  private relayerUrl: string;
6
6
 
7
7
  constructor(config: NetworkConfig) {
8
+ if (!config.apiKey) {
9
+ throw new Error("VelumX Client Error: API Key is required. Please obtain your key from the VelumX Developer Dashboard.");
10
+ }
8
11
  this.config = config;
9
12
  // Default to a hosted relayer if not provided
10
13
  this.relayerUrl = config.paymasterUrl || 'https://relayer.velumx.com/api/v1';