@velociti/sdk 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +147 -0
- package/dist/client.d.ts +98 -0
- package/dist/client.js +213 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +40 -0
- package/dist/types.d.ts +118 -0
- package/dist/types.js +6 -0
- package/docs/getting-started.md +73 -0
- package/examples/deploy-token.ts +75 -0
- package/package.json +35 -0
- package/src/client.ts +260 -0
- package/src/index.ts +23 -0
- package/src/types.ts +126 -0
- package/tsconfig.json +34 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 VELOCITI
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# VELOCITI SDK
|
|
2
|
+
|
|
3
|
+
Official SDK for deploying and managing tax tokens on [VELOCITI](https://velociti.fun) - the Solana Token-2022 launchpad with built-in transfer taxes.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🚀 **Deploy tokens** with configurable transfer taxes
|
|
8
|
+
- 💰 **Claim fees** accumulated from token transfers
|
|
9
|
+
- 📊 **Track tokens** and monitor performance
|
|
10
|
+
- ⚡ **Rate-limited API** with tiered access
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @velociti/sdk
|
|
16
|
+
# or
|
|
17
|
+
yarn add @velociti/sdk
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Quick Start
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
import { VelocitiClient } from '@velociti/sdk';
|
|
24
|
+
|
|
25
|
+
const client = new VelocitiClient({
|
|
26
|
+
apiKey: 'your-api-key', // Get at velociti.fun/developers
|
|
27
|
+
network: 'mainnet' // or 'devnet'
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// Deploy a new token
|
|
31
|
+
const token = await client.deployToken({
|
|
32
|
+
name: 'My Token',
|
|
33
|
+
symbol: 'MTK',
|
|
34
|
+
description: 'A token with built-in tax',
|
|
35
|
+
taxRate: 5, // 5% transfer tax
|
|
36
|
+
socials: {
|
|
37
|
+
twitter: '@mytoken',
|
|
38
|
+
website: 'https://mytoken.com'
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
console.log(`Token deployed: ${token.data?.mintAddress}`);
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## API Reference
|
|
46
|
+
|
|
47
|
+
### `VelocitiClient`
|
|
48
|
+
|
|
49
|
+
#### Constructor
|
|
50
|
+
|
|
51
|
+
```typescript
|
|
52
|
+
new VelocitiClient({
|
|
53
|
+
apiKey: string; // Required: Your API key
|
|
54
|
+
network?: 'mainnet' | 'devnet'; // Optional: Default 'mainnet'
|
|
55
|
+
baseUrl?: string; // Optional: Custom API URL
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Methods
|
|
60
|
+
|
|
61
|
+
#### `deployToken(params)`
|
|
62
|
+
|
|
63
|
+
Deploy a new token on VELOCITI.
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
await client.deployToken({
|
|
67
|
+
name: string; // Token name (max 32 chars)
|
|
68
|
+
symbol: string; // Token symbol (max 10 chars)
|
|
69
|
+
description?: string; // Token description
|
|
70
|
+
image?: string; // Image URL (IPFS/Arweave/HTTPS)
|
|
71
|
+
taxRate?: number; // Transfer tax 0-10% (default: 5)
|
|
72
|
+
socials?: {
|
|
73
|
+
twitter?: string;
|
|
74
|
+
telegram?: string;
|
|
75
|
+
website?: string;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
#### `getToken(mintAddress)`
|
|
81
|
+
|
|
82
|
+
Get token information.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
const token = await client.getToken('TokenMintAddress...');
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
#### `getMyTokens()`
|
|
89
|
+
|
|
90
|
+
Get all tokens created with your API key.
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
const tokens = await client.getMyTokens();
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
#### `claimFees(mintAddress, walletAddress)`
|
|
97
|
+
|
|
98
|
+
Claim accumulated transfer fees.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
const result = await client.claimFees(
|
|
102
|
+
'TokenMintAddress...',
|
|
103
|
+
'YourWalletAddress...'
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### `getUnclaimedFees(mintAddress)`
|
|
108
|
+
|
|
109
|
+
Check unclaimed fees for a token.
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
const fees = await client.getUnclaimedFees('TokenMintAddress...');
|
|
113
|
+
console.log(`Unclaimed: ${fees.data?.amount} tokens`);
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Rate Limits
|
|
117
|
+
|
|
118
|
+
| Tier | Requests/Day | Token Deploys/Day | Price |
|
|
119
|
+
|------|--------------|-------------------|-------|
|
|
120
|
+
| Free | 100 | 5 | $0 |
|
|
121
|
+
| Pro | 1,000 | 50 | $49/mo |
|
|
122
|
+
| Enterprise | Unlimited | Unlimited | Contact |
|
|
123
|
+
|
|
124
|
+
Check your rate limit status:
|
|
125
|
+
|
|
126
|
+
```typescript
|
|
127
|
+
const rateLimit = client.getRateLimitInfo();
|
|
128
|
+
console.log(`${rateLimit.remaining}/${rateLimit.limit} remaining`);
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Get Your API Key
|
|
132
|
+
|
|
133
|
+
1. Visit [velociti.fun/developers](https://velociti.fun/developers)
|
|
134
|
+
2. Fill out the access request form
|
|
135
|
+
3. Wait for approval (usually within 24 hours)
|
|
136
|
+
4. Receive your API key via email
|
|
137
|
+
|
|
138
|
+
## Links
|
|
139
|
+
|
|
140
|
+
- [VELOCITI Website](https://velociti.fun)
|
|
141
|
+
- [Documentation](https://docs.velociti.fun)
|
|
142
|
+
- [Twitter](https://twitter.com/velocitixyz)
|
|
143
|
+
- [Discord](https://discord.gg/velociti)
|
|
144
|
+
|
|
145
|
+
## License
|
|
146
|
+
|
|
147
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK Client
|
|
3
|
+
* Main client class for interacting with the VELOCITI API
|
|
4
|
+
*/
|
|
5
|
+
import { VelocitiConfig, DeployTokenParams, TokenInfo, ClaimFeesResult, ApiResponse, RateLimitInfo, PreparedTransaction, SubmitResult } from './types';
|
|
6
|
+
export declare class VelocitiClient {
|
|
7
|
+
private apiKey;
|
|
8
|
+
private baseUrl;
|
|
9
|
+
private network;
|
|
10
|
+
private rateLimitInfo;
|
|
11
|
+
constructor(config: VelocitiConfig);
|
|
12
|
+
/**
|
|
13
|
+
* Make an authenticated request to the VELOCITI API
|
|
14
|
+
*/
|
|
15
|
+
private request;
|
|
16
|
+
/**
|
|
17
|
+
* Prepare a token deployment transaction (Step 1)
|
|
18
|
+
*
|
|
19
|
+
* Returns an unsigned transaction that you must sign with your wallet.
|
|
20
|
+
* After signing, call submitTransaction() to complete the deployment.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* // Step 1: Prepare the transaction
|
|
25
|
+
* const prepared = await client.prepareTokenDeploy({
|
|
26
|
+
* name: 'My Token',
|
|
27
|
+
* symbol: 'MTK',
|
|
28
|
+
* taxRate: 5,
|
|
29
|
+
* payerAddress: 'YourWalletAddress...'
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* // Step 2: Sign with your wallet (example using @solana/web3.js)
|
|
33
|
+
* const tx = Transaction.from(Buffer.from(prepared.data.transaction, 'base64'));
|
|
34
|
+
* const signedTx = await wallet.signTransaction(tx);
|
|
35
|
+
*
|
|
36
|
+
* // Step 3: Submit the signed transaction
|
|
37
|
+
* const result = await client.submitTransaction(signedTx.serialize().toString('base64'));
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
prepareTokenDeploy(params: DeployTokenParams): Promise<ApiResponse<PreparedTransaction>>;
|
|
41
|
+
/**
|
|
42
|
+
* Submit a signed transaction (Step 2)
|
|
43
|
+
*
|
|
44
|
+
* @param signedTransaction - Base64 encoded signed transaction
|
|
45
|
+
*/
|
|
46
|
+
submitTransaction(signedTransaction: string): Promise<ApiResponse<SubmitResult>>;
|
|
47
|
+
/**
|
|
48
|
+
* Convenience method: Deploy token in one call (requires wallet adapter)
|
|
49
|
+
*
|
|
50
|
+
* This combines prepareTokenDeploy and submitTransaction.
|
|
51
|
+
* You must provide a signTransaction function from your wallet.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* const result = await client.deployToken({
|
|
56
|
+
* name: 'My Token',
|
|
57
|
+
* symbol: 'MTK',
|
|
58
|
+
* taxRate: 5,
|
|
59
|
+
* payerAddress: wallet.publicKey.toBase58()
|
|
60
|
+
* }, async (tx) => {
|
|
61
|
+
* return await wallet.signTransaction(tx);
|
|
62
|
+
* });
|
|
63
|
+
* ```
|
|
64
|
+
*/
|
|
65
|
+
deployToken(params: DeployTokenParams, signTransaction: (transaction: Uint8Array) => Promise<Uint8Array>): Promise<ApiResponse<SubmitResult>>;
|
|
66
|
+
/**
|
|
67
|
+
* Get token information by mint address
|
|
68
|
+
*/
|
|
69
|
+
getToken(mintAddress: string): Promise<ApiResponse<TokenInfo>>;
|
|
70
|
+
/**
|
|
71
|
+
* Get all tokens created with this API key
|
|
72
|
+
*/
|
|
73
|
+
getMyTokens(): Promise<ApiResponse<TokenInfo[]>>;
|
|
74
|
+
/**
|
|
75
|
+
* Prepare fee claim transaction
|
|
76
|
+
*/
|
|
77
|
+
prepareClaimFees(mintAddress: string, walletAddress: string): Promise<ApiResponse<PreparedTransaction>>;
|
|
78
|
+
/**
|
|
79
|
+
* Claim accumulated transfer fees for a token
|
|
80
|
+
* Combines prepare + sign + submit
|
|
81
|
+
*/
|
|
82
|
+
claimFees(mintAddress: string, walletAddress: string, signTransaction: (transaction: Uint8Array) => Promise<Uint8Array>): Promise<ApiResponse<ClaimFeesResult>>;
|
|
83
|
+
/**
|
|
84
|
+
* Get unclaimed fees for a token
|
|
85
|
+
*/
|
|
86
|
+
getUnclaimedFees(mintAddress: string): Promise<ApiResponse<{
|
|
87
|
+
amount: string;
|
|
88
|
+
valueInSol: number;
|
|
89
|
+
}>>;
|
|
90
|
+
/**
|
|
91
|
+
* Get current rate limit status
|
|
92
|
+
*/
|
|
93
|
+
getRateLimitInfo(): RateLimitInfo | null;
|
|
94
|
+
/**
|
|
95
|
+
* Get the current network
|
|
96
|
+
*/
|
|
97
|
+
getNetwork(): 'mainnet' | 'devnet';
|
|
98
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VELOCITI SDK Client
|
|
4
|
+
* Main client class for interacting with the VELOCITI API
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.VelocitiClient = void 0;
|
|
8
|
+
const DEFAULT_MAINNET_URL = 'https://velociti.fun/api/sdk';
|
|
9
|
+
const DEFAULT_DEVNET_URL = 'https://devnet.velociti.fun/api/sdk';
|
|
10
|
+
class VelocitiClient {
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.rateLimitInfo = null;
|
|
13
|
+
if (!config.apiKey) {
|
|
14
|
+
throw new Error('API key is required. Get one at velociti.fun/developers');
|
|
15
|
+
}
|
|
16
|
+
this.apiKey = config.apiKey;
|
|
17
|
+
this.network = config.network || 'mainnet';
|
|
18
|
+
this.baseUrl = config.baseUrl ||
|
|
19
|
+
(this.network === 'mainnet' ? DEFAULT_MAINNET_URL : DEFAULT_DEVNET_URL);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Make an authenticated request to the VELOCITI API
|
|
23
|
+
*/
|
|
24
|
+
async request(endpoint, options = {}) {
|
|
25
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
26
|
+
const response = await fetch(url, {
|
|
27
|
+
...options,
|
|
28
|
+
headers: {
|
|
29
|
+
'Content-Type': 'application/json',
|
|
30
|
+
'X-API-Key': this.apiKey,
|
|
31
|
+
...options.headers,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
// Update rate limit info from headers
|
|
35
|
+
const remaining = response.headers.get('X-RateLimit-Remaining');
|
|
36
|
+
const limit = response.headers.get('X-RateLimit-Limit');
|
|
37
|
+
const reset = response.headers.get('X-RateLimit-Reset');
|
|
38
|
+
if (remaining && limit && reset) {
|
|
39
|
+
this.rateLimitInfo = {
|
|
40
|
+
remaining: parseInt(remaining, 10),
|
|
41
|
+
limit: parseInt(limit, 10),
|
|
42
|
+
reset: parseInt(reset, 10),
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
if (response.status === 429) {
|
|
46
|
+
return {
|
|
47
|
+
success: false,
|
|
48
|
+
error: 'Rate limit exceeded. Please try again later.',
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (!response.ok) {
|
|
52
|
+
const errorData = await response.json().catch(() => ({}));
|
|
53
|
+
return {
|
|
54
|
+
success: false,
|
|
55
|
+
error: errorData.error || `HTTP ${response.status}: ${response.statusText}`,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const data = await response.json();
|
|
59
|
+
return { success: true, data };
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Prepare a token deployment transaction (Step 1)
|
|
63
|
+
*
|
|
64
|
+
* Returns an unsigned transaction that you must sign with your wallet.
|
|
65
|
+
* After signing, call submitTransaction() to complete the deployment.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* // Step 1: Prepare the transaction
|
|
70
|
+
* const prepared = await client.prepareTokenDeploy({
|
|
71
|
+
* name: 'My Token',
|
|
72
|
+
* symbol: 'MTK',
|
|
73
|
+
* taxRate: 5,
|
|
74
|
+
* payerAddress: 'YourWalletAddress...'
|
|
75
|
+
* });
|
|
76
|
+
*
|
|
77
|
+
* // Step 2: Sign with your wallet (example using @solana/web3.js)
|
|
78
|
+
* const tx = Transaction.from(Buffer.from(prepared.data.transaction, 'base64'));
|
|
79
|
+
* const signedTx = await wallet.signTransaction(tx);
|
|
80
|
+
*
|
|
81
|
+
* // Step 3: Submit the signed transaction
|
|
82
|
+
* const result = await client.submitTransaction(signedTx.serialize().toString('base64'));
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
async prepareTokenDeploy(params) {
|
|
86
|
+
// Validate params
|
|
87
|
+
if (!params.name || params.name.length > 32) {
|
|
88
|
+
return { success: false, error: 'Name is required and must be <= 32 characters' };
|
|
89
|
+
}
|
|
90
|
+
if (!params.symbol || params.symbol.length > 10) {
|
|
91
|
+
return { success: false, error: 'Symbol is required and must be <= 10 characters' };
|
|
92
|
+
}
|
|
93
|
+
if (!params.payerAddress) {
|
|
94
|
+
return { success: false, error: 'Payer wallet address is required' };
|
|
95
|
+
}
|
|
96
|
+
if (params.taxRate !== undefined && (params.taxRate < 0 || params.taxRate > 10)) {
|
|
97
|
+
return { success: false, error: 'Tax rate must be between 0 and 10%' };
|
|
98
|
+
}
|
|
99
|
+
return this.request('/deploy/prepare', {
|
|
100
|
+
method: 'POST',
|
|
101
|
+
body: JSON.stringify(params),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Submit a signed transaction (Step 2)
|
|
106
|
+
*
|
|
107
|
+
* @param signedTransaction - Base64 encoded signed transaction
|
|
108
|
+
*/
|
|
109
|
+
async submitTransaction(signedTransaction) {
|
|
110
|
+
return this.request('/deploy/submit', {
|
|
111
|
+
method: 'POST',
|
|
112
|
+
body: JSON.stringify({ signedTransaction }),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Convenience method: Deploy token in one call (requires wallet adapter)
|
|
117
|
+
*
|
|
118
|
+
* This combines prepareTokenDeploy and submitTransaction.
|
|
119
|
+
* You must provide a signTransaction function from your wallet.
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* ```typescript
|
|
123
|
+
* const result = await client.deployToken({
|
|
124
|
+
* name: 'My Token',
|
|
125
|
+
* symbol: 'MTK',
|
|
126
|
+
* taxRate: 5,
|
|
127
|
+
* payerAddress: wallet.publicKey.toBase58()
|
|
128
|
+
* }, async (tx) => {
|
|
129
|
+
* return await wallet.signTransaction(tx);
|
|
130
|
+
* });
|
|
131
|
+
* ```
|
|
132
|
+
*/
|
|
133
|
+
async deployToken(params, signTransaction) {
|
|
134
|
+
// Step 1: Prepare
|
|
135
|
+
const prepared = await this.prepareTokenDeploy(params);
|
|
136
|
+
if (!prepared.success || !prepared.data) {
|
|
137
|
+
return { success: false, error: prepared.error || 'Failed to prepare transaction' };
|
|
138
|
+
}
|
|
139
|
+
// Step 2: Sign
|
|
140
|
+
try {
|
|
141
|
+
const txBytes = Uint8Array.from(atob(prepared.data.transaction), c => c.charCodeAt(0));
|
|
142
|
+
const signedBytes = await signTransaction(txBytes);
|
|
143
|
+
const signedBase64 = btoa(String.fromCharCode(...signedBytes));
|
|
144
|
+
// Step 3: Submit
|
|
145
|
+
return this.submitTransaction(signedBase64);
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
return { success: false, error: `Signing failed: ${error.message}` };
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get token information by mint address
|
|
153
|
+
*/
|
|
154
|
+
async getToken(mintAddress) {
|
|
155
|
+
return this.request(`/tokens/${mintAddress}`);
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Get all tokens created with this API key
|
|
159
|
+
*/
|
|
160
|
+
async getMyTokens() {
|
|
161
|
+
return this.request('/tokens/mine');
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Prepare fee claim transaction
|
|
165
|
+
*/
|
|
166
|
+
async prepareClaimFees(mintAddress, walletAddress) {
|
|
167
|
+
return this.request('/fees/prepare', {
|
|
168
|
+
method: 'POST',
|
|
169
|
+
body: JSON.stringify({ mintAddress, walletAddress }),
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Claim accumulated transfer fees for a token
|
|
174
|
+
* Combines prepare + sign + submit
|
|
175
|
+
*/
|
|
176
|
+
async claimFees(mintAddress, walletAddress, signTransaction) {
|
|
177
|
+
const prepared = await this.prepareClaimFees(mintAddress, walletAddress);
|
|
178
|
+
if (!prepared.success || !prepared.data) {
|
|
179
|
+
return { success: false, error: prepared.error || 'Failed to prepare claim' };
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
const txBytes = Uint8Array.from(atob(prepared.data.transaction), c => c.charCodeAt(0));
|
|
183
|
+
const signedBytes = await signTransaction(txBytes);
|
|
184
|
+
const signedBase64 = btoa(String.fromCharCode(...signedBytes));
|
|
185
|
+
return this.request('/fees/submit', {
|
|
186
|
+
method: 'POST',
|
|
187
|
+
body: JSON.stringify({ signedTransaction: signedBase64, mintAddress }),
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
return { success: false, error: `Signing failed: ${error.message}` };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get unclaimed fees for a token
|
|
196
|
+
*/
|
|
197
|
+
async getUnclaimedFees(mintAddress) {
|
|
198
|
+
return this.request(`/fees/${mintAddress}`);
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* Get current rate limit status
|
|
202
|
+
*/
|
|
203
|
+
getRateLimitInfo() {
|
|
204
|
+
return this.rateLimitInfo;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Get the current network
|
|
208
|
+
*/
|
|
209
|
+
getNetwork() {
|
|
210
|
+
return this.network;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
exports.VelocitiClient = VelocitiClient;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK
|
|
3
|
+
* Official SDK for deploying and managing tokens on VELOCITI
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { VelocitiClient } from '@velociti/sdk';
|
|
8
|
+
*
|
|
9
|
+
* const client = new VelocitiClient({
|
|
10
|
+
* apiKey: 'your-api-key',
|
|
11
|
+
* network: 'devnet'
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* const token = await client.deployToken({
|
|
15
|
+
* name: 'My Token',
|
|
16
|
+
* symbol: 'MTK',
|
|
17
|
+
* taxRate: 5
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export { VelocitiClient } from './client';
|
|
22
|
+
export * from './types';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* VELOCITI SDK
|
|
4
|
+
* Official SDK for deploying and managing tokens on VELOCITI
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { VelocitiClient } from '@velociti/sdk';
|
|
9
|
+
*
|
|
10
|
+
* const client = new VelocitiClient({
|
|
11
|
+
* apiKey: 'your-api-key',
|
|
12
|
+
* network: 'devnet'
|
|
13
|
+
* });
|
|
14
|
+
*
|
|
15
|
+
* const token = await client.deployToken({
|
|
16
|
+
* name: 'My Token',
|
|
17
|
+
* symbol: 'MTK',
|
|
18
|
+
* taxRate: 5
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
23
|
+
if (k2 === undefined) k2 = k;
|
|
24
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
25
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
26
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
27
|
+
}
|
|
28
|
+
Object.defineProperty(o, k2, desc);
|
|
29
|
+
}) : (function(o, m, k, k2) {
|
|
30
|
+
if (k2 === undefined) k2 = k;
|
|
31
|
+
o[k2] = m[k];
|
|
32
|
+
}));
|
|
33
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
34
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.VelocitiClient = void 0;
|
|
38
|
+
var client_1 = require("./client");
|
|
39
|
+
Object.defineProperty(exports, "VelocitiClient", { enumerable: true, get: function () { return client_1.VelocitiClient; } });
|
|
40
|
+
__exportStar(require("./types"), exports);
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK Types
|
|
3
|
+
* TypeScript type definitions for the SDK
|
|
4
|
+
*/
|
|
5
|
+
/** SDK Configuration */
|
|
6
|
+
export interface VelocitiConfig {
|
|
7
|
+
/** Your API key from velociti.fun/developers */
|
|
8
|
+
apiKey: string;
|
|
9
|
+
/** Network to use: 'mainnet' or 'devnet' */
|
|
10
|
+
network?: 'mainnet' | 'devnet';
|
|
11
|
+
/** Custom API base URL (optional) */
|
|
12
|
+
baseUrl?: string;
|
|
13
|
+
}
|
|
14
|
+
/** Token deployment configuration */
|
|
15
|
+
export interface DeployTokenParams {
|
|
16
|
+
/** Token name (max 32 characters) */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Token symbol (max 10 characters) */
|
|
19
|
+
symbol: string;
|
|
20
|
+
/** Token description */
|
|
21
|
+
description?: string;
|
|
22
|
+
/** Image URL (IPFS, Arweave, or HTTPS) */
|
|
23
|
+
image?: string;
|
|
24
|
+
/** Transfer tax rate (0-10%) */
|
|
25
|
+
taxRate?: number;
|
|
26
|
+
/** Payer wallet address (required - will sign and pay fees) */
|
|
27
|
+
payerAddress: string;
|
|
28
|
+
/** Social links */
|
|
29
|
+
socials?: {
|
|
30
|
+
twitter?: string;
|
|
31
|
+
telegram?: string;
|
|
32
|
+
website?: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Prepared transaction ready for signing */
|
|
36
|
+
export interface PreparedTransaction {
|
|
37
|
+
/** Base64 encoded serialized transaction */
|
|
38
|
+
transaction: string;
|
|
39
|
+
/** Estimated SOL fee for the transaction */
|
|
40
|
+
estimatedFee: number;
|
|
41
|
+
/** Token mint address that will be created */
|
|
42
|
+
mintAddress: string;
|
|
43
|
+
/** Message to display to user */
|
|
44
|
+
message: string;
|
|
45
|
+
/** Blockhash used (expires after ~60 seconds) */
|
|
46
|
+
blockhash: string;
|
|
47
|
+
/** Last valid block height */
|
|
48
|
+
lastValidBlockHeight: number;
|
|
49
|
+
}
|
|
50
|
+
/** Token information returned from API */
|
|
51
|
+
export interface TokenInfo {
|
|
52
|
+
/** Token mint address */
|
|
53
|
+
mintAddress: string;
|
|
54
|
+
/** Token name */
|
|
55
|
+
name: string;
|
|
56
|
+
/** Token symbol */
|
|
57
|
+
symbol: string;
|
|
58
|
+
/** Token description */
|
|
59
|
+
description?: string;
|
|
60
|
+
/** Token image URL */
|
|
61
|
+
imageUrl?: string;
|
|
62
|
+
/** Current price in SOL */
|
|
63
|
+
priceInSol: number;
|
|
64
|
+
/** Current price in USD */
|
|
65
|
+
priceInUsd: number;
|
|
66
|
+
/** Market cap in USD */
|
|
67
|
+
marketCapUsd: number;
|
|
68
|
+
/** Graduation progress (0-100) */
|
|
69
|
+
progress: number;
|
|
70
|
+
/** Whether token has graduated to Raydium */
|
|
71
|
+
isGraduated: boolean;
|
|
72
|
+
/** Transfer tax rate */
|
|
73
|
+
taxRate: number;
|
|
74
|
+
/** Creator wallet address */
|
|
75
|
+
creator: string;
|
|
76
|
+
/** Bonding curve PDA */
|
|
77
|
+
bondingCurvePda: string;
|
|
78
|
+
/** Total supply */
|
|
79
|
+
totalSupply: string;
|
|
80
|
+
/** Created at timestamp */
|
|
81
|
+
createdAt: string;
|
|
82
|
+
}
|
|
83
|
+
/** Fee claiming result */
|
|
84
|
+
export interface ClaimFeesResult {
|
|
85
|
+
/** Transaction signature */
|
|
86
|
+
signature: string;
|
|
87
|
+
/** Amount claimed in tokens */
|
|
88
|
+
amountClaimed: string;
|
|
89
|
+
/** SOL value of claimed fees */
|
|
90
|
+
valueInSol: number;
|
|
91
|
+
}
|
|
92
|
+
/** Submit signed transaction result */
|
|
93
|
+
export interface SubmitResult {
|
|
94
|
+
/** Whether submission was successful */
|
|
95
|
+
success: boolean;
|
|
96
|
+
/** Transaction signature */
|
|
97
|
+
signature?: string;
|
|
98
|
+
/** Token info if deployment confirmed */
|
|
99
|
+
token?: TokenInfo;
|
|
100
|
+
/** Error message if failed */
|
|
101
|
+
error?: string;
|
|
102
|
+
}
|
|
103
|
+
/** API response wrapper */
|
|
104
|
+
export interface ApiResponse<T> {
|
|
105
|
+
success: boolean;
|
|
106
|
+
data?: T;
|
|
107
|
+
error?: string;
|
|
108
|
+
message?: string;
|
|
109
|
+
}
|
|
110
|
+
/** Rate limit information */
|
|
111
|
+
export interface RateLimitInfo {
|
|
112
|
+
/** Remaining requests in current window */
|
|
113
|
+
remaining: number;
|
|
114
|
+
/** Total limit for current tier */
|
|
115
|
+
limit: number;
|
|
116
|
+
/** Reset timestamp (Unix ms) */
|
|
117
|
+
reset: number;
|
|
118
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Getting Started with VELOCITI SDK
|
|
2
|
+
|
|
3
|
+
This guide will help you set up and deploy your first token using the VELOCITI SDK.
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- Node.js 18+
|
|
8
|
+
- npm or yarn
|
|
9
|
+
- A VELOCITI API key
|
|
10
|
+
|
|
11
|
+
## Step 1: Get Your API Key
|
|
12
|
+
|
|
13
|
+
1. Visit [velociti.fun/developers](https://velociti.fun/developers)
|
|
14
|
+
2. Fill out the access request form with:
|
|
15
|
+
- Your name and email
|
|
16
|
+
- Project name and description
|
|
17
|
+
- Intended use case
|
|
18
|
+
3. Wait for approval (usually within 24 hours)
|
|
19
|
+
4. Check your email for your API key
|
|
20
|
+
|
|
21
|
+
## Step 2: Install the SDK
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @velociti/sdk
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Step 3: Initialize the Client
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { VelocitiClient } from '@velociti/sdk';
|
|
31
|
+
|
|
32
|
+
const client = new VelocitiClient({
|
|
33
|
+
apiKey: process.env.VELOCITI_API_KEY,
|
|
34
|
+
network: 'devnet' // Start with devnet for testing
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Step 4: Deploy Your First Token
|
|
39
|
+
|
|
40
|
+
```typescript
|
|
41
|
+
const result = await client.deployToken({
|
|
42
|
+
name: 'My First Token',
|
|
43
|
+
symbol: 'MFT',
|
|
44
|
+
description: 'My first token on VELOCITI',
|
|
45
|
+
taxRate: 5, // 5% transfer tax
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (result.success) {
|
|
49
|
+
console.log('Token deployed!', result.data?.mintAddress);
|
|
50
|
+
} else {
|
|
51
|
+
console.error('Failed:', result.error);
|
|
52
|
+
}
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Step 5: Monitor and Claim Fees
|
|
56
|
+
|
|
57
|
+
```typescript
|
|
58
|
+
// Check unclaimed fees
|
|
59
|
+
const fees = await client.getUnclaimedFees(result.data.mintAddress);
|
|
60
|
+
console.log('Unclaimed fees:', fees.data?.amount);
|
|
61
|
+
|
|
62
|
+
// Claim fees to your wallet
|
|
63
|
+
const claim = await client.claimFees(
|
|
64
|
+
result.data.mintAddress,
|
|
65
|
+
'YourWalletAddress...'
|
|
66
|
+
);
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
## Next Steps
|
|
70
|
+
|
|
71
|
+
- Explore the [API Reference](./api-reference.md)
|
|
72
|
+
- Check out [examples](../examples/)
|
|
73
|
+
- Join our [Discord](https://discord.gg/velociti) for support
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Example: Deploy a token on VELOCITI
|
|
3
|
+
*
|
|
4
|
+
* This example shows the 2-step flow:
|
|
5
|
+
* 1. Prepare transaction (API builds it with all program addresses)
|
|
6
|
+
* 2. Sign & submit (you pay the fees)
|
|
7
|
+
*
|
|
8
|
+
* Run with: npx ts-node examples/deploy-token.ts
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { VelocitiClient } from '../src';
|
|
12
|
+
import { Keypair, Transaction } from '@solana/web3.js';
|
|
13
|
+
|
|
14
|
+
async function main() {
|
|
15
|
+
// Initialize the client with your API key
|
|
16
|
+
const client = new VelocitiClient({
|
|
17
|
+
apiKey: process.env.VELOCITI_API_KEY || 'your-api-key',
|
|
18
|
+
network: 'devnet',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
// Your wallet (in production, use wallet adapter)
|
|
22
|
+
const wallet = Keypair.generate(); // Demo only!
|
|
23
|
+
|
|
24
|
+
console.log('🚀 Preparing token deployment...\n');
|
|
25
|
+
console.log(` Wallet: ${wallet.publicKey.toBase58()}`);
|
|
26
|
+
|
|
27
|
+
// Step 1: Prepare the transaction
|
|
28
|
+
// The API builds the full transaction with all program addresses,
|
|
29
|
+
// PDAs, and accounts. You don't need to know any internal details!
|
|
30
|
+
const prepared = await client.prepareTokenDeploy({
|
|
31
|
+
name: 'My AI Token',
|
|
32
|
+
symbol: 'AIT',
|
|
33
|
+
description: 'A token deployed by an AI agent',
|
|
34
|
+
taxRate: 5,
|
|
35
|
+
payerAddress: wallet.publicKey.toBase58(), // You pay the fees
|
|
36
|
+
socials: {
|
|
37
|
+
twitter: '@myaitoken',
|
|
38
|
+
website: 'https://myaitoken.com',
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (!prepared.success || !prepared.data) {
|
|
43
|
+
console.error('❌ Prepare failed:', prepared.error);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log('\n📋 Transaction prepared:');
|
|
48
|
+
console.log(` Mint Address: ${prepared.data.mintAddress}`);
|
|
49
|
+
console.log(` Estimated Fee: ${prepared.data.estimatedFee} SOL`);
|
|
50
|
+
|
|
51
|
+
// Step 2: Sign the transaction with your wallet
|
|
52
|
+
const tx = Transaction.from(Buffer.from(prepared.data.transaction, 'base64'));
|
|
53
|
+
tx.sign(wallet); // In production: await walletAdapter.signTransaction(tx)
|
|
54
|
+
|
|
55
|
+
// Step 3: Submit the signed transaction
|
|
56
|
+
const signedBase64 = tx.serialize().toString('base64');
|
|
57
|
+
const result = await client.submitTransaction(signedBase64);
|
|
58
|
+
|
|
59
|
+
if (!result.success) {
|
|
60
|
+
console.error('❌ Deployment failed:', result.error);
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('\n✅ Token deployed successfully!');
|
|
65
|
+
console.log(` Signature: ${result.data?.signature}`);
|
|
66
|
+
console.log(` View: https://velociti.fun/token/${prepared.data.mintAddress}`);
|
|
67
|
+
|
|
68
|
+
// Check rate limit
|
|
69
|
+
const rateLimit = client.getRateLimitInfo();
|
|
70
|
+
if (rateLimit) {
|
|
71
|
+
console.log(`\n📊 Rate Limit: ${rateLimit.remaining}/${rateLimit.limit} remaining`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@velociti/sdk",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Official SDK for deploying and managing tokens on VELOCITI - the Solana tax token launchpad",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"test": "jest",
|
|
10
|
+
"prepublishOnly": "npm run build"
|
|
11
|
+
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"solana",
|
|
14
|
+
"token",
|
|
15
|
+
"launchpad",
|
|
16
|
+
"velociti",
|
|
17
|
+
"tax-token",
|
|
18
|
+
"token-2022",
|
|
19
|
+
"ai-agent"
|
|
20
|
+
],
|
|
21
|
+
"author": "VELOCITI",
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@solana/web3.js": "^1.95.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"typescript": "^5.3.0"
|
|
29
|
+
},
|
|
30
|
+
"repository": {
|
|
31
|
+
"type": "git",
|
|
32
|
+
"url": "https://github.com/Velociti-Launchpad/velociti-sdk"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://velociti.fun/developers"
|
|
35
|
+
}
|
package/src/client.ts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK Client
|
|
3
|
+
* Main client class for interacting with the VELOCITI API
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
VelocitiConfig,
|
|
8
|
+
DeployTokenParams,
|
|
9
|
+
TokenInfo,
|
|
10
|
+
ClaimFeesResult,
|
|
11
|
+
ApiResponse,
|
|
12
|
+
RateLimitInfo,
|
|
13
|
+
PreparedTransaction,
|
|
14
|
+
SubmitResult,
|
|
15
|
+
} from './types';
|
|
16
|
+
|
|
17
|
+
const DEFAULT_MAINNET_URL = 'https://velociti.fun/api/sdk';
|
|
18
|
+
const DEFAULT_DEVNET_URL = 'https://devnet.velociti.fun/api/sdk';
|
|
19
|
+
|
|
20
|
+
export class VelocitiClient {
|
|
21
|
+
private apiKey: string;
|
|
22
|
+
private baseUrl: string;
|
|
23
|
+
private network: 'mainnet' | 'devnet';
|
|
24
|
+
private rateLimitInfo: RateLimitInfo | null = null;
|
|
25
|
+
|
|
26
|
+
constructor(config: VelocitiConfig) {
|
|
27
|
+
if (!config.apiKey) {
|
|
28
|
+
throw new Error('API key is required. Get one at velociti.fun/developers');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
this.apiKey = config.apiKey;
|
|
32
|
+
this.network = config.network || 'mainnet';
|
|
33
|
+
this.baseUrl = config.baseUrl ||
|
|
34
|
+
(this.network === 'mainnet' ? DEFAULT_MAINNET_URL : DEFAULT_DEVNET_URL);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Make an authenticated request to the VELOCITI API
|
|
39
|
+
*/
|
|
40
|
+
private async request<T>(
|
|
41
|
+
endpoint: string,
|
|
42
|
+
options: RequestInit = {}
|
|
43
|
+
): Promise<ApiResponse<T>> {
|
|
44
|
+
const url = `${this.baseUrl}${endpoint}`;
|
|
45
|
+
|
|
46
|
+
const response = await fetch(url, {
|
|
47
|
+
...options,
|
|
48
|
+
headers: {
|
|
49
|
+
'Content-Type': 'application/json',
|
|
50
|
+
'X-API-Key': this.apiKey,
|
|
51
|
+
...options.headers,
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// Update rate limit info from headers
|
|
56
|
+
const remaining = response.headers.get('X-RateLimit-Remaining');
|
|
57
|
+
const limit = response.headers.get('X-RateLimit-Limit');
|
|
58
|
+
const reset = response.headers.get('X-RateLimit-Reset');
|
|
59
|
+
|
|
60
|
+
if (remaining && limit && reset) {
|
|
61
|
+
this.rateLimitInfo = {
|
|
62
|
+
remaining: parseInt(remaining, 10),
|
|
63
|
+
limit: parseInt(limit, 10),
|
|
64
|
+
reset: parseInt(reset, 10),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if (response.status === 429) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Rate limit exceeded. Please try again later.',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (!response.ok) {
|
|
76
|
+
const errorData = await response.json().catch(() => ({})) as { error?: string };
|
|
77
|
+
return {
|
|
78
|
+
success: false,
|
|
79
|
+
error: errorData.error || `HTTP ${response.status}: ${response.statusText}`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const data = await response.json() as T;
|
|
84
|
+
return { success: true, data };
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Prepare a token deployment transaction (Step 1)
|
|
89
|
+
*
|
|
90
|
+
* Returns an unsigned transaction that you must sign with your wallet.
|
|
91
|
+
* After signing, call submitTransaction() to complete the deployment.
|
|
92
|
+
*
|
|
93
|
+
* @example
|
|
94
|
+
* ```typescript
|
|
95
|
+
* // Step 1: Prepare the transaction
|
|
96
|
+
* const prepared = await client.prepareTokenDeploy({
|
|
97
|
+
* name: 'My Token',
|
|
98
|
+
* symbol: 'MTK',
|
|
99
|
+
* taxRate: 5,
|
|
100
|
+
* payerAddress: 'YourWalletAddress...'
|
|
101
|
+
* });
|
|
102
|
+
*
|
|
103
|
+
* // Step 2: Sign with your wallet (example using @solana/web3.js)
|
|
104
|
+
* const tx = Transaction.from(Buffer.from(prepared.data.transaction, 'base64'));
|
|
105
|
+
* const signedTx = await wallet.signTransaction(tx);
|
|
106
|
+
*
|
|
107
|
+
* // Step 3: Submit the signed transaction
|
|
108
|
+
* const result = await client.submitTransaction(signedTx.serialize().toString('base64'));
|
|
109
|
+
* ```
|
|
110
|
+
*/
|
|
111
|
+
async prepareTokenDeploy(params: DeployTokenParams): Promise<ApiResponse<PreparedTransaction>> {
|
|
112
|
+
// Validate params
|
|
113
|
+
if (!params.name || params.name.length > 32) {
|
|
114
|
+
return { success: false, error: 'Name is required and must be <= 32 characters' };
|
|
115
|
+
}
|
|
116
|
+
if (!params.symbol || params.symbol.length > 10) {
|
|
117
|
+
return { success: false, error: 'Symbol is required and must be <= 10 characters' };
|
|
118
|
+
}
|
|
119
|
+
if (!params.payerAddress) {
|
|
120
|
+
return { success: false, error: 'Payer wallet address is required' };
|
|
121
|
+
}
|
|
122
|
+
if (params.taxRate !== undefined && (params.taxRate < 0 || params.taxRate > 10)) {
|
|
123
|
+
return { success: false, error: 'Tax rate must be between 0 and 10%' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return this.request<PreparedTransaction>('/deploy/prepare', {
|
|
127
|
+
method: 'POST',
|
|
128
|
+
body: JSON.stringify(params),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Submit a signed transaction (Step 2)
|
|
134
|
+
*
|
|
135
|
+
* @param signedTransaction - Base64 encoded signed transaction
|
|
136
|
+
*/
|
|
137
|
+
async submitTransaction(signedTransaction: string): Promise<ApiResponse<SubmitResult>> {
|
|
138
|
+
return this.request<SubmitResult>('/deploy/submit', {
|
|
139
|
+
method: 'POST',
|
|
140
|
+
body: JSON.stringify({ signedTransaction }),
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Convenience method: Deploy token in one call (requires wallet adapter)
|
|
146
|
+
*
|
|
147
|
+
* This combines prepareTokenDeploy and submitTransaction.
|
|
148
|
+
* You must provide a signTransaction function from your wallet.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```typescript
|
|
152
|
+
* const result = await client.deployToken({
|
|
153
|
+
* name: 'My Token',
|
|
154
|
+
* symbol: 'MTK',
|
|
155
|
+
* taxRate: 5,
|
|
156
|
+
* payerAddress: wallet.publicKey.toBase58()
|
|
157
|
+
* }, async (tx) => {
|
|
158
|
+
* return await wallet.signTransaction(tx);
|
|
159
|
+
* });
|
|
160
|
+
* ```
|
|
161
|
+
*/
|
|
162
|
+
async deployToken(
|
|
163
|
+
params: DeployTokenParams,
|
|
164
|
+
signTransaction: (transaction: Uint8Array) => Promise<Uint8Array>
|
|
165
|
+
): Promise<ApiResponse<SubmitResult>> {
|
|
166
|
+
// Step 1: Prepare
|
|
167
|
+
const prepared = await this.prepareTokenDeploy(params);
|
|
168
|
+
if (!prepared.success || !prepared.data) {
|
|
169
|
+
return { success: false, error: prepared.error || 'Failed to prepare transaction' };
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Step 2: Sign
|
|
173
|
+
try {
|
|
174
|
+
const txBytes = Uint8Array.from(atob(prepared.data.transaction), c => c.charCodeAt(0));
|
|
175
|
+
const signedBytes = await signTransaction(txBytes);
|
|
176
|
+
const signedBase64 = btoa(String.fromCharCode(...signedBytes));
|
|
177
|
+
|
|
178
|
+
// Step 3: Submit
|
|
179
|
+
return this.submitTransaction(signedBase64);
|
|
180
|
+
} catch (error: any) {
|
|
181
|
+
return { success: false, error: `Signing failed: ${error.message}` };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get token information by mint address
|
|
187
|
+
*/
|
|
188
|
+
async getToken(mintAddress: string): Promise<ApiResponse<TokenInfo>> {
|
|
189
|
+
return this.request<TokenInfo>(`/tokens/${mintAddress}`);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Get all tokens created with this API key
|
|
194
|
+
*/
|
|
195
|
+
async getMyTokens(): Promise<ApiResponse<TokenInfo[]>> {
|
|
196
|
+
return this.request<TokenInfo[]>('/tokens/mine');
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Prepare fee claim transaction
|
|
201
|
+
*/
|
|
202
|
+
async prepareClaimFees(
|
|
203
|
+
mintAddress: string,
|
|
204
|
+
walletAddress: string
|
|
205
|
+
): Promise<ApiResponse<PreparedTransaction>> {
|
|
206
|
+
return this.request<PreparedTransaction>('/fees/prepare', {
|
|
207
|
+
method: 'POST',
|
|
208
|
+
body: JSON.stringify({ mintAddress, walletAddress }),
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Claim accumulated transfer fees for a token
|
|
214
|
+
* Combines prepare + sign + submit
|
|
215
|
+
*/
|
|
216
|
+
async claimFees(
|
|
217
|
+
mintAddress: string,
|
|
218
|
+
walletAddress: string,
|
|
219
|
+
signTransaction: (transaction: Uint8Array) => Promise<Uint8Array>
|
|
220
|
+
): Promise<ApiResponse<ClaimFeesResult>> {
|
|
221
|
+
const prepared = await this.prepareClaimFees(mintAddress, walletAddress);
|
|
222
|
+
if (!prepared.success || !prepared.data) {
|
|
223
|
+
return { success: false, error: prepared.error || 'Failed to prepare claim' };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const txBytes = Uint8Array.from(atob(prepared.data.transaction), c => c.charCodeAt(0));
|
|
228
|
+
const signedBytes = await signTransaction(txBytes);
|
|
229
|
+
const signedBase64 = btoa(String.fromCharCode(...signedBytes));
|
|
230
|
+
|
|
231
|
+
return this.request<ClaimFeesResult>('/fees/submit', {
|
|
232
|
+
method: 'POST',
|
|
233
|
+
body: JSON.stringify({ signedTransaction: signedBase64, mintAddress }),
|
|
234
|
+
});
|
|
235
|
+
} catch (error: any) {
|
|
236
|
+
return { success: false, error: `Signing failed: ${error.message}` };
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Get unclaimed fees for a token
|
|
242
|
+
*/
|
|
243
|
+
async getUnclaimedFees(mintAddress: string): Promise<ApiResponse<{ amount: string; valueInSol: number }>> {
|
|
244
|
+
return this.request(`/fees/${mintAddress}`);
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Get current rate limit status
|
|
249
|
+
*/
|
|
250
|
+
getRateLimitInfo(): RateLimitInfo | null {
|
|
251
|
+
return this.rateLimitInfo;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Get the current network
|
|
256
|
+
*/
|
|
257
|
+
getNetwork(): 'mainnet' | 'devnet' {
|
|
258
|
+
return this.network;
|
|
259
|
+
}
|
|
260
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK
|
|
3
|
+
* Official SDK for deploying and managing tokens on VELOCITI
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { VelocitiClient } from '@velociti/sdk';
|
|
8
|
+
*
|
|
9
|
+
* const client = new VelocitiClient({
|
|
10
|
+
* apiKey: 'your-api-key',
|
|
11
|
+
* network: 'devnet'
|
|
12
|
+
* });
|
|
13
|
+
*
|
|
14
|
+
* const token = await client.deployToken({
|
|
15
|
+
* name: 'My Token',
|
|
16
|
+
* symbol: 'MTK',
|
|
17
|
+
* taxRate: 5
|
|
18
|
+
* });
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
export { VelocitiClient } from './client';
|
|
23
|
+
export * from './types';
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VELOCITI SDK Types
|
|
3
|
+
* TypeScript type definitions for the SDK
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/** SDK Configuration */
|
|
7
|
+
export interface VelocitiConfig {
|
|
8
|
+
/** Your API key from velociti.fun/developers */
|
|
9
|
+
apiKey: string;
|
|
10
|
+
/** Network to use: 'mainnet' or 'devnet' */
|
|
11
|
+
network?: 'mainnet' | 'devnet';
|
|
12
|
+
/** Custom API base URL (optional) */
|
|
13
|
+
baseUrl?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/** Token deployment configuration */
|
|
17
|
+
export interface DeployTokenParams {
|
|
18
|
+
/** Token name (max 32 characters) */
|
|
19
|
+
name: string;
|
|
20
|
+
/** Token symbol (max 10 characters) */
|
|
21
|
+
symbol: string;
|
|
22
|
+
/** Token description */
|
|
23
|
+
description?: string;
|
|
24
|
+
/** Image URL (IPFS, Arweave, or HTTPS) */
|
|
25
|
+
image?: string;
|
|
26
|
+
/** Transfer tax rate (0-10%) */
|
|
27
|
+
taxRate?: number;
|
|
28
|
+
/** Payer wallet address (required - will sign and pay fees) */
|
|
29
|
+
payerAddress: string;
|
|
30
|
+
/** Social links */
|
|
31
|
+
socials?: {
|
|
32
|
+
twitter?: string;
|
|
33
|
+
telegram?: string;
|
|
34
|
+
website?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/** Prepared transaction ready for signing */
|
|
39
|
+
export interface PreparedTransaction {
|
|
40
|
+
/** Base64 encoded serialized transaction */
|
|
41
|
+
transaction: string;
|
|
42
|
+
/** Estimated SOL fee for the transaction */
|
|
43
|
+
estimatedFee: number;
|
|
44
|
+
/** Token mint address that will be created */
|
|
45
|
+
mintAddress: string;
|
|
46
|
+
/** Message to display to user */
|
|
47
|
+
message: string;
|
|
48
|
+
/** Blockhash used (expires after ~60 seconds) */
|
|
49
|
+
blockhash: string;
|
|
50
|
+
/** Last valid block height */
|
|
51
|
+
lastValidBlockHeight: number;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Token information returned from API */
|
|
55
|
+
export interface TokenInfo {
|
|
56
|
+
/** Token mint address */
|
|
57
|
+
mintAddress: string;
|
|
58
|
+
/** Token name */
|
|
59
|
+
name: string;
|
|
60
|
+
/** Token symbol */
|
|
61
|
+
symbol: string;
|
|
62
|
+
/** Token description */
|
|
63
|
+
description?: string;
|
|
64
|
+
/** Token image URL */
|
|
65
|
+
imageUrl?: string;
|
|
66
|
+
/** Current price in SOL */
|
|
67
|
+
priceInSol: number;
|
|
68
|
+
/** Current price in USD */
|
|
69
|
+
priceInUsd: number;
|
|
70
|
+
/** Market cap in USD */
|
|
71
|
+
marketCapUsd: number;
|
|
72
|
+
/** Graduation progress (0-100) */
|
|
73
|
+
progress: number;
|
|
74
|
+
/** Whether token has graduated to Raydium */
|
|
75
|
+
isGraduated: boolean;
|
|
76
|
+
/** Transfer tax rate */
|
|
77
|
+
taxRate: number;
|
|
78
|
+
/** Creator wallet address */
|
|
79
|
+
creator: string;
|
|
80
|
+
/** Bonding curve PDA */
|
|
81
|
+
bondingCurvePda: string;
|
|
82
|
+
/** Total supply */
|
|
83
|
+
totalSupply: string;
|
|
84
|
+
/** Created at timestamp */
|
|
85
|
+
createdAt: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Fee claiming result */
|
|
89
|
+
export interface ClaimFeesResult {
|
|
90
|
+
/** Transaction signature */
|
|
91
|
+
signature: string;
|
|
92
|
+
/** Amount claimed in tokens */
|
|
93
|
+
amountClaimed: string;
|
|
94
|
+
/** SOL value of claimed fees */
|
|
95
|
+
valueInSol: number;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Submit signed transaction result */
|
|
99
|
+
export interface SubmitResult {
|
|
100
|
+
/** Whether submission was successful */
|
|
101
|
+
success: boolean;
|
|
102
|
+
/** Transaction signature */
|
|
103
|
+
signature?: string;
|
|
104
|
+
/** Token info if deployment confirmed */
|
|
105
|
+
token?: TokenInfo;
|
|
106
|
+
/** Error message if failed */
|
|
107
|
+
error?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** API response wrapper */
|
|
111
|
+
export interface ApiResponse<T> {
|
|
112
|
+
success: boolean;
|
|
113
|
+
data?: T;
|
|
114
|
+
error?: string;
|
|
115
|
+
message?: string;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Rate limit information */
|
|
119
|
+
export interface RateLimitInfo {
|
|
120
|
+
/** Remaining requests in current window */
|
|
121
|
+
remaining: number;
|
|
122
|
+
/** Total limit for current tier */
|
|
123
|
+
limit: number;
|
|
124
|
+
/** Reset timestamp (Unix ms) */
|
|
125
|
+
reset: number;
|
|
126
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"lib": [
|
|
6
|
+
"ES2020",
|
|
7
|
+
"DOM"
|
|
8
|
+
],
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"strict": true,
|
|
11
|
+
"noImplicitAny": true,
|
|
12
|
+
"strictNullChecks": true,
|
|
13
|
+
"noImplicitThis": true,
|
|
14
|
+
"alwaysStrict": true,
|
|
15
|
+
"noUnusedLocals": false,
|
|
16
|
+
"noUnusedParameters": false,
|
|
17
|
+
"noImplicitReturns": true,
|
|
18
|
+
"noFallthroughCasesInSwitch": false,
|
|
19
|
+
"moduleResolution": "node",
|
|
20
|
+
"esModuleInterop": true,
|
|
21
|
+
"outDir": "./dist",
|
|
22
|
+
"rootDir": "./src",
|
|
23
|
+
"skipLibCheck": true,
|
|
24
|
+
"forceConsistentCasingInFileNames": true
|
|
25
|
+
},
|
|
26
|
+
"include": [
|
|
27
|
+
"src/**/*"
|
|
28
|
+
],
|
|
29
|
+
"exclude": [
|
|
30
|
+
"node_modules",
|
|
31
|
+
"dist",
|
|
32
|
+
"examples"
|
|
33
|
+
]
|
|
34
|
+
}
|