@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 +570 -0
- package/dist/IntentBuilder.d.ts +1 -1
- package/dist/IntentBuilder.js +1 -1
- package/dist/SimplePaymaster.d.ts +48 -0
- package/dist/SimplePaymaster.js +89 -0
- package/dist/VelumXClient.js +3 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -1
- package/package.json +3 -2
- package/src/IntentBuilder.ts +1 -1
- package/src/SimplePaymaster.ts +130 -0
- package/src/VelumXClient.ts +6 -6
- package/src/index.ts +2 -1
- package/tsconfig.json +2 -1
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
|
+
[](https://www.npmjs.com/package/@velumx/sdk)
|
|
6
|
+
[](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
|
package/dist/IntentBuilder.d.ts
CHANGED
|
@@ -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
|
|
13
|
+
* Structure matches the Smart Wallet v10 expectation
|
|
14
14
|
*/
|
|
15
15
|
private formatIntentMessage;
|
|
16
16
|
/**
|
package/dist/IntentBuilder.js
CHANGED
|
@@ -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
|
|
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;
|
package/dist/VelumXClient.js
CHANGED
|
@@ -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
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
|
|
24
|
+
// const paymaster = new SimplePaymaster({ network: 'testnet', ... });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velumx/sdk",
|
|
3
|
-
"version": "
|
|
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
|
+
}
|
package/src/IntentBuilder.ts
CHANGED
|
@@ -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
|
|
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
|
+
}
|
package/src/VelumXClient.ts
CHANGED
|
@@ -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
|
|
9
|
+
// const paymaster = new SimplePaymaster({ network: 'testnet', ... });
|