four-flap-meme-sdk 1.5.55 → 1.5.56
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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/sol/constants.d.ts +150 -0
- package/dist/sol/constants.js +188 -0
- package/dist/sol/dex/blockrazor/client.d.ts +51 -0
- package/dist/sol/dex/blockrazor/client.js +96 -0
- package/dist/sol/dex/blockrazor/constants.d.ts +34 -0
- package/dist/sol/dex/blockrazor/constants.js +55 -0
- package/dist/sol/dex/blockrazor/geyser.d.ts +128 -0
- package/dist/sol/dex/blockrazor/geyser.js +530 -0
- package/dist/sol/dex/blockrazor/index.d.ts +18 -0
- package/dist/sol/dex/blockrazor/index.js +23 -0
- package/dist/sol/dex/blockrazor/send.d.ts +135 -0
- package/dist/sol/dex/blockrazor/send.js +254 -0
- package/dist/sol/dex/blockrazor/types.d.ts +191 -0
- package/dist/sol/dex/blockrazor/types.js +5 -0
- package/dist/sol/dex/index.d.ts +10 -0
- package/dist/sol/dex/index.js +16 -0
- package/dist/sol/dex/jup/client.d.ts +33 -0
- package/dist/sol/dex/jup/client.js +110 -0
- package/dist/sol/dex/jup/index.d.ts +16 -0
- package/dist/sol/dex/jup/index.js +148 -0
- package/dist/sol/dex/jup/legacy.d.ts +623 -0
- package/dist/sol/dex/jup/legacy.js +416 -0
- package/dist/sol/dex/jup/lend.d.ts +640 -0
- package/dist/sol/dex/jup/lend.js +603 -0
- package/dist/sol/dex/jup/portfolio.d.ts +362 -0
- package/dist/sol/dex/jup/portfolio.js +367 -0
- package/dist/sol/dex/jup/price.d.ts +173 -0
- package/dist/sol/dex/jup/price.js +220 -0
- package/dist/sol/dex/jup/recurring.d.ts +437 -0
- package/dist/sol/dex/jup/recurring.js +320 -0
- package/dist/sol/dex/jup/send.d.ts +282 -0
- package/dist/sol/dex/jup/send.js +295 -0
- package/dist/sol/dex/jup/studio.d.ts +457 -0
- package/dist/sol/dex/jup/studio.js +488 -0
- package/dist/sol/dex/jup/tokens.d.ts +767 -0
- package/dist/sol/dex/jup/tokens.js +697 -0
- package/dist/sol/dex/jup/trigger.d.ts +511 -0
- package/dist/sol/dex/jup/trigger.js +397 -0
- package/dist/sol/dex/jup/types.d.ts +433 -0
- package/dist/sol/dex/jup/types.js +5 -0
- package/dist/sol/dex/jup/ultra.d.ts +646 -0
- package/dist/sol/dex/jup/ultra.js +853 -0
- package/dist/sol/dex/meteora/client.d.ts +76 -0
- package/dist/sol/dex/meteora/client.js +219 -0
- package/dist/sol/dex/meteora/damm-v1-bundle.d.ts +61 -0
- package/dist/sol/dex/meteora/damm-v1-bundle.js +112 -0
- package/dist/sol/dex/meteora/damm-v1.d.ts +118 -0
- package/dist/sol/dex/meteora/damm-v1.js +315 -0
- package/dist/sol/dex/meteora/damm-v2-bundle.d.ts +82 -0
- package/dist/sol/dex/meteora/damm-v2-bundle.js +242 -0
- package/dist/sol/dex/meteora/damm-v2.d.ts +172 -0
- package/dist/sol/dex/meteora/damm-v2.js +632 -0
- package/dist/sol/dex/meteora/dbc-bundle.d.ts +123 -0
- package/dist/sol/dex/meteora/dbc-bundle.js +304 -0
- package/dist/sol/dex/meteora/dbc.d.ts +192 -0
- package/dist/sol/dex/meteora/dbc.js +619 -0
- package/dist/sol/dex/meteora/dlmm-bundle.d.ts +39 -0
- package/dist/sol/dex/meteora/dlmm-bundle.js +189 -0
- package/dist/sol/dex/meteora/dlmm.d.ts +157 -0
- package/dist/sol/dex/meteora/dlmm.js +671 -0
- package/dist/sol/dex/meteora/index.d.ts +25 -0
- package/dist/sol/dex/meteora/index.js +65 -0
- package/dist/sol/dex/meteora/types.d.ts +787 -0
- package/dist/sol/dex/meteora/types.js +110 -0
- package/dist/sol/dex/orca/index.d.ts +10 -0
- package/dist/sol/dex/orca/index.js +16 -0
- package/dist/sol/dex/orca/orca-bundle.d.ts +41 -0
- package/dist/sol/dex/orca/orca-bundle.js +173 -0
- package/dist/sol/dex/orca/orca.d.ts +65 -0
- package/dist/sol/dex/orca/orca.js +474 -0
- package/dist/sol/dex/orca/types.d.ts +263 -0
- package/dist/sol/dex/orca/types.js +38 -0
- package/dist/sol/dex/orca/wavebreak-bundle.d.ts +34 -0
- package/dist/sol/dex/orca/wavebreak-bundle.js +198 -0
- package/dist/sol/dex/orca/wavebreak-types.d.ts +227 -0
- package/dist/sol/dex/orca/wavebreak-types.js +23 -0
- package/dist/sol/dex/orca/wavebreak.d.ts +78 -0
- package/dist/sol/dex/orca/wavebreak.js +497 -0
- package/dist/sol/dex/pump/index.d.ts +9 -0
- package/dist/sol/dex/pump/index.js +14 -0
- package/dist/sol/dex/pump/pump-bundle.d.ts +92 -0
- package/dist/sol/dex/pump/pump-bundle.js +383 -0
- package/dist/sol/dex/pump/pump-swap-bundle.d.ts +103 -0
- package/dist/sol/dex/pump/pump-swap-bundle.js +380 -0
- package/dist/sol/dex/pump/pump-swap.d.ts +46 -0
- package/dist/sol/dex/pump/pump-swap.js +199 -0
- package/dist/sol/dex/pump/pump.d.ts +35 -0
- package/dist/sol/dex/pump/pump.js +352 -0
- package/dist/sol/dex/pump/types.d.ts +215 -0
- package/dist/sol/dex/pump/types.js +5 -0
- package/dist/sol/dex/raydium/index.d.ts +8 -0
- package/dist/sol/dex/raydium/index.js +12 -0
- package/dist/sol/dex/raydium/launchlab.d.ts +68 -0
- package/dist/sol/dex/raydium/launchlab.js +210 -0
- package/dist/sol/dex/raydium/raydium-bundle.d.ts +64 -0
- package/dist/sol/dex/raydium/raydium-bundle.js +324 -0
- package/dist/sol/dex/raydium/raydium.d.ts +40 -0
- package/dist/sol/dex/raydium/raydium.js +366 -0
- package/dist/sol/dex/raydium/types.d.ts +240 -0
- package/dist/sol/dex/raydium/types.js +5 -0
- package/dist/sol/index.d.ts +11 -0
- package/dist/sol/index.js +18 -0
- package/dist/sol/jito/bundle.d.ts +90 -0
- package/dist/sol/jito/bundle.js +263 -0
- package/dist/sol/jito/index.d.ts +7 -0
- package/dist/sol/jito/index.js +7 -0
- package/dist/sol/jito/tip.d.ts +51 -0
- package/dist/sol/jito/tip.js +83 -0
- package/dist/sol/jito/types.d.ts +100 -0
- package/dist/sol/jito/types.js +5 -0
- package/dist/sol/nozomi/client.d.ts +63 -0
- package/dist/sol/nozomi/client.js +222 -0
- package/dist/sol/nozomi/index.d.ts +8 -0
- package/dist/sol/nozomi/index.js +8 -0
- package/dist/sol/nozomi/tip.d.ts +50 -0
- package/dist/sol/nozomi/tip.js +80 -0
- package/dist/sol/nozomi/types.d.ts +96 -0
- package/dist/sol/nozomi/types.js +5 -0
- package/dist/sol/token/create-complete.d.ts +115 -0
- package/dist/sol/token/create-complete.js +235 -0
- package/dist/sol/token/create-token.d.ts +57 -0
- package/dist/sol/token/create-token.js +230 -0
- package/dist/sol/token/index.d.ts +9 -0
- package/dist/sol/token/index.js +14 -0
- package/dist/sol/token/metadata-upload.d.ts +86 -0
- package/dist/sol/token/metadata-upload.js +173 -0
- package/dist/sol/token/metadata.d.ts +92 -0
- package/dist/sol/token/metadata.js +274 -0
- package/dist/sol/token/types.d.ts +153 -0
- package/dist/sol/token/types.js +5 -0
- package/dist/sol/types.d.ts +176 -0
- package/dist/sol/types.js +7 -0
- package/dist/sol/utils/balance.d.ts +160 -0
- package/dist/sol/utils/balance.js +638 -0
- package/dist/sol/utils/connection.d.ts +78 -0
- package/dist/sol/utils/connection.js +168 -0
- package/dist/sol/utils/index.d.ts +9 -0
- package/dist/sol/utils/index.js +9 -0
- package/dist/sol/utils/lp-inspect.d.ts +75 -0
- package/dist/sol/utils/lp-inspect.js +235 -0
- package/dist/sol/utils/transfer.d.ts +196 -0
- package/dist/sol/utils/transfer.js +307 -0
- package/dist/sol/utils/wallet.d.ts +107 -0
- package/dist/sol/utils/wallet.js +210 -0
- package/package.json +44 -5
- package/README.zh-CN.pdf +0 -0
- package/dist/flap/portal-bundle-merkle/encryption.d.ts +0 -16
- package/dist/flap/portal-bundle-merkle/encryption.js +0 -146
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 完整代币创建流程
|
|
3
|
+
* 包括:上传元数据 → 创建 Mint → 创建 Metadata → Mint 初始供应
|
|
4
|
+
* @module sol/token/create-complete
|
|
5
|
+
*/
|
|
6
|
+
import { TOKEN_2022_PROGRAM_ID, TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, } from '@solana/spl-token';
|
|
7
|
+
import { signCreateTokenTransaction } from './create-token.js';
|
|
8
|
+
import { signCreateMetadataTransaction } from './metadata.js';
|
|
9
|
+
import { uploadTokenMetadata, uploadTokenMetadataFromFile, cidToUri } from './metadata-upload.js';
|
|
10
|
+
/**
|
|
11
|
+
* 创建完整代币(上传元数据 + 创建 Mint + 创建 Metadata + Mint 初始供应)
|
|
12
|
+
*
|
|
13
|
+
* 流程:
|
|
14
|
+
* 1. 上传图片和元数据到 IPFS(使用 Flap 官方接口)
|
|
15
|
+
* 2. 创建 Mint 账户 + Mint 初始供应量
|
|
16
|
+
* 3. 创建 Metaplex Metadata 账户
|
|
17
|
+
*
|
|
18
|
+
* @param connection Solana 连接
|
|
19
|
+
* @param params 创建参数
|
|
20
|
+
*/
|
|
21
|
+
export async function createTokenComplete(connection, params) {
|
|
22
|
+
try {
|
|
23
|
+
const { name, symbol, description, decimals, initialSupply, imageBuffer, imageFile, metadataCid, creator, mintAuthority = creator.publicKey, freezeAuthority = creator.publicKey, tokenStandard = 'TOKEN_2022', social, } = params;
|
|
24
|
+
// ==================== Step 1: 上传元数据 ====================
|
|
25
|
+
let metadataUri;
|
|
26
|
+
if (metadataCid) {
|
|
27
|
+
// 已有元数据 CID
|
|
28
|
+
metadataUri = cidToUri(metadataCid);
|
|
29
|
+
}
|
|
30
|
+
else if (imageBuffer) {
|
|
31
|
+
// 上传图片和元数据(使用 Flap 官方 IPFS 接口)
|
|
32
|
+
const uploadResult = await uploadTokenMetadata(imageBuffer, {
|
|
33
|
+
name,
|
|
34
|
+
symbol,
|
|
35
|
+
description,
|
|
36
|
+
creator: creator.publicKey.toBase58(),
|
|
37
|
+
telegram: social?.telegram,
|
|
38
|
+
twitter: social?.twitter,
|
|
39
|
+
website: social?.website,
|
|
40
|
+
});
|
|
41
|
+
if (!uploadResult.success) {
|
|
42
|
+
return {
|
|
43
|
+
success: false,
|
|
44
|
+
error: `IPFS upload failed: ${uploadResult.error}`,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
metadataUri = uploadResult.uri;
|
|
48
|
+
}
|
|
49
|
+
else if (imageFile) {
|
|
50
|
+
// 从 File 对象上传(浏览器环境)
|
|
51
|
+
const uploadResult = await uploadTokenMetadataFromFile(imageFile, {
|
|
52
|
+
name,
|
|
53
|
+
symbol,
|
|
54
|
+
description,
|
|
55
|
+
creator: creator.publicKey.toBase58(),
|
|
56
|
+
telegram: social?.telegram,
|
|
57
|
+
twitter: social?.twitter,
|
|
58
|
+
website: social?.website,
|
|
59
|
+
});
|
|
60
|
+
if (!uploadResult.success) {
|
|
61
|
+
return {
|
|
62
|
+
success: false,
|
|
63
|
+
error: `IPFS upload failed: ${uploadResult.error}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
metadataUri = uploadResult.uri;
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Either metadataCid, imageBuffer, or imageFile is required',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
// ==================== Step 2: 创建 Mint + Mint To ====================
|
|
75
|
+
const createTokenResult = await signCreateTokenTransaction(connection, {
|
|
76
|
+
creator,
|
|
77
|
+
decimals,
|
|
78
|
+
initialSupply,
|
|
79
|
+
mintAuthority,
|
|
80
|
+
freezeAuthority,
|
|
81
|
+
tokenStandard,
|
|
82
|
+
});
|
|
83
|
+
const mintKeypair = createTokenResult.mintKeypair;
|
|
84
|
+
const mintAddress = createTokenResult.mintAddress;
|
|
85
|
+
// ==================== Step 3: 创建 Metadata ====================
|
|
86
|
+
const metadataResult = await signCreateMetadataTransaction(connection, {
|
|
87
|
+
mint: mintKeypair.publicKey,
|
|
88
|
+
mintAuthority: creator,
|
|
89
|
+
payer: creator,
|
|
90
|
+
name,
|
|
91
|
+
symbol,
|
|
92
|
+
uri: metadataUri,
|
|
93
|
+
sellerFeeBasisPoints: 0,
|
|
94
|
+
creators: [
|
|
95
|
+
{
|
|
96
|
+
address: creator.publicKey,
|
|
97
|
+
verified: true,
|
|
98
|
+
share: 100,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isMutable: true,
|
|
102
|
+
});
|
|
103
|
+
if (!metadataResult.success) {
|
|
104
|
+
return {
|
|
105
|
+
success: false,
|
|
106
|
+
error: `Metadata creation failed: ${metadataResult.error}`,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// ==================== 获取 ATA 地址 ====================
|
|
110
|
+
const programId = tokenStandard === 'TOKEN_2022' ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
|
|
111
|
+
const creatorAta = getAssociatedTokenAddressSync(mintKeypair.publicKey, creator.publicKey, false, programId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
112
|
+
// ==================== 组装结果 ====================
|
|
113
|
+
return {
|
|
114
|
+
success: true,
|
|
115
|
+
mint: mintAddress,
|
|
116
|
+
mintKeypair,
|
|
117
|
+
metadataAddress: metadataResult.metadataAddress,
|
|
118
|
+
metadataUri,
|
|
119
|
+
creatorAta: creatorAta.toBase58(),
|
|
120
|
+
signedTransactions: [
|
|
121
|
+
{
|
|
122
|
+
data: createTokenResult.signedTransaction.data,
|
|
123
|
+
signature: createTokenResult.signedTransaction.signature,
|
|
124
|
+
description: 'Create Mint + Mint Initial Supply',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
data: metadataResult.signedTransaction.data,
|
|
128
|
+
signature: metadataResult.signedTransaction.signature,
|
|
129
|
+
description: 'Create Metadata',
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
recentBlockhash: createTokenResult.recentBlockhash,
|
|
133
|
+
lastValidBlockHeight: createTokenResult.lastValidBlockHeight,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return {
|
|
138
|
+
success: false,
|
|
139
|
+
error: error.message,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* 创建代币(不上传元数据,使用已有 URI)
|
|
145
|
+
* 适用于元数据已经上传的情况
|
|
146
|
+
*/
|
|
147
|
+
export async function createTokenWithUri(connection, params) {
|
|
148
|
+
try {
|
|
149
|
+
const { name, symbol, metadataUri, decimals, initialSupply, creator, mintAuthority = creator.publicKey, freezeAuthority = creator.publicKey, tokenStandard = 'TOKEN_2022', } = params;
|
|
150
|
+
// 创建 Mint + Mint To
|
|
151
|
+
const createTokenResult = await signCreateTokenTransaction(connection, {
|
|
152
|
+
creator,
|
|
153
|
+
decimals,
|
|
154
|
+
initialSupply,
|
|
155
|
+
mintAuthority,
|
|
156
|
+
freezeAuthority,
|
|
157
|
+
tokenStandard,
|
|
158
|
+
});
|
|
159
|
+
const mintKeypair = createTokenResult.mintKeypair;
|
|
160
|
+
const mintAddress = createTokenResult.mintAddress;
|
|
161
|
+
// 创建 Metadata
|
|
162
|
+
const metadataResult = await signCreateMetadataTransaction(connection, {
|
|
163
|
+
mint: mintKeypair.publicKey,
|
|
164
|
+
mintAuthority: creator,
|
|
165
|
+
payer: creator,
|
|
166
|
+
name,
|
|
167
|
+
symbol,
|
|
168
|
+
uri: metadataUri,
|
|
169
|
+
sellerFeeBasisPoints: 0,
|
|
170
|
+
creators: [
|
|
171
|
+
{
|
|
172
|
+
address: creator.publicKey,
|
|
173
|
+
verified: true,
|
|
174
|
+
share: 100,
|
|
175
|
+
},
|
|
176
|
+
],
|
|
177
|
+
isMutable: true,
|
|
178
|
+
});
|
|
179
|
+
if (!metadataResult.success) {
|
|
180
|
+
return {
|
|
181
|
+
success: false,
|
|
182
|
+
error: `Metadata creation failed: ${metadataResult.error}`,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
// 获取 ATA 地址
|
|
186
|
+
const programId = tokenStandard === 'TOKEN_2022' ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
|
|
187
|
+
const creatorAta = getAssociatedTokenAddressSync(mintKeypair.publicKey, creator.publicKey, false, programId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
188
|
+
return {
|
|
189
|
+
success: true,
|
|
190
|
+
mint: mintAddress,
|
|
191
|
+
mintKeypair,
|
|
192
|
+
metadataAddress: metadataResult.metadataAddress,
|
|
193
|
+
metadataUri,
|
|
194
|
+
creatorAta: creatorAta.toBase58(),
|
|
195
|
+
signedTransactions: [
|
|
196
|
+
{
|
|
197
|
+
data: createTokenResult.signedTransaction.data,
|
|
198
|
+
signature: createTokenResult.signedTransaction.signature,
|
|
199
|
+
description: 'Create Mint + Mint Initial Supply',
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
data: metadataResult.signedTransaction.data,
|
|
203
|
+
signature: metadataResult.signedTransaction.signature,
|
|
204
|
+
description: 'Create Metadata',
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
recentBlockhash: createTokenResult.recentBlockhash,
|
|
208
|
+
lastValidBlockHeight: createTokenResult.lastValidBlockHeight,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
return {
|
|
213
|
+
success: false,
|
|
214
|
+
error: error.message,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* 将创建结果转换为后端 API 格式
|
|
220
|
+
*/
|
|
221
|
+
export function toBackendCreateTokenRequest(result) {
|
|
222
|
+
if (!result.success || !result.signedTransactions) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
mint: result.mint,
|
|
227
|
+
metadataAddress: result.metadataAddress,
|
|
228
|
+
metadataUri: result.metadataUri,
|
|
229
|
+
creatorAta: result.creatorAta,
|
|
230
|
+
transactions: result.signedTransactions,
|
|
231
|
+
recentBlockhash: result.recentBlockhash,
|
|
232
|
+
lastValidBlockHeight: result.lastValidBlockHeight,
|
|
233
|
+
timestamp: Date.now(),
|
|
234
|
+
};
|
|
235
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-2022 / SPL Token 创建
|
|
3
|
+
* SDK 只负责构建和签名交易,提交到后端广播
|
|
4
|
+
* @module sol/token/create-token
|
|
5
|
+
*/
|
|
6
|
+
import { Connection, Keypair, PublicKey } from '@solana/web3.js';
|
|
7
|
+
import type { TokenStandard, Token2022Extensions, MintToParams, MintToResult } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* 构建并签名创建代币交易(不含 Metaplex 元数据)
|
|
10
|
+
* @param connection Solana 连接
|
|
11
|
+
* @param params 创建参数
|
|
12
|
+
* @returns 签名后的交易数据
|
|
13
|
+
*/
|
|
14
|
+
export declare function signCreateTokenTransaction(connection: Connection, params: {
|
|
15
|
+
creator: Keypair;
|
|
16
|
+
decimals: number;
|
|
17
|
+
initialSupply: bigint;
|
|
18
|
+
mintAuthority?: PublicKey;
|
|
19
|
+
freezeAuthority?: PublicKey | null;
|
|
20
|
+
tokenStandard?: TokenStandard;
|
|
21
|
+
extensions?: Token2022Extensions;
|
|
22
|
+
}): Promise<{
|
|
23
|
+
mintKeypair: Keypair;
|
|
24
|
+
mintAddress: string;
|
|
25
|
+
signedTransaction: {
|
|
26
|
+
data: string;
|
|
27
|
+
signature: string;
|
|
28
|
+
};
|
|
29
|
+
recentBlockhash: string;
|
|
30
|
+
lastValidBlockHeight: number;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* 构建并签名 Mint To 交易
|
|
34
|
+
* @param connection Solana 连接
|
|
35
|
+
* @param params Mint To 参数
|
|
36
|
+
*/
|
|
37
|
+
export declare function signMintToTransaction(connection: Connection, params: MintToParams): Promise<MintToResult>;
|
|
38
|
+
/**
|
|
39
|
+
* 批量 Mint To(多个地址)
|
|
40
|
+
*/
|
|
41
|
+
export declare function signBatchMintToTransaction(connection: Connection, params: {
|
|
42
|
+
mint: string;
|
|
43
|
+
mintAuthority: Keypair;
|
|
44
|
+
distributions: Array<{
|
|
45
|
+
destination: string;
|
|
46
|
+
amount: bigint;
|
|
47
|
+
}>;
|
|
48
|
+
tokenStandard?: TokenStandard;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
success: boolean;
|
|
51
|
+
signedTransaction?: {
|
|
52
|
+
data: string;
|
|
53
|
+
signature: string;
|
|
54
|
+
};
|
|
55
|
+
ataAddresses?: string[];
|
|
56
|
+
error?: string;
|
|
57
|
+
}>;
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token-2022 / SPL Token 创建
|
|
3
|
+
* SDK 只负责构建和签名交易,提交到后端广播
|
|
4
|
+
* @module sol/token/create-token
|
|
5
|
+
*/
|
|
6
|
+
import { Keypair, PublicKey, SystemProgram, Transaction, } from '@solana/web3.js';
|
|
7
|
+
import { TOKEN_PROGRAM_ID, TOKEN_2022_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID, createInitializeMintInstruction, createAssociatedTokenAccountInstruction, createMintToInstruction, getAssociatedTokenAddressSync, getMintLen, ExtensionType, createInitializeTransferFeeConfigInstruction, createInitializeNonTransferableMintInstruction, createInitializePermanentDelegateInstruction, } from '@solana/spl-token';
|
|
8
|
+
import { ACCOUNT_SIZE } from '../constants.js';
|
|
9
|
+
/**
|
|
10
|
+
* 获取 Token Program ID
|
|
11
|
+
*/
|
|
12
|
+
function getTokenProgramId(standard = 'TOKEN_2022') {
|
|
13
|
+
return standard === 'TOKEN_2022' ? TOKEN_2022_PROGRAM_ID : TOKEN_PROGRAM_ID;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 计算 Mint 账户大小(包括扩展)
|
|
17
|
+
*/
|
|
18
|
+
function calculateMintSize(extensions) {
|
|
19
|
+
if (!extensions) {
|
|
20
|
+
return getMintLen([]);
|
|
21
|
+
}
|
|
22
|
+
const extensionTypes = [];
|
|
23
|
+
if (extensions.transferFee) {
|
|
24
|
+
extensionTypes.push(ExtensionType.TransferFeeConfig);
|
|
25
|
+
}
|
|
26
|
+
if (extensions.nonTransferable) {
|
|
27
|
+
extensionTypes.push(ExtensionType.NonTransferable);
|
|
28
|
+
}
|
|
29
|
+
if (extensions.permanentDelegate) {
|
|
30
|
+
extensionTypes.push(ExtensionType.PermanentDelegate);
|
|
31
|
+
}
|
|
32
|
+
return getMintLen(extensionTypes);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 构建创建 Mint 账户的指令
|
|
36
|
+
*/
|
|
37
|
+
async function buildCreateMintInstructions(connection, payer, mintKeypair, mintAuthority, freezeAuthority, decimals, tokenStandard, extensions) {
|
|
38
|
+
const instructions = [];
|
|
39
|
+
const programId = getTokenProgramId(tokenStandard);
|
|
40
|
+
// 计算账户大小和租金
|
|
41
|
+
const mintSize = tokenStandard === 'TOKEN_2022'
|
|
42
|
+
? calculateMintSize(extensions)
|
|
43
|
+
: ACCOUNT_SIZE.MINT;
|
|
44
|
+
const lamports = await connection.getMinimumBalanceForRentExemption(mintSize);
|
|
45
|
+
// 1. 创建账户
|
|
46
|
+
instructions.push(SystemProgram.createAccount({
|
|
47
|
+
fromPubkey: payer,
|
|
48
|
+
newAccountPubkey: mintKeypair.publicKey,
|
|
49
|
+
space: mintSize,
|
|
50
|
+
lamports,
|
|
51
|
+
programId,
|
|
52
|
+
}));
|
|
53
|
+
// 2. 初始化扩展(Token-2022 only,必须在 InitializeMint 之前)
|
|
54
|
+
if (tokenStandard === 'TOKEN_2022' && extensions) {
|
|
55
|
+
// 转账手续费
|
|
56
|
+
if (extensions.transferFee) {
|
|
57
|
+
instructions.push(createInitializeTransferFeeConfigInstruction(mintKeypair.publicKey, mintAuthority, // transferFeeConfigAuthority
|
|
58
|
+
mintAuthority, // withdrawWithheldAuthority
|
|
59
|
+
extensions.transferFee.feeBasisPoints, extensions.transferFee.maxFee, programId));
|
|
60
|
+
}
|
|
61
|
+
// 不可转让
|
|
62
|
+
if (extensions.nonTransferable) {
|
|
63
|
+
instructions.push(createInitializeNonTransferableMintInstruction(mintKeypair.publicKey, programId));
|
|
64
|
+
}
|
|
65
|
+
// 永久代理
|
|
66
|
+
if (extensions.permanentDelegate) {
|
|
67
|
+
instructions.push(createInitializePermanentDelegateInstruction(mintKeypair.publicKey, extensions.permanentDelegate, programId));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// 3. 初始化 Mint
|
|
71
|
+
instructions.push(createInitializeMintInstruction(mintKeypair.publicKey, decimals, mintAuthority, freezeAuthority, programId));
|
|
72
|
+
return instructions;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* 构建创建 ATA 和 Mint To 的指令
|
|
76
|
+
*/
|
|
77
|
+
function buildMintToInstructions(mint, destination, mintAuthority, amount, tokenStandard, payer) {
|
|
78
|
+
const instructions = [];
|
|
79
|
+
const programId = getTokenProgramId(tokenStandard);
|
|
80
|
+
// 获取 ATA 地址
|
|
81
|
+
const ata = getAssociatedTokenAddressSync(mint, destination, false, programId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
82
|
+
// 1. 创建 ATA(如果不存在)
|
|
83
|
+
instructions.push(createAssociatedTokenAccountInstruction(payer, ata, destination, mint, programId, ASSOCIATED_TOKEN_PROGRAM_ID));
|
|
84
|
+
// 2. Mint To
|
|
85
|
+
instructions.push(createMintToInstruction(mint, ata, mintAuthority, amount, [], programId));
|
|
86
|
+
return instructions;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* 构建并签名创建代币交易(不含 Metaplex 元数据)
|
|
90
|
+
* @param connection Solana 连接
|
|
91
|
+
* @param params 创建参数
|
|
92
|
+
* @returns 签名后的交易数据
|
|
93
|
+
*/
|
|
94
|
+
export async function signCreateTokenTransaction(connection, params) {
|
|
95
|
+
const { creator, decimals, initialSupply, mintAuthority = creator.publicKey, freezeAuthority = creator.publicKey, tokenStandard = 'TOKEN_2022', extensions, } = params;
|
|
96
|
+
// 生成 Mint Keypair
|
|
97
|
+
const mintKeypair = Keypair.generate();
|
|
98
|
+
const programId = getTokenProgramId(tokenStandard);
|
|
99
|
+
// 获取 blockhash
|
|
100
|
+
const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash('finalized');
|
|
101
|
+
// 构建指令
|
|
102
|
+
const instructions = [];
|
|
103
|
+
// 1. 创建 Mint
|
|
104
|
+
const createMintIxs = await buildCreateMintInstructions(connection, creator.publicKey, mintKeypair, mintAuthority, freezeAuthority, decimals, tokenStandard, extensions);
|
|
105
|
+
instructions.push(...createMintIxs);
|
|
106
|
+
// 2. 创建 ATA 并 Mint 初始供应量
|
|
107
|
+
if (initialSupply > 0) {
|
|
108
|
+
const mintToIxs = buildMintToInstructions(mintKeypair.publicKey, creator.publicKey, // mint 到创建者
|
|
109
|
+
mintAuthority, initialSupply * BigInt(10 ** decimals), tokenStandard, creator.publicKey);
|
|
110
|
+
instructions.push(...mintToIxs);
|
|
111
|
+
}
|
|
112
|
+
// 构建交易
|
|
113
|
+
const transaction = new Transaction();
|
|
114
|
+
transaction.add(...instructions);
|
|
115
|
+
transaction.recentBlockhash = blockhash;
|
|
116
|
+
transaction.feePayer = creator.publicKey;
|
|
117
|
+
// 签名(需要 creator 和 mintKeypair)
|
|
118
|
+
transaction.sign(creator, mintKeypair);
|
|
119
|
+
const serialized = transaction.serialize();
|
|
120
|
+
return {
|
|
121
|
+
mintKeypair,
|
|
122
|
+
mintAddress: mintKeypair.publicKey.toBase58(),
|
|
123
|
+
signedTransaction: {
|
|
124
|
+
data: Buffer.from(serialized).toString('base64'),
|
|
125
|
+
signature: transaction.signature ? Buffer.from(transaction.signature).toString('base64') : '',
|
|
126
|
+
},
|
|
127
|
+
recentBlockhash: blockhash,
|
|
128
|
+
lastValidBlockHeight,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* 构建并签名 Mint To 交易
|
|
133
|
+
* @param connection Solana 连接
|
|
134
|
+
* @param params Mint To 参数
|
|
135
|
+
*/
|
|
136
|
+
export async function signMintToTransaction(connection, params) {
|
|
137
|
+
try {
|
|
138
|
+
const { mint, destination, amount, mintAuthority, tokenStandard = 'TOKEN_2022', } = params;
|
|
139
|
+
const programId = getTokenProgramId(tokenStandard);
|
|
140
|
+
const mintPubkey = new PublicKey(mint);
|
|
141
|
+
const destinationPubkey = new PublicKey(destination);
|
|
142
|
+
// 获取 ATA 地址
|
|
143
|
+
const ata = getAssociatedTokenAddressSync(mintPubkey, destinationPubkey, false, programId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
144
|
+
const { blockhash } = await connection.getLatestBlockhash('finalized');
|
|
145
|
+
// 构建交易
|
|
146
|
+
const transaction = new Transaction();
|
|
147
|
+
// 检查 ATA 是否存在
|
|
148
|
+
const ataInfo = await connection.getAccountInfo(ata);
|
|
149
|
+
if (!ataInfo) {
|
|
150
|
+
// 创建 ATA
|
|
151
|
+
transaction.add(createAssociatedTokenAccountInstruction(mintAuthority.publicKey, ata, destinationPubkey, mintPubkey, programId, ASSOCIATED_TOKEN_PROGRAM_ID));
|
|
152
|
+
}
|
|
153
|
+
// Mint To
|
|
154
|
+
transaction.add(createMintToInstruction(mintPubkey, ata, mintAuthority.publicKey, amount, [], programId));
|
|
155
|
+
transaction.recentBlockhash = blockhash;
|
|
156
|
+
transaction.feePayer = mintAuthority.publicKey;
|
|
157
|
+
transaction.sign(mintAuthority);
|
|
158
|
+
const serialized = transaction.serialize();
|
|
159
|
+
return {
|
|
160
|
+
success: true,
|
|
161
|
+
ataAddress: ata.toBase58(),
|
|
162
|
+
signedTransaction: {
|
|
163
|
+
data: Buffer.from(serialized).toString('base64'),
|
|
164
|
+
signature: transaction.signature ? Buffer.from(transaction.signature).toString('base64') : '',
|
|
165
|
+
},
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
return {
|
|
170
|
+
success: false,
|
|
171
|
+
error: error.message,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* 批量 Mint To(多个地址)
|
|
177
|
+
*/
|
|
178
|
+
export async function signBatchMintToTransaction(connection, params) {
|
|
179
|
+
try {
|
|
180
|
+
const { mint, mintAuthority, distributions, tokenStandard = 'TOKEN_2022', } = params;
|
|
181
|
+
if (distributions.length === 0) {
|
|
182
|
+
return { success: false, error: 'No distributions provided' };
|
|
183
|
+
}
|
|
184
|
+
if (distributions.length > 10) {
|
|
185
|
+
return { success: false, error: 'Too many distributions. Max 10 per transaction.' };
|
|
186
|
+
}
|
|
187
|
+
const programId = getTokenProgramId(tokenStandard);
|
|
188
|
+
const mintPubkey = new PublicKey(mint);
|
|
189
|
+
const { blockhash } = await connection.getLatestBlockhash('finalized');
|
|
190
|
+
const transaction = new Transaction();
|
|
191
|
+
const ataAddresses = [];
|
|
192
|
+
// 批量获取 ATA 信息
|
|
193
|
+
const atas = distributions.map(d => {
|
|
194
|
+
const destPubkey = new PublicKey(d.destination);
|
|
195
|
+
return getAssociatedTokenAddressSync(mintPubkey, destPubkey, false, programId, ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
196
|
+
});
|
|
197
|
+
const ataInfos = await connection.getMultipleAccountsInfo(atas);
|
|
198
|
+
for (let i = 0; i < distributions.length; i++) {
|
|
199
|
+
const dist = distributions[i];
|
|
200
|
+
const ata = atas[i];
|
|
201
|
+
const ataInfo = ataInfos[i];
|
|
202
|
+
const destPubkey = new PublicKey(dist.destination);
|
|
203
|
+
ataAddresses.push(ata.toBase58());
|
|
204
|
+
// 创建 ATA(如果不存在)
|
|
205
|
+
if (!ataInfo) {
|
|
206
|
+
transaction.add(createAssociatedTokenAccountInstruction(mintAuthority.publicKey, ata, destPubkey, mintPubkey, programId, ASSOCIATED_TOKEN_PROGRAM_ID));
|
|
207
|
+
}
|
|
208
|
+
// Mint To
|
|
209
|
+
transaction.add(createMintToInstruction(mintPubkey, ata, mintAuthority.publicKey, dist.amount, [], programId));
|
|
210
|
+
}
|
|
211
|
+
transaction.recentBlockhash = blockhash;
|
|
212
|
+
transaction.feePayer = mintAuthority.publicKey;
|
|
213
|
+
transaction.sign(mintAuthority);
|
|
214
|
+
const serialized = transaction.serialize();
|
|
215
|
+
return {
|
|
216
|
+
success: true,
|
|
217
|
+
signedTransaction: {
|
|
218
|
+
data: Buffer.from(serialized).toString('base64'),
|
|
219
|
+
signature: transaction.signature ? Buffer.from(transaction.signature).toString('base64') : '',
|
|
220
|
+
},
|
|
221
|
+
ataAddresses,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
return {
|
|
226
|
+
success: false,
|
|
227
|
+
error: error.message,
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Token 创建模块
|
|
3
|
+
* @module sol/token
|
|
4
|
+
*/
|
|
5
|
+
// 类型导出
|
|
6
|
+
export * from './types.js';
|
|
7
|
+
// 元数据上传
|
|
8
|
+
export * from './metadata-upload.js';
|
|
9
|
+
// 代币创建
|
|
10
|
+
export * from './create-token.js';
|
|
11
|
+
// Metaplex 元数据
|
|
12
|
+
export * from './metadata.js';
|
|
13
|
+
// 完整创建流程
|
|
14
|
+
export * from './create-complete.js';
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 元数据上传(复用 Flap 官方 IPFS 接口)
|
|
3
|
+
* @module sol/token/metadata-upload
|
|
4
|
+
*/
|
|
5
|
+
import type { TokenMetadataInput, TokenMetadataJson } from './types.js';
|
|
6
|
+
/**
|
|
7
|
+
* 上传结果
|
|
8
|
+
*/
|
|
9
|
+
export interface UploadResult {
|
|
10
|
+
success: boolean;
|
|
11
|
+
/** CID(bafkrei... 格式) */
|
|
12
|
+
cid?: string;
|
|
13
|
+
/** 完整 IPFS URI */
|
|
14
|
+
uri?: string;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Flap 元数据输入
|
|
19
|
+
*/
|
|
20
|
+
export interface FlapMetaInput {
|
|
21
|
+
/** 创建者地址 */
|
|
22
|
+
creator?: string;
|
|
23
|
+
/** 描述 */
|
|
24
|
+
description?: string;
|
|
25
|
+
/** Telegram 链接 */
|
|
26
|
+
telegram?: string | null;
|
|
27
|
+
/** Twitter 链接 */
|
|
28
|
+
twitter?: string | null;
|
|
29
|
+
/** 网站链接 */
|
|
30
|
+
website?: string | null;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* 使用 Flap 官方 GraphQL 接口上传文件到 IPFS
|
|
34
|
+
* 同时上传图片和元数据,返回 bafkrei... 格式的 CIDv1
|
|
35
|
+
*
|
|
36
|
+
* @param file 图片文件(File 或 Uint8Array 或 Buffer)
|
|
37
|
+
* @param meta 元数据
|
|
38
|
+
* @returns CID
|
|
39
|
+
*/
|
|
40
|
+
export declare function uploadToFlapIPFS(file: File | Uint8Array | Buffer, meta: FlapMetaInput): Promise<UploadResult>;
|
|
41
|
+
/**
|
|
42
|
+
* 上传图片和元数据到 IPFS(Flap 官方接口)
|
|
43
|
+
* 这是主要的上传方法
|
|
44
|
+
*
|
|
45
|
+
* @param imageBuffer 图片 Buffer
|
|
46
|
+
* @param metadata 代币元数据
|
|
47
|
+
* @returns 上传结果
|
|
48
|
+
*/
|
|
49
|
+
export declare function uploadTokenMetadata(imageBuffer: Buffer | Uint8Array, metadata: {
|
|
50
|
+
name: string;
|
|
51
|
+
symbol: string;
|
|
52
|
+
description: string;
|
|
53
|
+
creator?: string;
|
|
54
|
+
telegram?: string;
|
|
55
|
+
twitter?: string;
|
|
56
|
+
website?: string;
|
|
57
|
+
}): Promise<UploadResult>;
|
|
58
|
+
/**
|
|
59
|
+
* 从 File 对象上传(浏览器环境)
|
|
60
|
+
*/
|
|
61
|
+
export declare function uploadTokenMetadataFromFile(file: File, metadata: {
|
|
62
|
+
name: string;
|
|
63
|
+
symbol: string;
|
|
64
|
+
description: string;
|
|
65
|
+
creator?: string;
|
|
66
|
+
telegram?: string;
|
|
67
|
+
twitter?: string;
|
|
68
|
+
website?: string;
|
|
69
|
+
}): Promise<UploadResult>;
|
|
70
|
+
/**
|
|
71
|
+
* 构建完整的 Metaplex 元数据 JSON
|
|
72
|
+
* 用于已经上传图片后,构建标准的元数据格式
|
|
73
|
+
*/
|
|
74
|
+
export declare function buildMetaplexMetadataJson(metadata: TokenMetadataInput, imageCid: string): TokenMetadataJson;
|
|
75
|
+
/**
|
|
76
|
+
* 构建元数据 JSON(不上传,用于已有图片 URL 的情况)
|
|
77
|
+
*/
|
|
78
|
+
export declare function buildMetadataJson(metadata: TokenMetadataInput): TokenMetadataJson;
|
|
79
|
+
/**
|
|
80
|
+
* CID 转换为 IPFS URI
|
|
81
|
+
*/
|
|
82
|
+
export declare function cidToUri(cid: string): string;
|
|
83
|
+
/**
|
|
84
|
+
* CID 转换为 HTTP 网关 URL
|
|
85
|
+
*/
|
|
86
|
+
export declare function cidToHttpUrl(cid: string, gateway?: string): string;
|