@velumx/sdk 1.4.0 → 2.0.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/README.md ADDED
@@ -0,0 +1,570 @@
1
+ # @velumx/sdk
2
+
3
+ > Gasless transaction SDK for Stacks - Pay fees in USDCx, not STX
4
+
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)
7
+
8
+ ## Overview
9
+
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
21
+
22
+ ```bash
23
+ npm install @velumx/sdk
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### 1. Initialize Client
29
+
30
+ ```typescript
31
+ import { getVelumXClient } from '@velumx/sdk';
32
+
33
+ const velumx = getVelumXClient();
34
+ ```
35
+
36
+ ### 2. Estimate Fee
37
+
38
+ ```typescript
39
+ const estimate = await velumx.estimateFee({
40
+ estimatedGas: 100000
41
+ });
42
+
43
+ console.log(`Fee: ${estimate.maxFeeUSDCx} micro-USDCx`);
44
+ // Output: Fee: 540000 micro-USDCx (0.54 USDCx)
45
+ ```
46
+
47
+ ### 3. Execute Gasless Transaction
48
+
49
+ ```typescript
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
+ }
72
+ });
73
+ ```
74
+
75
+ ## How It Works
76
+
77
+ ### Architecture
78
+
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 USDCx = (Gas Cost in STX × STX/USD Rate × 1.08) / USDC/USD Rate
117
+
118
+ Example:
119
+ - Gas: 100,000 units = 1 STX
120
+ - STX/USD: $0.50
121
+ - Markup: 8%
122
+ - Fee: 1 × $0.50 × 1.08 = $0.54 = 0.54 USDCx
123
+ ```
124
+
125
+ ## API Reference
126
+
127
+ ### VelumXClient
128
+
129
+ #### Configuration
130
+
131
+ ```typescript
132
+ interface NetworkConfig {
133
+ coreApiUrl: string; // Stacks API URL
134
+ network: 'mainnet' | 'testnet' | 'devnet';
135
+ paymasterUrl?: string; // Relayer URL (optional)
136
+ }
137
+ ```
138
+
139
+ **Default Configuration**:
140
+ ```typescript
141
+ {
142
+ coreApiUrl: 'https://api.testnet.hiro.so',
143
+ network: 'testnet',
144
+ paymasterUrl: 'https://sgal-relayer.onrender.com/api/v1'
145
+ }
146
+ ```
147
+
148
+ #### Methods
149
+
150
+ ##### estimateFee()
151
+
152
+ Get fee estimate in USDCx for a transaction.
153
+
154
+ ```typescript
155
+ estimateFee(params: {
156
+ estimatedGas: number
157
+ }): Promise<FeeEstimate>
158
+ ```
159
+
160
+ **Parameters**:
161
+ - `estimatedGas`: Estimated gas units (e.g., 100000)
162
+
163
+ **Returns**:
164
+ ```typescript
165
+ interface FeeEstimate {
166
+ maxFeeUSDCx: string; // Fee in micro-USDCx
167
+ estimatedGas: number; // Gas units
168
+ stxToUsd?: number; // Exchange rate
169
+ markup?: number; // Fee markup (0.08 = 8%)
170
+ }
171
+ ```
172
+
173
+ **Example**:
174
+ ```typescript
175
+ const estimate = await velumx.estimateFee({
176
+ estimatedGas: 100000
177
+ });
178
+
179
+ console.log(`Fee: ${estimate.maxFeeUSDCx} micro-USDCx`);
180
+ // Fee: 540000 micro-USDCx (0.54 USDCx)
181
+ ```
182
+
183
+ ##### submitRawTransaction()
184
+
185
+ Submit a signed transaction for sponsorship.
186
+
187
+ ```typescript
188
+ submitRawTransaction(txRaw: string): Promise<TransactionResult>
189
+ ```
190
+
191
+ **Parameters**:
192
+ - `txRaw`: Hex-encoded signed transaction from wallet
193
+
194
+ **Returns**:
195
+ ```typescript
196
+ interface TransactionResult {
197
+ txid: string; // Transaction ID
198
+ status: string; // Status (pending/success/failed)
199
+ }
200
+ ```
201
+
202
+ **Example**:
203
+ ```typescript
204
+ const result = await velumx.submitRawTransaction(data.txRaw);
205
+ console.log(`Transaction ID: ${result.txid}`);
206
+ ```
207
+
208
+ ##### sponsorTransaction()
209
+
210
+ High-level helper to make any transaction gasless.
211
+
212
+ ```typescript
213
+ sponsorTransaction(params: {
214
+ transaction: any;
215
+ network: 'mainnet' | 'testnet';
216
+ }): Promise<any>
217
+ ```
218
+
219
+ **Parameters**:
220
+ - `transaction`: Unsigned Stacks transaction
221
+ - `network`: Target network
222
+
223
+ **Returns**: Transaction with `sponsored: true` flag
224
+
225
+ **Example**:
226
+ ```typescript
227
+ import { makeContractCall } from '@stacks/transactions';
228
+
229
+ const unsignedTx = await makeContractCall({...});
230
+
231
+ const sponsored = await velumx.sponsorTransaction({
232
+ transaction: unsignedTx,
233
+ network: 'testnet'
234
+ });
235
+
236
+ // User signs and broadcasts
237
+ const result = await openContractCall(sponsored);
238
+ ```
239
+
240
+ ## Use Cases
241
+
242
+ ### 1. Gasless Bridge
243
+
244
+ Bridge USDC from Ethereum to Stacks without needing STX.
245
+
246
+ ```typescript
247
+ import { getVelumXClient } from '@velumx/sdk';
248
+ import { openContractCall } from '@stacks/connect';
249
+ import { Cl } from '@stacks/transactions';
250
+ import { parseUnits } from 'viem';
251
+
252
+ async function gaslessBridge(amount: string, recipient: string) {
253
+ const velumx = getVelumXClient();
254
+
255
+ // 1. Estimate fee
256
+ const estimate = await velumx.estimateFee({
257
+ estimatedGas: 100000
258
+ });
259
+
260
+ // 2. Encode Ethereum address
261
+ const recipientBytes = encodeEthereumAddress(recipient);
262
+
263
+ // 3. Execute gasless bridge
264
+ const result = await openContractCall({
265
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
266
+ contractName: 'simple-paymaster-v1',
267
+ functionName: 'bridge-gasless',
268
+ functionArgs: [
269
+ Cl.uint(parseUnits(amount, 6)),
270
+ Cl.buffer(recipientBytes),
271
+ Cl.uint(estimate.maxFeeUSDCx),
272
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
273
+ Cl.principal('ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx')
274
+ ],
275
+ sponsored: true,
276
+ network: 'testnet',
277
+ onFinish: async (data) => {
278
+ const tx = await velumx.submitRawTransaction(data.txRaw);
279
+ console.log(`Bridge transaction: ${tx.txid}`);
280
+ }
281
+ });
282
+ }
283
+
284
+ // Helper function
285
+ function encodeEthereumAddress(address: string): Uint8Array {
286
+ const hex = address.startsWith('0x') ? address.slice(2) : address;
287
+ const paddedHex = hex.padStart(64, '0');
288
+ const bytes = new Uint8Array(32);
289
+ for (let i = 0; i < 32; i++) {
290
+ bytes[i] = parseInt(paddedHex.substring(i * 2, i * 2 + 2), 16);
291
+ }
292
+ return bytes;
293
+ }
294
+ ```
295
+
296
+ ### 2. Gasless Swap
297
+
298
+ Swap tokens without holding STX.
299
+
300
+ ```typescript
301
+ async function gaslessSwap(
302
+ tokenIn: string,
303
+ tokenOut: string,
304
+ amountIn: string,
305
+ minOut: string
306
+ ) {
307
+ const velumx = getVelumXClient();
308
+
309
+ // 1. Estimate fee
310
+ const estimate = await velumx.estimateFee({
311
+ estimatedGas: 150000
312
+ });
313
+
314
+ // 2. Execute gasless swap
315
+ const result = await openContractCall({
316
+ contractAddress: 'STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P',
317
+ contractName: 'simple-paymaster-v1',
318
+ functionName: 'swap-gasless',
319
+ functionArgs: [
320
+ Cl.principal(tokenIn),
321
+ Cl.principal(tokenOut),
322
+ Cl.uint(parseUnits(amountIn, 6)),
323
+ Cl.uint(parseUnits(minOut, 6)),
324
+ Cl.uint(estimate.maxFeeUSDCx),
325
+ Cl.principal('STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P'),
326
+ Cl.principal('ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx')
327
+ ],
328
+ sponsored: true,
329
+ network: 'testnet',
330
+ onFinish: async (data) => {
331
+ const tx = await velumx.submitRawTransaction(data.txRaw);
332
+ console.log(`Swap transaction: ${tx.txid}`);
333
+ }
334
+ });
335
+ }
336
+ ```
337
+
338
+ ### 3. Custom Gasless Transaction
339
+
340
+ Make any contract call gasless.
341
+
342
+ ```typescript
343
+ async function customGaslessTransaction() {
344
+ const velumx = getVelumXClient();
345
+
346
+ // 1. Estimate fee
347
+ const estimate = await velumx.estimateFee({
348
+ estimatedGas: 120000
349
+ });
350
+
351
+ // 2. Your custom contract call
352
+ const result = await openContractCall({
353
+ contractAddress: 'YOUR_CONTRACT_ADDRESS',
354
+ contractName: 'your-contract',
355
+ functionName: 'your-function',
356
+ functionArgs: [
357
+ // Your function args
358
+ Cl.uint(estimate.maxFeeUSDCx), // Include fee
359
+ // More args...
360
+ ],
361
+ sponsored: true, // Enable gasless
362
+ network: 'testnet',
363
+ onFinish: async (data) => {
364
+ const tx = await velumx.submitRawTransaction(data.txRaw);
365
+ console.log(`Transaction: ${tx.txid}`);
366
+ }
367
+ });
368
+ }
369
+ ```
370
+
371
+ ## Smart Contract Integration
372
+
373
+ To make your contract gasless-compatible, accept a fee parameter and transfer it to the relayer:
374
+
375
+ ```clarity
376
+ (define-public (your-gasless-function
377
+ (amount uint)
378
+ (fee-usdcx uint)
379
+ (relayer principal)
380
+ (fee-token <sip-010-trait>))
381
+ (begin
382
+ ;; 1. Transfer fee from user to relayer
383
+ (try! (contract-call? fee-token transfer
384
+ fee-usdcx tx-sender relayer none))
385
+
386
+ ;; 2. Your contract logic
387
+ (try! (your-logic amount))
388
+
389
+ (ok true)
390
+ )
391
+ )
392
+ ```
393
+
394
+ ## Configuration
395
+
396
+ ### Environment Variables
397
+
398
+ ```bash
399
+ # Frontend (.env.local)
400
+ NEXT_PUBLIC_STACKS_NETWORK=testnet
401
+ NEXT_PUBLIC_STACKS_API_URL=https://api.testnet.hiro.so
402
+ NEXT_PUBLIC_VELUMX_RELAYER_URL=https://sgal-relayer.onrender.com/api/v1
403
+
404
+ # Contracts
405
+ NEXT_PUBLIC_STACKS_PAYMASTER_ADDRESS=STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P.simple-paymaster-v1
406
+ NEXT_PUBLIC_STACKS_USDCX_ADDRESS=ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx
407
+ ```
408
+
409
+ ### Network Configuration
410
+
411
+ ```typescript
412
+ // Testnet (default)
413
+ const velumx = getVelumXClient();
414
+
415
+ // Mainnet
416
+ const velumx = new VelumXClient({
417
+ coreApiUrl: 'https://api.mainnet.hiro.so',
418
+ network: 'mainnet',
419
+ paymasterUrl: 'https://mainnet-relayer.velumx.com/api/v1'
420
+ });
421
+ ```
422
+
423
+ ## Error Handling
424
+
425
+ ```typescript
426
+ try {
427
+ const estimate = await velumx.estimateFee({
428
+ estimatedGas: 100000
429
+ });
430
+
431
+ const result = await openContractCall({
432
+ // ... transaction params
433
+ onFinish: async (data) => {
434
+ try {
435
+ const tx = await velumx.submitRawTransaction(data.txRaw);
436
+ console.log(`Success: ${tx.txid}`);
437
+ } catch (error) {
438
+ if (error.message.includes('insufficient balance')) {
439
+ console.error('User needs more USDCx for fees');
440
+ } else if (error.message.includes('invalid signature')) {
441
+ console.error('Signature verification failed');
442
+ } else {
443
+ console.error('Transaction failed:', error);
444
+ }
445
+ }
446
+ },
447
+ onCancel: () => {
448
+ console.log('User cancelled transaction');
449
+ }
450
+ });
451
+ } catch (error) {
452
+ console.error('Failed to estimate fee:', error);
453
+ }
454
+ ```
455
+
456
+ ## Testing
457
+
458
+ ### Unit Tests
459
+
460
+ ```bash
461
+ npm test
462
+ ```
463
+
464
+ ### Integration Tests
465
+
466
+ ```bash
467
+ npm run test:integration
468
+ ```
469
+
470
+ ### Example Test
471
+
472
+ ```typescript
473
+ import { getVelumXClient } from '@velumx/sdk';
474
+
475
+ describe('VelumX SDK', () => {
476
+ it('should estimate fee correctly', async () => {
477
+ const velumx = getVelumXClient();
478
+
479
+ const estimate = await velumx.estimateFee({
480
+ estimatedGas: 100000
481
+ });
482
+
483
+ expect(estimate.maxFeeUSDCx).toBeDefined();
484
+ expect(Number(estimate.maxFeeUSDCx)).toBeGreaterThan(0);
485
+ });
486
+ });
487
+ ```
488
+
489
+ ## Deployed Contracts
490
+
491
+ ### Testnet
492
+
493
+ **Simple Paymaster**
494
+ ```
495
+ Address: STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P.simple-paymaster-v1
496
+ Network: Stacks Testnet
497
+ Explorer: https://explorer.hiro.so/txid/0x90c134205b04599405e3cccae6c86ed496ae2d81ef0392970e2c9a7acd3b2138?chain=testnet
498
+ ```
499
+
500
+ **USDCx Token**
501
+ ```
502
+ Address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx
503
+ Standard: SIP-010
504
+ Decimals: 6
505
+ ```
506
+
507
+ **Relayer**
508
+ ```
509
+ URL: https://sgal-relayer.onrender.com/api/v1
510
+ Status: https://sgal-relayer.onrender.com/api/v1/health
511
+ ```
512
+
513
+ ## FAQ
514
+
515
+ ### Q: Do users need STX?
516
+ **A:** No! Users only need USDCx. The relayer pays STX fees.
517
+
518
+ ### Q: How much does it cost?
519
+ **A:** Fees are calculated in real-time based on STX/USD rates with an 8% markup. Typically 0.001-0.01 USDCx per transaction.
520
+
521
+ ### Q: Is it secure?
522
+ **A:** Yes! Uses Stacks' native sponsored transaction feature. No smart wallet complexity.
523
+
524
+ ### Q: What wallets are supported?
525
+ **A:** Any Stacks wallet (Xverse, Leather, Hiro) that supports sponsored transactions.
526
+
527
+ ### Q: Can I use this in production?
528
+ **A:** Currently on testnet. Mainnet launch pending security audit.
529
+
530
+ ### Q: How do I get an API key?
531
+ **A:** Visit [https://velum-x-ssum.vercel.app](https://velum-x-ssum.vercel.app) to sign up and generate API keys.
532
+
533
+ ## Examples
534
+
535
+ Complete examples available in the repository:
536
+
537
+ - [Bridge Example](../examples/bridge)
538
+ - [Swap Example](../examples/swap)
539
+ - [Custom Integration](../examples/custom)
540
+
541
+ ## Support
542
+
543
+ - **Documentation**: [docs.velumx.com](https://docs.velumx.com)
544
+ - **Dashboard**: [https://velum-x-ssum.vercel.app](https://velum-x-ssum.vercel.app)
545
+ - **Discord**: [discord.gg/velumx](https://discord.gg/velumx)
546
+ - **Email**: support@velumx.com
547
+ - **GitHub Issues**: [github.com/velumx/sdk/issues](https://github.com/velumx/sdk/issues)
548
+
549
+ ## Contributing
550
+
551
+ Contributions are welcome! Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for guidelines.
552
+
553
+ ## License
554
+
555
+ MIT License - see [LICENSE](./LICENSE) for details.
556
+
557
+ ## Changelog
558
+
559
+ ### v2.0.0 (Current)
560
+ - ✅ Simplified architecture (removed smart wallets)
561
+ - ✅ Native Stacks sponsored transactions
562
+ - ✅ Simple paymaster contract
563
+ - ✅ Improved performance and reliability
564
+
565
+ ### v1.0.0
566
+ - Initial release with smart wallet pattern
567
+
568
+ ---
569
+
570
+ Built with ❤️ by the VelumX team
@@ -10,7 +10,7 @@ export declare class IntentBuilder {
10
10
  private getDomain;
11
11
  /**
12
12
  * Formats the intent into a Clarity Tuple for signing
13
- * Structure matches the Smart Wallet v7 expectation
13
+ * Structure matches the Smart Wallet v10 expectation
14
14
  */
15
15
  private formatIntentMessage;
16
16
  /**
@@ -20,7 +20,7 @@ class IntentBuilder {
20
20
  }
21
21
  /**
22
22
  * Formats the intent into a Clarity Tuple for signing
23
- * Structure matches the Smart Wallet v7 expectation
23
+ * Structure matches the Smart Wallet v10 expectation
24
24
  */
25
25
  formatIntentMessage(intent) {
26
26
  return (0, transactions_1.tupleCV)({
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Simple Paymaster SDK
3
+ * Simplified gasless transactions using Stacks-native sponsored transactions
4
+ */
5
+ export interface SimplePaymasterConfig {
6
+ network: 'mainnet' | 'testnet';
7
+ paymasterContract: string;
8
+ relayerAddress: string;
9
+ usdcxContract: string;
10
+ }
11
+ export interface BridgeParams {
12
+ amount: string;
13
+ recipient: string;
14
+ feeUsdcx: string;
15
+ onFinish?: (data: any) => void;
16
+ onCancel?: () => void;
17
+ }
18
+ export interface SwapParams {
19
+ tokenIn: string;
20
+ tokenOut: string;
21
+ amountIn: string;
22
+ minOut: string;
23
+ feeUsdcx: string;
24
+ onFinish?: (data: any) => void;
25
+ onCancel?: () => void;
26
+ }
27
+ export declare class SimplePaymaster {
28
+ private config;
29
+ constructor(config: SimplePaymasterConfig);
30
+ /**
31
+ * Execute gasless bridge withdrawal (Stacks → Ethereum)
32
+ */
33
+ bridgeGasless(params: BridgeParams): Promise<void>;
34
+ /**
35
+ * Execute gasless swap
36
+ */
37
+ swapGasless(params: SwapParams): Promise<void>;
38
+ /**
39
+ * Estimate fee for gasless transaction
40
+ */
41
+ estimateFee(estimatedGas?: number): Promise<{
42
+ feeUsdcx: string;
43
+ }>;
44
+ /**
45
+ * Encode Ethereum address to bytes32 for Stacks contract
46
+ */
47
+ private encodeEthereumAddress;
48
+ }
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * Simple Paymaster SDK
4
+ * Simplified gasless transactions using Stacks-native sponsored transactions
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SimplePaymaster = void 0;
8
+ const connect_1 = require("@stacks/connect");
9
+ const transactions_1 = require("@stacks/transactions");
10
+ class SimplePaymaster {
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Execute gasless bridge withdrawal (Stacks → Ethereum)
16
+ */
17
+ async bridgeGasless(params) {
18
+ const [contractAddress, contractName] = this.config.paymasterContract.split('.');
19
+ // Encode Ethereum address to bytes32
20
+ const recipientBytes = this.encodeEthereumAddress(params.recipient);
21
+ const functionArgs = [
22
+ (0, transactions_1.uintCV)(params.amount),
23
+ (0, transactions_1.bufferCV)(recipientBytes),
24
+ (0, transactions_1.uintCV)(params.feeUsdcx),
25
+ (0, transactions_1.principalCV)(this.config.relayerAddress),
26
+ (0, transactions_1.contractPrincipalCV)(this.config.usdcxContract.split('.')[0], this.config.usdcxContract.split('.')[1])
27
+ ];
28
+ await (0, connect_1.openContractCall)({
29
+ contractAddress,
30
+ contractName,
31
+ functionName: 'bridge-gasless',
32
+ functionArgs,
33
+ network: this.config.network,
34
+ sponsored: true,
35
+ postConditionMode: transactions_1.PostConditionMode.Allow,
36
+ onFinish: params.onFinish || (() => { }),
37
+ onCancel: params.onCancel || (() => { }),
38
+ });
39
+ }
40
+ /**
41
+ * Execute gasless swap
42
+ */
43
+ async swapGasless(params) {
44
+ const [contractAddress, contractName] = this.config.paymasterContract.split('.');
45
+ const functionArgs = [
46
+ (0, transactions_1.principalCV)(params.tokenIn),
47
+ (0, transactions_1.principalCV)(params.tokenOut),
48
+ (0, transactions_1.uintCV)(params.amountIn),
49
+ (0, transactions_1.uintCV)(params.minOut),
50
+ (0, transactions_1.uintCV)(params.feeUsdcx),
51
+ (0, transactions_1.principalCV)(this.config.relayerAddress),
52
+ (0, transactions_1.contractPrincipalCV)(this.config.usdcxContract.split('.')[0], this.config.usdcxContract.split('.')[1])
53
+ ];
54
+ await (0, connect_1.openContractCall)({
55
+ contractAddress,
56
+ contractName,
57
+ functionName: 'swap-gasless',
58
+ functionArgs,
59
+ network: this.config.network,
60
+ sponsored: true,
61
+ postConditionMode: transactions_1.PostConditionMode.Allow,
62
+ onFinish: params.onFinish || (() => { }),
63
+ onCancel: params.onCancel || (() => { }),
64
+ });
65
+ }
66
+ /**
67
+ * Estimate fee for gasless transaction
68
+ */
69
+ async estimateFee(estimatedGas = 100000) {
70
+ // Simple fee calculation: ~0.25 USDCx per transaction
71
+ // In production, this would call the relayer API
72
+ return {
73
+ feeUsdcx: '250000' // 0.25 USDCx
74
+ };
75
+ }
76
+ /**
77
+ * Encode Ethereum address to bytes32 for Stacks contract
78
+ */
79
+ encodeEthereumAddress(address) {
80
+ const hex = address.startsWith('0x') ? address.slice(2) : address;
81
+ const paddedHex = hex.padStart(64, '0');
82
+ const bytes = new Uint8Array(32);
83
+ for (let i = 0; i < 32; i++) {
84
+ bytes[i] = parseInt(paddedHex.substring(i * 2, i * 2 + 2), 16);
85
+ }
86
+ return bytes;
87
+ }
88
+ }
89
+ exports.SimplePaymaster = SimplePaymaster;
@@ -22,7 +22,7 @@ class VelumXClient {
22
22
  body: JSON.stringify({ intent })
23
23
  });
24
24
  if (!response.ok) {
25
- const errData = await response.json().catch(() => ({}));
25
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' }));
26
26
  throw new Error(`Fee estimation failed: ${errData.error || errData.message || response.statusText}`);
27
27
  }
28
28
  return await response.json();
@@ -47,7 +47,7 @@ class VelumXClient {
47
47
  body: JSON.stringify({ intent: signedIntent })
48
48
  });
49
49
  if (!response.ok) {
50
- const errData = await response.json().catch(() => ({}));
50
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' }));
51
51
  throw new Error(`Intent sponsorship failed: ${errData.error || errData.message || response.statusText}`);
52
52
  }
53
53
  return await response.json();
@@ -72,7 +72,7 @@ class VelumXClient {
72
72
  body: JSON.stringify({ txHex })
73
73
  });
74
74
  if (!response.ok) {
75
- const errData = await response.json().catch(() => ({}));
75
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' }));
76
76
  throw new Error(`Transaction broadcast failed: ${errData.error || errData.message || response.statusText}`);
77
77
  }
78
78
  return await response.json();
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './types';
2
2
  export * from './IntentBuilder';
3
3
  export * from './VelumXClient';
4
+ export * from './SimplePaymaster';
package/dist/index.js CHANGED
@@ -17,7 +17,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./types"), exports);
18
18
  __exportStar(require("./IntentBuilder"), exports);
19
19
  __exportStar(require("./VelumXClient"), exports);
20
+ __exportStar(require("./SimplePaymaster"), exports);
20
21
  // Core entrypoint for the @velumx/sdk
21
22
  // Example Usage:
22
23
  // const client = new VelumXClient({ network: 'testnet' });
23
- // const intentBuilder = new IntentBuilder();
24
+ // const paymaster = new SimplePaymaster({ network: 'testnet', ... });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@velumx/sdk",
3
- "version": "1.4.0",
3
+ "version": "2.0.1",
4
4
  "description": "VelumX Gas Abstraction Layer SDK for dApps",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,6 +24,7 @@
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
26
  "@stacks/common": "^7.3.1",
27
+ "@stacks/connect": "^7.10.0",
27
28
  "@stacks/network": "^7.3.1",
28
29
  "@stacks/transactions": "^7.3.1"
29
30
  },
@@ -31,4 +32,4 @@
31
32
  "@types/node": "^25.3.2",
32
33
  "typescript": "^5.9.3"
33
34
  }
34
- }
35
+ }
@@ -33,7 +33,7 @@ export class IntentBuilder {
33
33
 
34
34
  /**
35
35
  * Formats the intent into a Clarity Tuple for signing
36
- * Structure matches the Smart Wallet v7 expectation
36
+ * Structure matches the Smart Wallet v10 expectation
37
37
  */
38
38
  private formatIntentMessage(intent: WalletIntent) {
39
39
  return tupleCV({
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Simple Paymaster SDK
3
+ * Simplified gasless transactions using Stacks-native sponsored transactions
4
+ */
5
+
6
+ import { openContractCall } from '@stacks/connect';
7
+ import {
8
+ uintCV,
9
+ bufferCV,
10
+ principalCV,
11
+ contractPrincipalCV,
12
+ ClarityValue,
13
+ PostConditionMode
14
+ } from '@stacks/transactions';
15
+
16
+ export interface SimplePaymasterConfig {
17
+ network: 'mainnet' | 'testnet';
18
+ paymasterContract: string; // e.g., 'DEPLOYER.simple-paymaster-v1'
19
+ relayerAddress: string; // e.g., 'STKY...25E3P'
20
+ usdcxContract: string; // e.g., 'ST1P...PGZGM.usdcx'
21
+ }
22
+
23
+ export interface BridgeParams {
24
+ amount: string; // Amount in micro units (e.g., "10000000" for 10 USDCx)
25
+ recipient: string; // Ethereum address (0x...)
26
+ feeUsdcx: string; // Fee in micro units (e.g., "250000" for 0.25 USDCx)
27
+ onFinish?: (data: any) => void;
28
+ onCancel?: () => void;
29
+ }
30
+
31
+ export interface SwapParams {
32
+ tokenIn: string; // Contract principal
33
+ tokenOut: string; // Contract principal
34
+ amountIn: string; // Amount in micro units
35
+ minOut: string; // Minimum output in micro units
36
+ feeUsdcx: string; // Fee in micro units
37
+ onFinish?: (data: any) => void;
38
+ onCancel?: () => void;
39
+ }
40
+
41
+ export class SimplePaymaster {
42
+ private config: SimplePaymasterConfig;
43
+
44
+ constructor(config: SimplePaymasterConfig) {
45
+ this.config = config;
46
+ }
47
+
48
+ /**
49
+ * Execute gasless bridge withdrawal (Stacks → Ethereum)
50
+ */
51
+ async bridgeGasless(params: BridgeParams): Promise<void> {
52
+ const [contractAddress, contractName] = this.config.paymasterContract.split('.');
53
+
54
+ // Encode Ethereum address to bytes32
55
+ const recipientBytes = this.encodeEthereumAddress(params.recipient);
56
+
57
+ const functionArgs: ClarityValue[] = [
58
+ uintCV(params.amount),
59
+ bufferCV(recipientBytes),
60
+ uintCV(params.feeUsdcx),
61
+ principalCV(this.config.relayerAddress),
62
+ contractPrincipalCV(this.config.usdcxContract.split('.')[0], this.config.usdcxContract.split('.')[1])
63
+ ];
64
+
65
+ await openContractCall({
66
+ contractAddress,
67
+ contractName,
68
+ functionName: 'bridge-gasless',
69
+ functionArgs,
70
+ network: this.config.network,
71
+ sponsored: true,
72
+ postConditionMode: PostConditionMode.Allow,
73
+ onFinish: params.onFinish || (() => {}),
74
+ onCancel: params.onCancel || (() => {}),
75
+ });
76
+ }
77
+
78
+ /**
79
+ * Execute gasless swap
80
+ */
81
+ async swapGasless(params: SwapParams): Promise<void> {
82
+ const [contractAddress, contractName] = this.config.paymasterContract.split('.');
83
+
84
+ const functionArgs: ClarityValue[] = [
85
+ principalCV(params.tokenIn),
86
+ principalCV(params.tokenOut),
87
+ uintCV(params.amountIn),
88
+ uintCV(params.minOut),
89
+ uintCV(params.feeUsdcx),
90
+ principalCV(this.config.relayerAddress),
91
+ contractPrincipalCV(this.config.usdcxContract.split('.')[0], this.config.usdcxContract.split('.')[1])
92
+ ];
93
+
94
+ await openContractCall({
95
+ contractAddress,
96
+ contractName,
97
+ functionName: 'swap-gasless',
98
+ functionArgs,
99
+ network: this.config.network,
100
+ sponsored: true,
101
+ postConditionMode: PostConditionMode.Allow,
102
+ onFinish: params.onFinish || (() => {}),
103
+ onCancel: params.onCancel || (() => {}),
104
+ });
105
+ }
106
+
107
+ /**
108
+ * Estimate fee for gasless transaction
109
+ */
110
+ async estimateFee(estimatedGas: number = 100000): Promise<{ feeUsdcx: string }> {
111
+ // Simple fee calculation: ~0.25 USDCx per transaction
112
+ // In production, this would call the relayer API
113
+ return {
114
+ feeUsdcx: '250000' // 0.25 USDCx
115
+ };
116
+ }
117
+
118
+ /**
119
+ * Encode Ethereum address to bytes32 for Stacks contract
120
+ */
121
+ private encodeEthereumAddress(address: string): Uint8Array {
122
+ const hex = address.startsWith('0x') ? address.slice(2) : address;
123
+ const paddedHex = hex.padStart(64, '0');
124
+ const bytes = new Uint8Array(32);
125
+ for (let i = 0; i < 32; i++) {
126
+ bytes[i] = parseInt(paddedHex.substring(i * 2, i * 2 + 2), 16);
127
+ }
128
+ return bytes;
129
+ }
130
+ }
@@ -27,11 +27,11 @@ export class VelumXClient {
27
27
  });
28
28
 
29
29
  if (!response.ok) {
30
- const errData = await response.json().catch(() => ({}));
30
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' })) as any;
31
31
  throw new Error(`Fee estimation failed: ${errData.error || errData.message || response.statusText}`);
32
32
  }
33
33
 
34
- return await response.json();
34
+ return await response.json() as { maxFeeUSDCx: string, estimatedGas: number };
35
35
  } catch (error) {
36
36
  console.error("VelumX Client Error (estimateFee):", error);
37
37
  throw error;
@@ -55,11 +55,11 @@ export class VelumXClient {
55
55
  });
56
56
 
57
57
  if (!response.ok) {
58
- const errData = await response.json().catch(() => ({}));
58
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' })) as any;
59
59
  throw new Error(`Intent sponsorship failed: ${errData.error || errData.message || response.statusText}`);
60
60
  }
61
61
 
62
- return await response.json();
62
+ return await response.json() as { txid: string, status: string };
63
63
  } catch (error) {
64
64
  console.error("VelumX Client Error (submitIntent):", error);
65
65
  throw error;
@@ -83,11 +83,11 @@ export class VelumXClient {
83
83
  });
84
84
 
85
85
  if (!response.ok) {
86
- const errData = await response.json().catch(() => ({}));
86
+ const errData = await response.json().catch(() => ({ error: 'Unknown error' })) as any;
87
87
  throw new Error(`Transaction broadcast failed: ${errData.error || errData.message || response.statusText}`);
88
88
  }
89
89
 
90
- return await response.json();
90
+ return await response.json() as { txid: string, status: string };
91
91
  } catch (error) {
92
92
  console.error("VelumX Client Error (submitRawTransaction):", error);
93
93
  throw error;
package/src/index.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  export * from './types';
2
2
  export * from './IntentBuilder';
3
3
  export * from './VelumXClient';
4
+ export * from './SimplePaymaster';
4
5
 
5
6
  // Core entrypoint for the @velumx/sdk
6
7
  // Example Usage:
7
8
  // const client = new VelumXClient({ network: 'testnet' });
8
- // const intentBuilder = new IntentBuilder();
9
+ // const paymaster = new SimplePaymaster({ network: 'testnet', ... });
package/tsconfig.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "target": "es2020",
3
+ "target": "es2021",
4
+ "lib": ["es2021", "dom"],
4
5
  "module": "commonjs",
5
6
  "declaration": true,
6
7
  "outDir": "./dist",