@velumx/sdk 2.0.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 +453 -189
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,41 +1,39 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @velumx/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Gasless transaction SDK for Stacks - Pay fees in USDCx, not STX
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@velumx/sdk)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
|
-
|
|
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
|
-
|
|
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
|
-
##
|
|
20
|
-
|
|
21
|
-
### 1. Get API Key
|
|
26
|
+
## Quick Start
|
|
22
27
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
### 2. Initialize Client
|
|
28
|
+
### 1. Initialize Client
|
|
26
29
|
|
|
27
30
|
```typescript
|
|
28
|
-
import {
|
|
31
|
+
import { getVelumXClient } from '@velumx/sdk';
|
|
29
32
|
|
|
30
|
-
const velumx =
|
|
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
|
-
###
|
|
36
|
+
### 2. Estimate Fee
|
|
39
37
|
|
|
40
38
|
```typescript
|
|
41
39
|
const estimate = await velumx.estimateFee({
|
|
@@ -43,263 +41,529 @@ 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
|
-
###
|
|
47
|
+
### 3. Execute Gasless Transaction
|
|
49
48
|
|
|
50
49
|
```typescript
|
|
51
|
-
import {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
|
75
76
|
|
|
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
|
|
77
123
|
```
|
|
78
124
|
|
|
79
|
-
##
|
|
125
|
+
## API Reference
|
|
80
126
|
|
|
81
127
|
### VelumXClient
|
|
82
128
|
|
|
83
|
-
####
|
|
129
|
+
#### Configuration
|
|
84
130
|
|
|
85
131
|
```typescript
|
|
86
|
-
|
|
132
|
+
interface NetworkConfig {
|
|
133
|
+
coreApiUrl: string; // Stacks API URL
|
|
134
|
+
network: 'mainnet' | 'testnet' | 'devnet';
|
|
135
|
+
paymasterUrl?: string; // Relayer URL (optional)
|
|
136
|
+
}
|
|
87
137
|
```
|
|
88
138
|
|
|
89
|
-
**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
+
```
|
|
94
147
|
|
|
95
148
|
#### Methods
|
|
96
149
|
|
|
97
150
|
##### estimateFee()
|
|
98
151
|
|
|
152
|
+
Get fee estimate in USDCx for a transaction.
|
|
153
|
+
|
|
99
154
|
```typescript
|
|
100
|
-
estimateFee(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
}>
|
|
155
|
+
estimateFee(params: {
|
|
156
|
+
estimatedGas: number
|
|
157
|
+
}): Promise<FeeEstimate>
|
|
104
158
|
```
|
|
105
159
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
##### submitIntent()
|
|
160
|
+
**Parameters**:
|
|
161
|
+
- `estimatedGas`: Estimated gas units (e.g., 100000)
|
|
109
162
|
|
|
163
|
+
**Returns**:
|
|
110
164
|
```typescript
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
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
|
+
}
|
|
115
171
|
```
|
|
116
172
|
|
|
117
|
-
|
|
173
|
+
**Example**:
|
|
174
|
+
```typescript
|
|
175
|
+
const estimate = await velumx.estimateFee({
|
|
176
|
+
estimatedGas: 100000
|
|
177
|
+
});
|
|
118
178
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
- `maxFeeUSDCx`: Maximum fee in micro-USDCx
|
|
123
|
-
- `nonce`: Smart Wallet nonce
|
|
124
|
-
- `signature`: SIP-018 signature
|
|
179
|
+
console.log(`Fee: ${estimate.maxFeeUSDCx} micro-USDCx`);
|
|
180
|
+
// Fee: 540000 micro-USDCx (0.54 USDCx)
|
|
181
|
+
```
|
|
125
182
|
|
|
126
183
|
##### submitRawTransaction()
|
|
127
184
|
|
|
185
|
+
Submit a signed transaction for sponsorship.
|
|
186
|
+
|
|
128
187
|
```typescript
|
|
129
|
-
submitRawTransaction(
|
|
130
|
-
txid: string;
|
|
131
|
-
status: string;
|
|
132
|
-
}>
|
|
188
|
+
submitRawTransaction(txRaw: string): Promise<TransactionResult>
|
|
133
189
|
```
|
|
134
190
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
## π― Use Cases
|
|
191
|
+
**Parameters**:
|
|
192
|
+
- `txRaw`: Hex-encoded signed transaction from wallet
|
|
138
193
|
|
|
139
|
-
|
|
194
|
+
**Returns**:
|
|
195
|
+
```typescript
|
|
196
|
+
interface TransactionResult {
|
|
197
|
+
txid: string; // Transaction ID
|
|
198
|
+
status: string; // Status (pending/success/failed)
|
|
199
|
+
}
|
|
200
|
+
```
|
|
140
201
|
|
|
202
|
+
**Example**:
|
|
141
203
|
```typescript
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
amount: uintCV(5000000), // 5 USDCx
|
|
146
|
-
fee: uintCV(250000), // 0.25 USDCx fee
|
|
147
|
-
recipient: bufferCV(ethAddressBytes)
|
|
148
|
-
});
|
|
204
|
+
const result = await velumx.submitRawTransaction(data.txRaw);
|
|
205
|
+
console.log(`Transaction ID: ${result.txid}`);
|
|
206
|
+
```
|
|
149
207
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
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>
|
|
157
217
|
```
|
|
158
218
|
|
|
159
|
-
|
|
219
|
+
**Parameters**:
|
|
220
|
+
- `transaction`: Unsigned Stacks transaction
|
|
221
|
+
- `network`: Target network
|
|
222
|
+
|
|
223
|
+
**Returns**: Transaction with `sponsored: true` flag
|
|
160
224
|
|
|
225
|
+
**Example**:
|
|
161
226
|
```typescript
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
tokenOut: principalCV('ST...TOKEN-B'),
|
|
166
|
-
amountIn: uintCV(1000000),
|
|
167
|
-
minOut: uintCV(950000),
|
|
168
|
-
fee: uintCV(200000)
|
|
169
|
-
});
|
|
227
|
+
import { makeContractCall } from '@stacks/transactions';
|
|
228
|
+
|
|
229
|
+
const unsignedTx = await makeContractCall({...});
|
|
170
230
|
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
maxFeeUSDCx: '200000',
|
|
175
|
-
nonce: 1,
|
|
176
|
-
signature: userSignature
|
|
231
|
+
const sponsored = await velumx.sponsorTransaction({
|
|
232
|
+
transaction: unsignedTx,
|
|
233
|
+
network: 'testnet'
|
|
177
234
|
});
|
|
235
|
+
|
|
236
|
+
// User signs and broadcasts
|
|
237
|
+
const result = await openContractCall(sponsored);
|
|
178
238
|
```
|
|
179
239
|
|
|
180
|
-
|
|
240
|
+
## Use Cases
|
|
241
|
+
|
|
242
|
+
### 1. Gasless Bridge
|
|
243
|
+
|
|
244
|
+
Bridge USDC from Ethereum to Stacks without needing STX.
|
|
181
245
|
|
|
182
246
|
```typescript
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
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
|
+
}
|
|
189
283
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
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
|
+
}
|
|
197
294
|
```
|
|
198
295
|
|
|
199
|
-
|
|
296
|
+
### 2. Gasless Swap
|
|
200
297
|
|
|
201
|
-
|
|
298
|
+
Swap tokens without holding STX.
|
|
202
299
|
|
|
203
300
|
```typescript
|
|
204
|
-
|
|
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
|
+
```
|
|
205
337
|
|
|
206
|
-
|
|
338
|
+
### 3. Custom Gasless Transaction
|
|
207
339
|
|
|
208
|
-
|
|
209
|
-
const hasWallet = await manager.hasSmartWallet(userAddress);
|
|
340
|
+
Make any contract call gasless.
|
|
210
341
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
|
|
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
|
+
});
|
|
215
368
|
}
|
|
216
369
|
```
|
|
217
370
|
|
|
218
|
-
##
|
|
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
|
+
```
|
|
219
393
|
|
|
220
|
-
|
|
221
|
-
- **Markup**: 8% (configurable by relayer)
|
|
222
|
-
- **Example**: 0.005 STX gas = ~$0.0025 = 0.0025 USDCx + 8% = 0.0027 USDCx
|
|
394
|
+
## Configuration
|
|
223
395
|
|
|
224
|
-
|
|
396
|
+
### Environment Variables
|
|
225
397
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
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
|
+
```
|
|
230
408
|
|
|
231
|
-
###
|
|
232
|
-
- Relayer: `https://mainnet-relayer.velumx.com/api/v1`
|
|
233
|
-
- Stacks API: `https://api.mainnet.hiro.so`
|
|
234
|
-
- Requires API key from dashboard
|
|
409
|
+
### Network Configuration
|
|
235
410
|
|
|
236
|
-
|
|
411
|
+
```typescript
|
|
412
|
+
// Testnet (default)
|
|
413
|
+
const velumx = getVelumXClient();
|
|
237
414
|
|
|
238
|
-
|
|
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
|
|
239
424
|
|
|
240
425
|
```typescript
|
|
241
|
-
|
|
242
|
-
const
|
|
243
|
-
|
|
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
|
|
244
465
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
const gasInUsd = gasInStx * rates.stxToUsd;
|
|
248
|
-
const feeInUsdcx = gasInUsd * 1.08; // 8% markup
|
|
466
|
+
```bash
|
|
467
|
+
npm run test:integration
|
|
249
468
|
```
|
|
250
469
|
|
|
251
|
-
###
|
|
470
|
+
### Example Test
|
|
252
471
|
|
|
253
472
|
```typescript
|
|
254
|
-
|
|
255
|
-
|
|
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
|
|
256
490
|
|
|
257
|
-
|
|
258
|
-
const status = await fetch(
|
|
259
|
-
`https://api.testnet.hiro.so/extended/v1/tx/${result.txid}`
|
|
260
|
-
);
|
|
491
|
+
### Testnet
|
|
261
492
|
|
|
262
|
-
|
|
263
|
-
|
|
493
|
+
**Simple Paymaster**
|
|
494
|
+
```
|
|
495
|
+
Address: STKYNF473GQ1V0WWCF24TV7ZR1WYAKTC79V25E3P.simple-paymaster-v1
|
|
496
|
+
Network: Stacks Testnet
|
|
497
|
+
Explorer: https://explorer.hiro.so/txid/0x90c134205b04599405e3cccae6c86ed496ae2d81ef0392970e2c9a7acd3b2138?chain=testnet
|
|
264
498
|
```
|
|
265
499
|
|
|
266
|
-
|
|
500
|
+
**USDCx Token**
|
|
501
|
+
```
|
|
502
|
+
Address: ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.usdcx
|
|
503
|
+
Standard: SIP-010
|
|
504
|
+
Decimals: 6
|
|
505
|
+
```
|
|
267
506
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
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
|
-
}
|
|
279
|
-
}
|
|
507
|
+
**Relayer**
|
|
508
|
+
```
|
|
509
|
+
URL: https://sgal-relayer.onrender.com/api/v1
|
|
510
|
+
Status: https://sgal-relayer.onrender.com/api/v1/health
|
|
280
511
|
```
|
|
281
512
|
|
|
282
|
-
##
|
|
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.
|
|
283
529
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
- [DEX Integration](../examples/swap)
|
|
287
|
-
- [NFT Marketplace](../examples/nft)
|
|
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.
|
|
288
532
|
|
|
289
|
-
##
|
|
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
|
|
290
542
|
|
|
291
543
|
- **Documentation**: [docs.velumx.com](https://docs.velumx.com)
|
|
292
|
-
- **Dashboard**: [
|
|
544
|
+
- **Dashboard**: [https://velum-x-ssum.vercel.app](https://velum-x-ssum.vercel.app)
|
|
293
545
|
- **Discord**: [discord.gg/velumx](https://discord.gg/velumx)
|
|
294
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
|
|
295
554
|
|
|
296
|
-
|
|
555
|
+
MIT License - see [LICENSE](./LICENSE) for details.
|
|
297
556
|
|
|
298
|
-
|
|
557
|
+
## Changelog
|
|
299
558
|
|
|
300
|
-
|
|
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
|
|
301
564
|
|
|
302
|
-
|
|
565
|
+
### v1.0.0
|
|
566
|
+
- Initial release with smart wallet pattern
|
|
303
567
|
|
|
304
568
|
---
|
|
305
569
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@velumx/sdk",
|
|
3
|
-
"version": "2.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",
|
|
@@ -32,4 +32,4 @@
|
|
|
32
32
|
"@types/node": "^25.3.2",
|
|
33
33
|
"typescript": "^5.9.3"
|
|
34
34
|
}
|
|
35
|
-
}
|
|
35
|
+
}
|