@velumx/sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,22 @@
1
+ import { WalletIntent, SignedIntent } from './types';
2
+ export declare class IntentBuilder {
3
+ private domainName;
4
+ private domainVersion;
5
+ private chainId;
6
+ constructor(network?: 'mainnet' | 'testnet' | 'devnet');
7
+ /**
8
+ * Builds the SIP-018 structured data domain
9
+ */
10
+ private getDomain;
11
+ /**
12
+ * Formats the intent into a Clarity Tuple for signing
13
+ * Structure matches the Smart Wallet expectation
14
+ */
15
+ private formatIntentMessage;
16
+ /**
17
+ * Signs an intent using a private key
18
+ * In a browser environment, this would use a wallet popup (e.g. Leather/Xverse)
19
+ * For Node.js/Backend, it signs directly.
20
+ */
21
+ signIntent(intent: WalletIntent, privateKey: string): SignedIntent;
22
+ }
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IntentBuilder = void 0;
4
+ const transactions_1 = require("@stacks/transactions");
5
+ class IntentBuilder {
6
+ constructor(network = 'mainnet') {
7
+ this.domainName = "SGAL-Smart-Wallet";
8
+ this.domainVersion = "1.0.0";
9
+ this.chainId = network === 'mainnet' ? 1 : 2147483648; // Testnet chain ID
10
+ }
11
+ /**
12
+ * Builds the SIP-018 structured data domain
13
+ */
14
+ getDomain() {
15
+ return (0, transactions_1.tupleCV)({
16
+ name: (0, transactions_1.stringAsciiCV)(this.domainName),
17
+ version: (0, transactions_1.stringAsciiCV)(this.domainVersion),
18
+ 'chain-id': (0, transactions_1.uintCV)(this.chainId)
19
+ });
20
+ }
21
+ /**
22
+ * Formats the intent into a Clarity Tuple for signing
23
+ * Structure matches the Smart Wallet expectation
24
+ */
25
+ formatIntentMessage(intent) {
26
+ return (0, transactions_1.tupleCV)({
27
+ target: (0, transactions_1.principalCV)(intent.target),
28
+ 'function-name': (0, transactions_1.stringAsciiCV)(intent.functionName),
29
+ args: (0, transactions_1.listCV)(intent.args),
30
+ 'max-fee-usdcx': (0, transactions_1.uintCV)(intent.maxFeeUSDCx),
31
+ nonce: (0, transactions_1.uintCV)(intent.nonce),
32
+ deadline: intent.deadline ? (0, transactions_1.someCV)((0, transactions_1.uintCV)(intent.deadline)) : (0, transactions_1.noneCV)()
33
+ });
34
+ }
35
+ /**
36
+ * Signs an intent using a private key
37
+ * In a browser environment, this would use a wallet popup (e.g. Leather/Xverse)
38
+ * For Node.js/Backend, it signs directly.
39
+ */
40
+ signIntent(intent, privateKey) {
41
+ const domain = this.getDomain();
42
+ const message = this.formatIntentMessage(intent);
43
+ // Uses Stacks.js SIP-018 signing utility
44
+ // Note: For dApps, use the '@stacks/connect' openSignatureRequest instead
45
+ const signature = (0, transactions_1.signStructuredData)({
46
+ message,
47
+ domain,
48
+ privateKey
49
+ });
50
+ return {
51
+ ...intent,
52
+ signature
53
+ };
54
+ }
55
+ }
56
+ exports.IntentBuilder = IntentBuilder;
@@ -0,0 +1,20 @@
1
+ import { SignedIntent, NetworkConfig } from './types';
2
+ export declare class VelumXClient {
3
+ private config;
4
+ private relayerUrl;
5
+ constructor(config: NetworkConfig);
6
+ /**
7
+ * Get a fee estimation from the SGAL relayer for a specific intent
8
+ */
9
+ estimateFee(intent: any): Promise<{
10
+ maxFeeUSDCx: string;
11
+ estimatedGas: number;
12
+ }>;
13
+ /**
14
+ * Submit a signed intent to the relayer for sponsorship and execution
15
+ */
16
+ submitIntent(signedIntent: SignedIntent): Promise<{
17
+ txid: string;
18
+ status: string;
19
+ }>;
20
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.VelumXClient = void 0;
4
+ class VelumXClient {
5
+ constructor(config) {
6
+ this.config = config;
7
+ // Default to a hosted relayer if not provided
8
+ this.relayerUrl = config.paymasterUrl || 'https://relayer.velumx.com/api/v1';
9
+ }
10
+ /**
11
+ * Get a fee estimation from the SGAL relayer for a specific intent
12
+ */
13
+ async estimateFee(intent) {
14
+ try {
15
+ const headers = { 'Content-Type': 'application/json' };
16
+ if (this.config.apiKey) {
17
+ headers['x-api-key'] = this.config.apiKey;
18
+ }
19
+ const response = await fetch(`${this.relayerUrl}/estimate`, {
20
+ method: 'POST',
21
+ headers,
22
+ body: JSON.stringify({ intent })
23
+ });
24
+ if (!response.ok) {
25
+ throw new Error(`Fee estimation failed: ${response.statusText}`);
26
+ }
27
+ return await response.json();
28
+ }
29
+ catch (error) {
30
+ console.error("VelumX Client Error (estimateFee):", error);
31
+ throw error;
32
+ }
33
+ }
34
+ /**
35
+ * Submit a signed intent to the relayer for sponsorship and execution
36
+ */
37
+ async submitIntent(signedIntent) {
38
+ try {
39
+ const headers = { 'Content-Type': 'application/json' };
40
+ if (this.config.apiKey) {
41
+ headers['x-api-key'] = this.config.apiKey;
42
+ }
43
+ const response = await fetch(`${this.relayerUrl}/sponsor`, {
44
+ method: 'POST',
45
+ headers,
46
+ body: JSON.stringify({ intent: signedIntent })
47
+ });
48
+ if (!response.ok) {
49
+ const errData = await response.json().catch(() => ({}));
50
+ throw new Error(`Intent sponsorship failed: ${errData.message || response.statusText}`);
51
+ }
52
+ return await response.json();
53
+ }
54
+ catch (error) {
55
+ console.error("VelumX Client Error (submitIntent):", error);
56
+ throw error;
57
+ }
58
+ }
59
+ }
60
+ exports.VelumXClient = VelumXClient;
@@ -0,0 +1,3 @@
1
+ export * from './types';
2
+ export * from './IntentBuilder';
3
+ export * from './VelumXClient';
package/dist/index.js ADDED
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./types"), exports);
18
+ __exportStar(require("./IntentBuilder"), exports);
19
+ __exportStar(require("./VelumXClient"), exports);
20
+ // Core entrypoint for the @velumx/sdk
21
+ // Example Usage:
22
+ // const client = new VelumXClient({ network: 'testnet' });
23
+ // const intentBuilder = new IntentBuilder();
@@ -0,0 +1,18 @@
1
+ import { ClarityValue } from '@stacks/transactions';
2
+ export interface WalletIntent {
3
+ target: string;
4
+ functionName: string;
5
+ args: ClarityValue[];
6
+ maxFeeUSDCx: string | number;
7
+ nonce: string | number;
8
+ deadline?: string | number;
9
+ }
10
+ export interface SignedIntent extends WalletIntent {
11
+ signature: string;
12
+ }
13
+ export interface NetworkConfig {
14
+ coreApiUrl: string;
15
+ network: 'mainnet' | 'testnet' | 'devnet';
16
+ paymasterUrl?: string;
17
+ apiKey?: string;
18
+ }
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "@velumx/sdk",
3
+ "version": "1.0.0",
4
+ "description": "VelumX Gas Abstraction Layer SDK for dApps",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "clean": "if exist dist rmdir /s /q dist",
9
+ "build": "npm run clean && tsc",
10
+ "test": "echo \"Error: no test specified\" && exit 1"
11
+ },
12
+ "publishConfig": {
13
+ "access": "public",
14
+ "registry": "https://registry.npmjs.org/"
15
+ },
16
+ "keywords": [
17
+ "stacks",
18
+ "stx",
19
+ "gasless",
20
+ "paymaster",
21
+ "account-abstraction"
22
+ ],
23
+ "author": "VelumX",
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@stacks/common": "^7.3.1",
27
+ "@stacks/network": "^7.3.1",
28
+ "@stacks/transactions": "^7.3.1"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^25.3.2",
32
+ "typescript": "^5.9.3"
33
+ }
34
+ }
@@ -0,0 +1,70 @@
1
+ import {
2
+ signStructuredData,
3
+ tupleCV,
4
+ uintCV,
5
+ principalCV,
6
+ stringAsciiCV,
7
+ noneCV,
8
+ someCV,
9
+ listCV
10
+ } from '@stacks/transactions';
11
+ import { WalletIntent, SignedIntent } from './types';
12
+
13
+ export class IntentBuilder {
14
+ private domainName = "SGAL-Smart-Wallet";
15
+ private domainVersion = "1.0.0";
16
+ private chainId: number;
17
+
18
+ constructor(network: 'mainnet' | 'testnet' | 'devnet' = 'mainnet') {
19
+ this.chainId = network === 'mainnet' ? 1 : 2147483648; // Testnet chain ID
20
+ }
21
+
22
+ /**
23
+ * Builds the SIP-018 structured data domain
24
+ */
25
+ private getDomain() {
26
+ return tupleCV({
27
+ name: stringAsciiCV(this.domainName),
28
+ version: stringAsciiCV(this.domainVersion),
29
+ 'chain-id': uintCV(this.chainId)
30
+ });
31
+ }
32
+
33
+ /**
34
+ * Formats the intent into a Clarity Tuple for signing
35
+ * Structure matches the Smart Wallet expectation
36
+ */
37
+ private formatIntentMessage(intent: WalletIntent) {
38
+ return tupleCV({
39
+ target: principalCV(intent.target),
40
+ 'function-name': stringAsciiCV(intent.functionName),
41
+ args: listCV(intent.args),
42
+ 'max-fee-usdcx': uintCV(intent.maxFeeUSDCx),
43
+ nonce: uintCV(intent.nonce),
44
+ deadline: intent.deadline ? someCV(uintCV(intent.deadline)) : noneCV()
45
+ });
46
+ }
47
+
48
+ /**
49
+ * Signs an intent using a private key
50
+ * In a browser environment, this would use a wallet popup (e.g. Leather/Xverse)
51
+ * For Node.js/Backend, it signs directly.
52
+ */
53
+ public signIntent(intent: WalletIntent, privateKey: string): SignedIntent {
54
+ const domain = this.getDomain();
55
+ const message = this.formatIntentMessage(intent);
56
+
57
+ // Uses Stacks.js SIP-018 signing utility
58
+ // Note: For dApps, use the '@stacks/connect' openSignatureRequest instead
59
+ const signature = signStructuredData({
60
+ message,
61
+ domain,
62
+ privateKey
63
+ });
64
+
65
+ return {
66
+ ...intent,
67
+ signature
68
+ };
69
+ }
70
+ }
@@ -0,0 +1,67 @@
1
+ import { SignedIntent, NetworkConfig } from './types';
2
+
3
+ export class VelumXClient {
4
+ private config: NetworkConfig;
5
+ private relayerUrl: string;
6
+
7
+ constructor(config: NetworkConfig) {
8
+ this.config = config;
9
+ // Default to a hosted relayer if not provided
10
+ this.relayerUrl = config.paymasterUrl || 'https://relayer.velumx.com/api/v1';
11
+ }
12
+
13
+ /**
14
+ * Get a fee estimation from the SGAL relayer for a specific intent
15
+ */
16
+ public async estimateFee(intent: any): Promise<{ maxFeeUSDCx: string, estimatedGas: number }> {
17
+ try {
18
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
19
+ if (this.config.apiKey) {
20
+ headers['x-api-key'] = this.config.apiKey;
21
+ }
22
+
23
+ const response = await fetch(`${this.relayerUrl}/estimate`, {
24
+ method: 'POST',
25
+ headers,
26
+ body: JSON.stringify({ intent })
27
+ });
28
+
29
+ if (!response.ok) {
30
+ throw new Error(`Fee estimation failed: ${response.statusText}`);
31
+ }
32
+
33
+ return await response.json();
34
+ } catch (error) {
35
+ console.error("VelumX Client Error (estimateFee):", error);
36
+ throw error;
37
+ }
38
+ }
39
+
40
+ /**
41
+ * Submit a signed intent to the relayer for sponsorship and execution
42
+ */
43
+ public async submitIntent(signedIntent: SignedIntent): Promise<{ txid: string, status: string }> {
44
+ try {
45
+ const headers: Record<string, string> = { 'Content-Type': 'application/json' };
46
+ if (this.config.apiKey) {
47
+ headers['x-api-key'] = this.config.apiKey;
48
+ }
49
+
50
+ const response = await fetch(`${this.relayerUrl}/sponsor`, {
51
+ method: 'POST',
52
+ headers,
53
+ body: JSON.stringify({ intent: signedIntent })
54
+ });
55
+
56
+ if (!response.ok) {
57
+ const errData = await response.json().catch(() => ({}));
58
+ throw new Error(`Intent sponsorship failed: ${errData.message || response.statusText}`);
59
+ }
60
+
61
+ return await response.json();
62
+ } catch (error) {
63
+ console.error("VelumX Client Error (submitIntent):", error);
64
+ throw error;
65
+ }
66
+ }
67
+ }
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from './types';
2
+ export * from './IntentBuilder';
3
+ export * from './VelumXClient';
4
+
5
+ // Core entrypoint for the @velumx/sdk
6
+ // Example Usage:
7
+ // const client = new VelumXClient({ network: 'testnet' });
8
+ // const intentBuilder = new IntentBuilder();
package/src/types.ts ADDED
@@ -0,0 +1,21 @@
1
+ import { principalCV, uintCV, stringAsciiCV, tupleCV, someCV, noneCV, ClarityValue } from '@stacks/transactions';
2
+
3
+ export interface WalletIntent {
4
+ target: string;
5
+ functionName: string;
6
+ args: ClarityValue[];
7
+ maxFeeUSDCx: string | number; // uint represented as string or number
8
+ nonce: string | number;
9
+ deadline?: string | number; // Future feature
10
+ }
11
+
12
+ export interface SignedIntent extends WalletIntent {
13
+ signature: string;
14
+ }
15
+
16
+ export interface NetworkConfig {
17
+ coreApiUrl: string;
18
+ network: 'mainnet' | 'testnet' | 'devnet';
19
+ paymasterUrl?: string; // URL for the SGAL relayer service
20
+ apiKey?: string; // SGAL API Key
21
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2020",
4
+ "module": "commonjs",
5
+ "declaration": true,
6
+ "outDir": "./dist",
7
+ "strict": true,
8
+ "esModuleInterop": true,
9
+ "skipLibCheck": true,
10
+ "forceConsistentCasingInFileNames": true
11
+ },
12
+ "include": [
13
+ "src/**/*"
14
+ ]
15
+ }