@rialo/spl-token 0.3.0-alpha.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/README.md +522 -0
- package/dist/index.d.mts +1143 -0
- package/dist/index.d.ts +1143 -0
- package/dist/index.js +1383 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1356 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +57 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1383 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var tsCdk = require('@rialo/ts-cdk');
|
|
4
|
+
|
|
5
|
+
// src/client/spl-token-client.ts
|
|
6
|
+
|
|
7
|
+
// src/constants.ts
|
|
8
|
+
var TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
9
|
+
var ASSOCIATED_TOKEN_PROGRAM_ID = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
|
|
10
|
+
var TOKEN_PROGRAM_ID = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
|
|
11
|
+
var MINT_SIZE = 82;
|
|
12
|
+
var TOKEN_ACCOUNT_SIZE = 165;
|
|
13
|
+
var MINT_SUPPLY_OFFSET = 36;
|
|
14
|
+
var MINT_DECIMALS_OFFSET = 44;
|
|
15
|
+
var MINT_IS_INITIALIZED_OFFSET = 45;
|
|
16
|
+
var MINT_FREEZE_AUTHORITY_OFFSET = 46;
|
|
17
|
+
var TOKEN_ACCOUNT_MINT_OFFSET = 0;
|
|
18
|
+
var TOKEN_ACCOUNT_OWNER_OFFSET = 32;
|
|
19
|
+
var TOKEN_ACCOUNT_AMOUNT_OFFSET = 64;
|
|
20
|
+
var TOKEN_ACCOUNT_DELEGATE_OFFSET = 72;
|
|
21
|
+
var TOKEN_ACCOUNT_STATE_OFFSET = 108;
|
|
22
|
+
var TOKEN_ACCOUNT_IS_NATIVE_OFFSET = 109;
|
|
23
|
+
var TOKEN_ACCOUNT_DELEGATED_AMOUNT_OFFSET = 121;
|
|
24
|
+
var TOKEN_ACCOUNT_CLOSE_AUTHORITY_OFFSET = 129;
|
|
25
|
+
var COPTION_SOME = 1;
|
|
26
|
+
var PUBKEY_SIZE = 32;
|
|
27
|
+
var TokenAccountState = /* @__PURE__ */ ((TokenAccountState2) => {
|
|
28
|
+
TokenAccountState2[TokenAccountState2["Uninitialized"] = 0] = "Uninitialized";
|
|
29
|
+
TokenAccountState2[TokenAccountState2["Initialized"] = 1] = "Initialized";
|
|
30
|
+
TokenAccountState2[TokenAccountState2["Frozen"] = 2] = "Frozen";
|
|
31
|
+
return TokenAccountState2;
|
|
32
|
+
})(TokenAccountState || {});
|
|
33
|
+
var ExtensionType = /* @__PURE__ */ ((ExtensionType2) => {
|
|
34
|
+
ExtensionType2[ExtensionType2["Uninitialized"] = 0] = "Uninitialized";
|
|
35
|
+
ExtensionType2[ExtensionType2["TransferFeeConfig"] = 1] = "TransferFeeConfig";
|
|
36
|
+
ExtensionType2[ExtensionType2["TransferFeeAmount"] = 2] = "TransferFeeAmount";
|
|
37
|
+
ExtensionType2[ExtensionType2["MintCloseAuthority"] = 3] = "MintCloseAuthority";
|
|
38
|
+
ExtensionType2[ExtensionType2["ConfidentialTransferMint"] = 4] = "ConfidentialTransferMint";
|
|
39
|
+
ExtensionType2[ExtensionType2["ConfidentialTransferAccount"] = 5] = "ConfidentialTransferAccount";
|
|
40
|
+
ExtensionType2[ExtensionType2["DefaultAccountState"] = 6] = "DefaultAccountState";
|
|
41
|
+
ExtensionType2[ExtensionType2["ImmutableOwner"] = 7] = "ImmutableOwner";
|
|
42
|
+
ExtensionType2[ExtensionType2["MemoTransfer"] = 8] = "MemoTransfer";
|
|
43
|
+
ExtensionType2[ExtensionType2["NonTransferable"] = 9] = "NonTransferable";
|
|
44
|
+
ExtensionType2[ExtensionType2["InterestBearingConfig"] = 10] = "InterestBearingConfig";
|
|
45
|
+
ExtensionType2[ExtensionType2["CpiGuard"] = 11] = "CpiGuard";
|
|
46
|
+
ExtensionType2[ExtensionType2["PermanentDelegate"] = 12] = "PermanentDelegate";
|
|
47
|
+
ExtensionType2[ExtensionType2["NonTransferableAccount"] = 13] = "NonTransferableAccount";
|
|
48
|
+
ExtensionType2[ExtensionType2["TransferHook"] = 14] = "TransferHook";
|
|
49
|
+
ExtensionType2[ExtensionType2["TransferHookAccount"] = 15] = "TransferHookAccount";
|
|
50
|
+
ExtensionType2[ExtensionType2["ConfidentialTransferFeeConfig"] = 16] = "ConfidentialTransferFeeConfig";
|
|
51
|
+
ExtensionType2[ExtensionType2["ConfidentialTransferFeeAmount"] = 17] = "ConfidentialTransferFeeAmount";
|
|
52
|
+
ExtensionType2[ExtensionType2["MetadataPointer"] = 18] = "MetadataPointer";
|
|
53
|
+
ExtensionType2[ExtensionType2["TokenMetadata"] = 19] = "TokenMetadata";
|
|
54
|
+
ExtensionType2[ExtensionType2["GroupPointer"] = 20] = "GroupPointer";
|
|
55
|
+
ExtensionType2[ExtensionType2["TokenGroup"] = 21] = "TokenGroup";
|
|
56
|
+
ExtensionType2[ExtensionType2["GroupMemberPointer"] = 22] = "GroupMemberPointer";
|
|
57
|
+
ExtensionType2[ExtensionType2["TokenGroupMember"] = 23] = "TokenGroupMember";
|
|
58
|
+
return ExtensionType2;
|
|
59
|
+
})(ExtensionType || {});
|
|
60
|
+
var AccountType = /* @__PURE__ */ ((AccountType2) => {
|
|
61
|
+
AccountType2[AccountType2["Uninitialized"] = 0] = "Uninitialized";
|
|
62
|
+
AccountType2[AccountType2["Mint"] = 1] = "Mint";
|
|
63
|
+
AccountType2[AccountType2["Account"] = 2] = "Account";
|
|
64
|
+
return AccountType2;
|
|
65
|
+
})(AccountType || {});
|
|
66
|
+
var TokenInstruction = /* @__PURE__ */ ((TokenInstruction2) => {
|
|
67
|
+
TokenInstruction2[TokenInstruction2["InitializeMint"] = 0] = "InitializeMint";
|
|
68
|
+
TokenInstruction2[TokenInstruction2["InitializeAccount"] = 1] = "InitializeAccount";
|
|
69
|
+
TokenInstruction2[TokenInstruction2["InitializeMultisig"] = 2] = "InitializeMultisig";
|
|
70
|
+
TokenInstruction2[TokenInstruction2["Transfer"] = 3] = "Transfer";
|
|
71
|
+
TokenInstruction2[TokenInstruction2["Approve"] = 4] = "Approve";
|
|
72
|
+
TokenInstruction2[TokenInstruction2["Revoke"] = 5] = "Revoke";
|
|
73
|
+
TokenInstruction2[TokenInstruction2["SetAuthority"] = 6] = "SetAuthority";
|
|
74
|
+
TokenInstruction2[TokenInstruction2["MintTo"] = 7] = "MintTo";
|
|
75
|
+
TokenInstruction2[TokenInstruction2["Burn"] = 8] = "Burn";
|
|
76
|
+
TokenInstruction2[TokenInstruction2["CloseAccount"] = 9] = "CloseAccount";
|
|
77
|
+
TokenInstruction2[TokenInstruction2["FreezeAccount"] = 10] = "FreezeAccount";
|
|
78
|
+
TokenInstruction2[TokenInstruction2["ThawAccount"] = 11] = "ThawAccount";
|
|
79
|
+
TokenInstruction2[TokenInstruction2["TransferChecked"] = 12] = "TransferChecked";
|
|
80
|
+
TokenInstruction2[TokenInstruction2["ApproveChecked"] = 13] = "ApproveChecked";
|
|
81
|
+
TokenInstruction2[TokenInstruction2["MintToChecked"] = 14] = "MintToChecked";
|
|
82
|
+
TokenInstruction2[TokenInstruction2["BurnChecked"] = 15] = "BurnChecked";
|
|
83
|
+
TokenInstruction2[TokenInstruction2["InitializeAccount2"] = 16] = "InitializeAccount2";
|
|
84
|
+
TokenInstruction2[TokenInstruction2["SyncNative"] = 17] = "SyncNative";
|
|
85
|
+
TokenInstruction2[TokenInstruction2["InitializeAccount3"] = 18] = "InitializeAccount3";
|
|
86
|
+
TokenInstruction2[TokenInstruction2["InitializeMultisig2"] = 19] = "InitializeMultisig2";
|
|
87
|
+
TokenInstruction2[TokenInstruction2["InitializeMint2"] = 20] = "InitializeMint2";
|
|
88
|
+
return TokenInstruction2;
|
|
89
|
+
})(TokenInstruction || {});
|
|
90
|
+
var TLV_TYPE_SIZE = 2;
|
|
91
|
+
var TLV_LENGTH_SIZE = 2;
|
|
92
|
+
var MINT_EXTENSIONS_OFFSET = MINT_SIZE + 1;
|
|
93
|
+
|
|
94
|
+
// src/errors.ts
|
|
95
|
+
var SplTokenErrorCode = /* @__PURE__ */ ((SplTokenErrorCode2) => {
|
|
96
|
+
SplTokenErrorCode2["INVALID_MINT"] = "INVALID_MINT";
|
|
97
|
+
SplTokenErrorCode2["INVALID_TOKEN_ACCOUNT"] = "INVALID_TOKEN_ACCOUNT";
|
|
98
|
+
SplTokenErrorCode2["TOKEN_ACCOUNT_NOT_FOUND"] = "TOKEN_ACCOUNT_NOT_FOUND";
|
|
99
|
+
SplTokenErrorCode2["MINT_NOT_FOUND"] = "MINT_NOT_FOUND";
|
|
100
|
+
SplTokenErrorCode2["ACCOUNT_FROZEN"] = "ACCOUNT_FROZEN";
|
|
101
|
+
SplTokenErrorCode2["INSUFFICIENT_BALANCE"] = "INSUFFICIENT_BALANCE";
|
|
102
|
+
SplTokenErrorCode2["INVALID_EXTENSION"] = "INVALID_EXTENSION";
|
|
103
|
+
SplTokenErrorCode2["PDA_DERIVATION_FAILED"] = "PDA_DERIVATION_FAILED";
|
|
104
|
+
SplTokenErrorCode2["INVALID_METADATA"] = "INVALID_METADATA";
|
|
105
|
+
SplTokenErrorCode2["ACCOUNT_NOT_INITIALIZED"] = "ACCOUNT_NOT_INITIALIZED";
|
|
106
|
+
return SplTokenErrorCode2;
|
|
107
|
+
})(SplTokenErrorCode || {});
|
|
108
|
+
var SplTokenError = class _SplTokenError extends Error {
|
|
109
|
+
code;
|
|
110
|
+
details;
|
|
111
|
+
constructor({ code, message, details }) {
|
|
112
|
+
super(message);
|
|
113
|
+
this.name = "SplTokenError";
|
|
114
|
+
this.code = code;
|
|
115
|
+
this.details = details;
|
|
116
|
+
if (Error.captureStackTrace) {
|
|
117
|
+
Error.captureStackTrace(this, _SplTokenError);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Creates an invalid mint error.
|
|
122
|
+
*
|
|
123
|
+
* @param options - Error options containing the reason
|
|
124
|
+
*/
|
|
125
|
+
static invalidMint({ reason }) {
|
|
126
|
+
return new _SplTokenError({
|
|
127
|
+
code: "INVALID_MINT" /* INVALID_MINT */,
|
|
128
|
+
message: `Invalid mint: ${reason}`
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Creates an invalid token account error.
|
|
133
|
+
*
|
|
134
|
+
* @param options - Error options containing the reason
|
|
135
|
+
*/
|
|
136
|
+
static invalidTokenAccount({ reason }) {
|
|
137
|
+
return new _SplTokenError({
|
|
138
|
+
code: "INVALID_TOKEN_ACCOUNT" /* INVALID_TOKEN_ACCOUNT */,
|
|
139
|
+
message: `Invalid token account: ${reason}`
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Creates a token account not found error.
|
|
144
|
+
*
|
|
145
|
+
* @param options - Error options containing the address
|
|
146
|
+
*/
|
|
147
|
+
static tokenAccountNotFound({ address }) {
|
|
148
|
+
return new _SplTokenError({
|
|
149
|
+
code: "TOKEN_ACCOUNT_NOT_FOUND" /* TOKEN_ACCOUNT_NOT_FOUND */,
|
|
150
|
+
message: `Token account not found: ${address}`,
|
|
151
|
+
details: { address }
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Creates a mint not found error.
|
|
156
|
+
*
|
|
157
|
+
* @param options - Error options containing the address
|
|
158
|
+
*/
|
|
159
|
+
static mintNotFound({ address }) {
|
|
160
|
+
return new _SplTokenError({
|
|
161
|
+
code: "MINT_NOT_FOUND" /* MINT_NOT_FOUND */,
|
|
162
|
+
message: `Mint not found: ${address}`,
|
|
163
|
+
details: { address }
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Creates an account frozen error.
|
|
168
|
+
*
|
|
169
|
+
* @param options - Error options containing the address
|
|
170
|
+
*/
|
|
171
|
+
static accountFrozen({ address }) {
|
|
172
|
+
return new _SplTokenError({
|
|
173
|
+
code: "ACCOUNT_FROZEN" /* ACCOUNT_FROZEN */,
|
|
174
|
+
message: `Token account is frozen: ${address}`,
|
|
175
|
+
details: { address }
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Creates an insufficient balance error.
|
|
180
|
+
*
|
|
181
|
+
* @param options - Error options containing required and available amounts
|
|
182
|
+
*/
|
|
183
|
+
static insufficientBalance({
|
|
184
|
+
required,
|
|
185
|
+
available
|
|
186
|
+
}) {
|
|
187
|
+
return new _SplTokenError({
|
|
188
|
+
code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
|
|
189
|
+
message: `Insufficient balance: required ${required}, available ${available}`,
|
|
190
|
+
details: { required: required.toString(), available: available.toString() }
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/**
|
|
194
|
+
* Creates an invalid extension error.
|
|
195
|
+
*
|
|
196
|
+
* @param options - Error options containing the reason
|
|
197
|
+
*/
|
|
198
|
+
static invalidExtension({ reason }) {
|
|
199
|
+
return new _SplTokenError({
|
|
200
|
+
code: "INVALID_EXTENSION" /* INVALID_EXTENSION */,
|
|
201
|
+
message: `Invalid extension: ${reason}`
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Creates a PDA derivation failed error.
|
|
206
|
+
*
|
|
207
|
+
* @param options - Error options containing the reason
|
|
208
|
+
*/
|
|
209
|
+
static pdaDerivationFailed({ reason }) {
|
|
210
|
+
return new _SplTokenError({
|
|
211
|
+
code: "PDA_DERIVATION_FAILED" /* PDA_DERIVATION_FAILED */,
|
|
212
|
+
message: `PDA derivation failed: ${reason}`
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Creates an invalid metadata error.
|
|
217
|
+
*
|
|
218
|
+
* @param options - Error options containing the reason
|
|
219
|
+
*/
|
|
220
|
+
static invalidMetadata({ reason }) {
|
|
221
|
+
return new _SplTokenError({
|
|
222
|
+
code: "INVALID_METADATA" /* INVALID_METADATA */,
|
|
223
|
+
message: `Invalid metadata: ${reason}`
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Creates an account not initialized error.
|
|
228
|
+
*
|
|
229
|
+
* @param options - Error options containing the address
|
|
230
|
+
*/
|
|
231
|
+
static accountNotInitialized({ address }) {
|
|
232
|
+
return new _SplTokenError({
|
|
233
|
+
code: "ACCOUNT_NOT_INITIALIZED" /* ACCOUNT_NOT_INITIALIZED */,
|
|
234
|
+
message: `Account not initialized: ${address}`,
|
|
235
|
+
details: { address }
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
function createAssociatedTokenAccountInstruction({
|
|
240
|
+
payer,
|
|
241
|
+
associatedToken,
|
|
242
|
+
owner,
|
|
243
|
+
mint,
|
|
244
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
245
|
+
}) {
|
|
246
|
+
const associatedTokenProgramId = tsCdk.PublicKey.fromString(ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
247
|
+
const systemProgramId = tsCdk.PublicKey.fromString(tsCdk.SYSTEM_PROGRAM_ID);
|
|
248
|
+
return {
|
|
249
|
+
programId: associatedTokenProgramId,
|
|
250
|
+
accounts: [
|
|
251
|
+
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
252
|
+
{ pubkey: associatedToken, isSigner: false, isWritable: true },
|
|
253
|
+
{ pubkey: owner, isSigner: false, isWritable: false },
|
|
254
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
255
|
+
{ pubkey: systemProgramId, isSigner: false, isWritable: false },
|
|
256
|
+
{ pubkey: programId, isSigner: false, isWritable: false }
|
|
257
|
+
],
|
|
258
|
+
// CreateAssociatedTokenAccount has no instruction data
|
|
259
|
+
data: new Uint8Array(0)
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function createAssociatedTokenAccountIdempotentInstruction({
|
|
263
|
+
payer,
|
|
264
|
+
associatedToken,
|
|
265
|
+
owner,
|
|
266
|
+
mint,
|
|
267
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
268
|
+
}) {
|
|
269
|
+
const associatedTokenProgramId = tsCdk.PublicKey.fromString(ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
270
|
+
const systemProgramId = tsCdk.PublicKey.fromString(tsCdk.SYSTEM_PROGRAM_ID);
|
|
271
|
+
return {
|
|
272
|
+
programId: associatedTokenProgramId,
|
|
273
|
+
accounts: [
|
|
274
|
+
{ pubkey: payer, isSigner: true, isWritable: true },
|
|
275
|
+
{ pubkey: associatedToken, isSigner: false, isWritable: true },
|
|
276
|
+
{ pubkey: owner, isSigner: false, isWritable: false },
|
|
277
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
278
|
+
{ pubkey: systemProgramId, isSigner: false, isWritable: false },
|
|
279
|
+
{ pubkey: programId, isSigner: false, isWritable: false }
|
|
280
|
+
],
|
|
281
|
+
// Idempotent variant uses instruction discriminator 1
|
|
282
|
+
data: new Uint8Array([1])
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/test-helpers.ts
|
|
287
|
+
function writeU64LE({
|
|
288
|
+
data,
|
|
289
|
+
offset,
|
|
290
|
+
value
|
|
291
|
+
}) {
|
|
292
|
+
for (let i = 0; i < 8; i++) {
|
|
293
|
+
data[offset + i] = Number(value >> BigInt(i * 8) & 0xffn);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
// src/instructions/mint.ts
|
|
298
|
+
function initializeMintInstruction({
|
|
299
|
+
mint,
|
|
300
|
+
decimals,
|
|
301
|
+
mintAuthority,
|
|
302
|
+
freezeAuthority,
|
|
303
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
304
|
+
}) {
|
|
305
|
+
const data = new Uint8Array(67);
|
|
306
|
+
data[0] = 20 /* InitializeMint2 */;
|
|
307
|
+
data[1] = decimals;
|
|
308
|
+
data.set(mintAuthority.toBytes(), 2);
|
|
309
|
+
if (freezeAuthority) {
|
|
310
|
+
data[34] = 1;
|
|
311
|
+
data.set(freezeAuthority.toBytes(), 35);
|
|
312
|
+
} else {
|
|
313
|
+
data[34] = 0;
|
|
314
|
+
}
|
|
315
|
+
const [tombstonePda] = tsCdk.PublicKey.findProgramAddress(
|
|
316
|
+
["mint_tombstone", mint.toBytes()],
|
|
317
|
+
programId
|
|
318
|
+
);
|
|
319
|
+
return {
|
|
320
|
+
programId,
|
|
321
|
+
accounts: [
|
|
322
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
323
|
+
{ pubkey: tombstonePda, isSigner: false, isWritable: false }
|
|
324
|
+
],
|
|
325
|
+
data
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function mintToInstruction({
|
|
329
|
+
mint,
|
|
330
|
+
destination,
|
|
331
|
+
authority,
|
|
332
|
+
amount,
|
|
333
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
334
|
+
}) {
|
|
335
|
+
const data = new Uint8Array(9);
|
|
336
|
+
data[0] = 7 /* MintTo */;
|
|
337
|
+
writeU64LE({ data, offset: 1, value: amount });
|
|
338
|
+
return {
|
|
339
|
+
programId,
|
|
340
|
+
accounts: [
|
|
341
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
342
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
343
|
+
{ pubkey: authority, isSigner: true, isWritable: false }
|
|
344
|
+
],
|
|
345
|
+
data
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function writeU64LE2({
|
|
349
|
+
data,
|
|
350
|
+
offset,
|
|
351
|
+
value
|
|
352
|
+
}) {
|
|
353
|
+
for (let i = 0; i < 8; i++) {
|
|
354
|
+
data[offset + i] = Number(value >> BigInt(i * 8) & 0xffn);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
function transferCheckedInstruction({
|
|
358
|
+
source,
|
|
359
|
+
mint,
|
|
360
|
+
destination,
|
|
361
|
+
authority,
|
|
362
|
+
amount,
|
|
363
|
+
decimals,
|
|
364
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
365
|
+
}) {
|
|
366
|
+
const data = new Uint8Array(10);
|
|
367
|
+
data[0] = 12 /* TransferChecked */;
|
|
368
|
+
writeU64LE2({ data, offset: 1, value: amount });
|
|
369
|
+
data[9] = decimals;
|
|
370
|
+
return {
|
|
371
|
+
programId,
|
|
372
|
+
accounts: [
|
|
373
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
374
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
375
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
376
|
+
{ pubkey: authority, isSigner: true, isWritable: false }
|
|
377
|
+
],
|
|
378
|
+
data
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
function transferInstruction({
|
|
382
|
+
source,
|
|
383
|
+
destination,
|
|
384
|
+
authority,
|
|
385
|
+
amount,
|
|
386
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
387
|
+
}) {
|
|
388
|
+
const data = new Uint8Array(9);
|
|
389
|
+
data[0] = 3 /* Transfer */;
|
|
390
|
+
writeU64LE2({ data, offset: 1, value: amount });
|
|
391
|
+
return {
|
|
392
|
+
programId,
|
|
393
|
+
accounts: [
|
|
394
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
395
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
396
|
+
{ pubkey: authority, isSigner: true, isWritable: false }
|
|
397
|
+
],
|
|
398
|
+
data
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// node_modules/@noble/hashes/utils.js
|
|
403
|
+
function isBytes(a) {
|
|
404
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
405
|
+
}
|
|
406
|
+
function abytes(value, length, title = "") {
|
|
407
|
+
const bytes = isBytes(value);
|
|
408
|
+
const len = value?.length;
|
|
409
|
+
const needsLen = length !== void 0;
|
|
410
|
+
if (!bytes || needsLen) {
|
|
411
|
+
const prefix = title && `"${title}" `;
|
|
412
|
+
const ofLen = "";
|
|
413
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
414
|
+
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
415
|
+
}
|
|
416
|
+
return value;
|
|
417
|
+
}
|
|
418
|
+
function aexists(instance, checkFinished = true) {
|
|
419
|
+
if (instance.destroyed)
|
|
420
|
+
throw new Error("Hash instance has been destroyed");
|
|
421
|
+
if (checkFinished && instance.finished)
|
|
422
|
+
throw new Error("Hash#digest() has already been called");
|
|
423
|
+
}
|
|
424
|
+
function aoutput(out, instance) {
|
|
425
|
+
abytes(out, void 0, "digestInto() output");
|
|
426
|
+
const min = instance.outputLen;
|
|
427
|
+
if (out.length < min) {
|
|
428
|
+
throw new Error('"digestInto() output" expected to be of length >=' + min);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function clean(...arrays) {
|
|
432
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
433
|
+
arrays[i].fill(0);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
function createView(arr) {
|
|
437
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
438
|
+
}
|
|
439
|
+
function rotr(word, shift) {
|
|
440
|
+
return word << 32 - shift | word >>> shift;
|
|
441
|
+
}
|
|
442
|
+
function createHasher(hashCons, info = {}) {
|
|
443
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
444
|
+
const tmp = hashCons(void 0);
|
|
445
|
+
hashC.outputLen = tmp.outputLen;
|
|
446
|
+
hashC.blockLen = tmp.blockLen;
|
|
447
|
+
hashC.create = (opts) => hashCons(opts);
|
|
448
|
+
Object.assign(hashC, info);
|
|
449
|
+
return Object.freeze(hashC);
|
|
450
|
+
}
|
|
451
|
+
var oidNist = (suffix) => ({
|
|
452
|
+
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
453
|
+
});
|
|
454
|
+
|
|
455
|
+
// node_modules/@noble/hashes/_md.js
|
|
456
|
+
function Chi(a, b, c) {
|
|
457
|
+
return a & b ^ ~a & c;
|
|
458
|
+
}
|
|
459
|
+
function Maj(a, b, c) {
|
|
460
|
+
return a & b ^ a & c ^ b & c;
|
|
461
|
+
}
|
|
462
|
+
var HashMD = class {
|
|
463
|
+
blockLen;
|
|
464
|
+
outputLen;
|
|
465
|
+
padOffset;
|
|
466
|
+
isLE;
|
|
467
|
+
// For partial updates less than block size
|
|
468
|
+
buffer;
|
|
469
|
+
view;
|
|
470
|
+
finished = false;
|
|
471
|
+
length = 0;
|
|
472
|
+
pos = 0;
|
|
473
|
+
destroyed = false;
|
|
474
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
475
|
+
this.blockLen = blockLen;
|
|
476
|
+
this.outputLen = outputLen;
|
|
477
|
+
this.padOffset = padOffset;
|
|
478
|
+
this.isLE = isLE;
|
|
479
|
+
this.buffer = new Uint8Array(blockLen);
|
|
480
|
+
this.view = createView(this.buffer);
|
|
481
|
+
}
|
|
482
|
+
update(data) {
|
|
483
|
+
aexists(this);
|
|
484
|
+
abytes(data);
|
|
485
|
+
const { view, buffer, blockLen } = this;
|
|
486
|
+
const len = data.length;
|
|
487
|
+
for (let pos = 0; pos < len; ) {
|
|
488
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
489
|
+
if (take === blockLen) {
|
|
490
|
+
const dataView = createView(data);
|
|
491
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
492
|
+
this.process(dataView, pos);
|
|
493
|
+
continue;
|
|
494
|
+
}
|
|
495
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
496
|
+
this.pos += take;
|
|
497
|
+
pos += take;
|
|
498
|
+
if (this.pos === blockLen) {
|
|
499
|
+
this.process(view, 0);
|
|
500
|
+
this.pos = 0;
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
this.length += data.length;
|
|
504
|
+
this.roundClean();
|
|
505
|
+
return this;
|
|
506
|
+
}
|
|
507
|
+
digestInto(out) {
|
|
508
|
+
aexists(this);
|
|
509
|
+
aoutput(out, this);
|
|
510
|
+
this.finished = true;
|
|
511
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
512
|
+
let { pos } = this;
|
|
513
|
+
buffer[pos++] = 128;
|
|
514
|
+
clean(this.buffer.subarray(pos));
|
|
515
|
+
if (this.padOffset > blockLen - pos) {
|
|
516
|
+
this.process(view, 0);
|
|
517
|
+
pos = 0;
|
|
518
|
+
}
|
|
519
|
+
for (let i = pos; i < blockLen; i++)
|
|
520
|
+
buffer[i] = 0;
|
|
521
|
+
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
522
|
+
this.process(view, 0);
|
|
523
|
+
const oview = createView(out);
|
|
524
|
+
const len = this.outputLen;
|
|
525
|
+
if (len % 4)
|
|
526
|
+
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
527
|
+
const outLen = len / 4;
|
|
528
|
+
const state = this.get();
|
|
529
|
+
if (outLen > state.length)
|
|
530
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
531
|
+
for (let i = 0; i < outLen; i++)
|
|
532
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
533
|
+
}
|
|
534
|
+
digest() {
|
|
535
|
+
const { buffer, outputLen } = this;
|
|
536
|
+
this.digestInto(buffer);
|
|
537
|
+
const res = buffer.slice(0, outputLen);
|
|
538
|
+
this.destroy();
|
|
539
|
+
return res;
|
|
540
|
+
}
|
|
541
|
+
_cloneInto(to) {
|
|
542
|
+
to ||= new this.constructor();
|
|
543
|
+
to.set(...this.get());
|
|
544
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
545
|
+
to.destroyed = destroyed;
|
|
546
|
+
to.finished = finished;
|
|
547
|
+
to.length = length;
|
|
548
|
+
to.pos = pos;
|
|
549
|
+
if (length % blockLen)
|
|
550
|
+
to.buffer.set(buffer);
|
|
551
|
+
return to;
|
|
552
|
+
}
|
|
553
|
+
clone() {
|
|
554
|
+
return this._cloneInto();
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
558
|
+
1779033703,
|
|
559
|
+
3144134277,
|
|
560
|
+
1013904242,
|
|
561
|
+
2773480762,
|
|
562
|
+
1359893119,
|
|
563
|
+
2600822924,
|
|
564
|
+
528734635,
|
|
565
|
+
1541459225
|
|
566
|
+
]);
|
|
567
|
+
|
|
568
|
+
// node_modules/@noble/hashes/sha2.js
|
|
569
|
+
var SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
570
|
+
1116352408,
|
|
571
|
+
1899447441,
|
|
572
|
+
3049323471,
|
|
573
|
+
3921009573,
|
|
574
|
+
961987163,
|
|
575
|
+
1508970993,
|
|
576
|
+
2453635748,
|
|
577
|
+
2870763221,
|
|
578
|
+
3624381080,
|
|
579
|
+
310598401,
|
|
580
|
+
607225278,
|
|
581
|
+
1426881987,
|
|
582
|
+
1925078388,
|
|
583
|
+
2162078206,
|
|
584
|
+
2614888103,
|
|
585
|
+
3248222580,
|
|
586
|
+
3835390401,
|
|
587
|
+
4022224774,
|
|
588
|
+
264347078,
|
|
589
|
+
604807628,
|
|
590
|
+
770255983,
|
|
591
|
+
1249150122,
|
|
592
|
+
1555081692,
|
|
593
|
+
1996064986,
|
|
594
|
+
2554220882,
|
|
595
|
+
2821834349,
|
|
596
|
+
2952996808,
|
|
597
|
+
3210313671,
|
|
598
|
+
3336571891,
|
|
599
|
+
3584528711,
|
|
600
|
+
113926993,
|
|
601
|
+
338241895,
|
|
602
|
+
666307205,
|
|
603
|
+
773529912,
|
|
604
|
+
1294757372,
|
|
605
|
+
1396182291,
|
|
606
|
+
1695183700,
|
|
607
|
+
1986661051,
|
|
608
|
+
2177026350,
|
|
609
|
+
2456956037,
|
|
610
|
+
2730485921,
|
|
611
|
+
2820302411,
|
|
612
|
+
3259730800,
|
|
613
|
+
3345764771,
|
|
614
|
+
3516065817,
|
|
615
|
+
3600352804,
|
|
616
|
+
4094571909,
|
|
617
|
+
275423344,
|
|
618
|
+
430227734,
|
|
619
|
+
506948616,
|
|
620
|
+
659060556,
|
|
621
|
+
883997877,
|
|
622
|
+
958139571,
|
|
623
|
+
1322822218,
|
|
624
|
+
1537002063,
|
|
625
|
+
1747873779,
|
|
626
|
+
1955562222,
|
|
627
|
+
2024104815,
|
|
628
|
+
2227730452,
|
|
629
|
+
2361852424,
|
|
630
|
+
2428436474,
|
|
631
|
+
2756734187,
|
|
632
|
+
3204031479,
|
|
633
|
+
3329325298
|
|
634
|
+
]);
|
|
635
|
+
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
636
|
+
var SHA2_32B = class extends HashMD {
|
|
637
|
+
constructor(outputLen) {
|
|
638
|
+
super(64, outputLen, 8, false);
|
|
639
|
+
}
|
|
640
|
+
get() {
|
|
641
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
642
|
+
return [A, B, C, D, E, F, G, H];
|
|
643
|
+
}
|
|
644
|
+
// prettier-ignore
|
|
645
|
+
set(A, B, C, D, E, F, G, H) {
|
|
646
|
+
this.A = A | 0;
|
|
647
|
+
this.B = B | 0;
|
|
648
|
+
this.C = C | 0;
|
|
649
|
+
this.D = D | 0;
|
|
650
|
+
this.E = E | 0;
|
|
651
|
+
this.F = F | 0;
|
|
652
|
+
this.G = G | 0;
|
|
653
|
+
this.H = H | 0;
|
|
654
|
+
}
|
|
655
|
+
process(view, offset) {
|
|
656
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
657
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
658
|
+
for (let i = 16; i < 64; i++) {
|
|
659
|
+
const W15 = SHA256_W[i - 15];
|
|
660
|
+
const W2 = SHA256_W[i - 2];
|
|
661
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
662
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
663
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
664
|
+
}
|
|
665
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
666
|
+
for (let i = 0; i < 64; i++) {
|
|
667
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
668
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
669
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
670
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
671
|
+
H = G;
|
|
672
|
+
G = F;
|
|
673
|
+
F = E;
|
|
674
|
+
E = D + T1 | 0;
|
|
675
|
+
D = C;
|
|
676
|
+
C = B;
|
|
677
|
+
B = A;
|
|
678
|
+
A = T1 + T2 | 0;
|
|
679
|
+
}
|
|
680
|
+
A = A + this.A | 0;
|
|
681
|
+
B = B + this.B | 0;
|
|
682
|
+
C = C + this.C | 0;
|
|
683
|
+
D = D + this.D | 0;
|
|
684
|
+
E = E + this.E | 0;
|
|
685
|
+
F = F + this.F | 0;
|
|
686
|
+
G = G + this.G | 0;
|
|
687
|
+
H = H + this.H | 0;
|
|
688
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
689
|
+
}
|
|
690
|
+
roundClean() {
|
|
691
|
+
clean(SHA256_W);
|
|
692
|
+
}
|
|
693
|
+
destroy() {
|
|
694
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
695
|
+
clean(this.buffer);
|
|
696
|
+
}
|
|
697
|
+
};
|
|
698
|
+
var _SHA256 = class extends SHA2_32B {
|
|
699
|
+
// We cannot use array here since array allows indexing by variable
|
|
700
|
+
// which means optimizer/compiler cannot use registers.
|
|
701
|
+
A = SHA256_IV[0] | 0;
|
|
702
|
+
B = SHA256_IV[1] | 0;
|
|
703
|
+
C = SHA256_IV[2] | 0;
|
|
704
|
+
D = SHA256_IV[3] | 0;
|
|
705
|
+
E = SHA256_IV[4] | 0;
|
|
706
|
+
F = SHA256_IV[5] | 0;
|
|
707
|
+
G = SHA256_IV[6] | 0;
|
|
708
|
+
H = SHA256_IV[7] | 0;
|
|
709
|
+
constructor() {
|
|
710
|
+
super(32);
|
|
711
|
+
}
|
|
712
|
+
};
|
|
713
|
+
var sha256 = /* @__PURE__ */ createHasher(
|
|
714
|
+
() => new _SHA256(),
|
|
715
|
+
/* @__PURE__ */ oidNist(1)
|
|
716
|
+
);
|
|
717
|
+
function createProgramAddress({
|
|
718
|
+
seeds,
|
|
719
|
+
programId
|
|
720
|
+
}) {
|
|
721
|
+
for (let bump = 255; bump >= 0; bump--) {
|
|
722
|
+
const bumpSeed = new Uint8Array([bump]);
|
|
723
|
+
const allSeeds = [...seeds, bumpSeed];
|
|
724
|
+
const programIdBytes = programId.toBytes();
|
|
725
|
+
const pda_marker = new TextEncoder().encode("ProgramDerivedAddress");
|
|
726
|
+
let totalLength = 0;
|
|
727
|
+
for (const seed of allSeeds) {
|
|
728
|
+
totalLength += seed.length;
|
|
729
|
+
}
|
|
730
|
+
totalLength += programIdBytes.length + pda_marker.length;
|
|
731
|
+
const combined = new Uint8Array(totalLength);
|
|
732
|
+
let offset = 0;
|
|
733
|
+
for (const seed of allSeeds) {
|
|
734
|
+
combined.set(seed, offset);
|
|
735
|
+
offset += seed.length;
|
|
736
|
+
}
|
|
737
|
+
combined.set(programIdBytes, offset);
|
|
738
|
+
offset += programIdBytes.length;
|
|
739
|
+
combined.set(pda_marker, offset);
|
|
740
|
+
const hash = sha256(combined);
|
|
741
|
+
if (!tsCdk.isOnCurve(hash)) {
|
|
742
|
+
return {
|
|
743
|
+
address: tsCdk.PublicKey.fromBytes(hash),
|
|
744
|
+
bump
|
|
745
|
+
};
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
return null;
|
|
749
|
+
}
|
|
750
|
+
function findAssociatedTokenAddress({
|
|
751
|
+
wallet,
|
|
752
|
+
mint,
|
|
753
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
754
|
+
}) {
|
|
755
|
+
const associatedTokenProgramId = tsCdk.PublicKey.fromString(ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
756
|
+
const seeds = [wallet.toBytes(), programId.toBytes(), mint.toBytes()];
|
|
757
|
+
const result = createProgramAddress({ seeds, programId: associatedTokenProgramId });
|
|
758
|
+
if (!result) {
|
|
759
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
760
|
+
reason: `Could not find valid PDA for wallet=${wallet.toString()}, mint=${mint.toString()}`
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
return result;
|
|
764
|
+
}
|
|
765
|
+
function getAssociatedTokenAddressSync({
|
|
766
|
+
wallet,
|
|
767
|
+
mint,
|
|
768
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
769
|
+
}) {
|
|
770
|
+
return findAssociatedTokenAddress({ wallet, mint, programId }).address;
|
|
771
|
+
}
|
|
772
|
+
function readU64LE({ data, offset }) {
|
|
773
|
+
let value = 0n;
|
|
774
|
+
for (let i = 0; i < 8; i++) {
|
|
775
|
+
value |= BigInt(data[offset + i]) << BigInt(i * 8);
|
|
776
|
+
}
|
|
777
|
+
return value;
|
|
778
|
+
}
|
|
779
|
+
function readU32LE({ data, offset }) {
|
|
780
|
+
return (data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24) >>> 0;
|
|
781
|
+
}
|
|
782
|
+
function readCOptionPubkey({
|
|
783
|
+
data,
|
|
784
|
+
offset
|
|
785
|
+
}) {
|
|
786
|
+
const tag = readU32LE({ data, offset });
|
|
787
|
+
if (tag === COPTION_SOME) {
|
|
788
|
+
const pubkeyBytes = data.slice(offset + 4, offset + 4 + PUBKEY_SIZE);
|
|
789
|
+
return tsCdk.PublicKey.fromBytes(pubkeyBytes);
|
|
790
|
+
}
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
function parseMintAccount({ address, data }) {
|
|
794
|
+
if (data.length < MINT_SIZE) {
|
|
795
|
+
throw SplTokenError.invalidMint({
|
|
796
|
+
reason: `Account data too short: expected at least ${MINT_SIZE} bytes, got ${data.length}`
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
const mintAuthority = readCOptionPubkey({ data, offset: 0 });
|
|
800
|
+
const supply = readU64LE({ data, offset: MINT_SUPPLY_OFFSET });
|
|
801
|
+
const decimals = data[MINT_DECIMALS_OFFSET];
|
|
802
|
+
const isInitialized = data[MINT_IS_INITIALIZED_OFFSET] !== 0;
|
|
803
|
+
const freezeAuthority = readCOptionPubkey({ data, offset: MINT_FREEZE_AUTHORITY_OFFSET });
|
|
804
|
+
if (!isInitialized) {
|
|
805
|
+
throw SplTokenError.accountNotInitialized({ address: address.toString() });
|
|
806
|
+
}
|
|
807
|
+
return {
|
|
808
|
+
address,
|
|
809
|
+
supply,
|
|
810
|
+
decimals,
|
|
811
|
+
isInitialized,
|
|
812
|
+
mintAuthority,
|
|
813
|
+
freezeAuthority
|
|
814
|
+
};
|
|
815
|
+
}
|
|
816
|
+
function readU64LE2({ data, offset }) {
|
|
817
|
+
let value = 0n;
|
|
818
|
+
for (let i = 0; i < 8; i++) {
|
|
819
|
+
value |= BigInt(data[offset + i]) << BigInt(i * 8);
|
|
820
|
+
}
|
|
821
|
+
return value;
|
|
822
|
+
}
|
|
823
|
+
function readU32LE2({ data, offset }) {
|
|
824
|
+
return (data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24) >>> 0;
|
|
825
|
+
}
|
|
826
|
+
function readCOptionPubkey2({
|
|
827
|
+
data,
|
|
828
|
+
offset
|
|
829
|
+
}) {
|
|
830
|
+
const tag = readU32LE2({ data, offset });
|
|
831
|
+
if (tag === COPTION_SOME) {
|
|
832
|
+
const pubkeyBytes = data.slice(offset + 4, offset + 4 + PUBKEY_SIZE);
|
|
833
|
+
return tsCdk.PublicKey.fromBytes(pubkeyBytes);
|
|
834
|
+
}
|
|
835
|
+
return null;
|
|
836
|
+
}
|
|
837
|
+
function readCOptionU64({ data, offset }) {
|
|
838
|
+
const tag = readU32LE2({ data, offset });
|
|
839
|
+
if (tag === COPTION_SOME) {
|
|
840
|
+
return readU64LE2({ data, offset: offset + 4 });
|
|
841
|
+
}
|
|
842
|
+
return null;
|
|
843
|
+
}
|
|
844
|
+
function parseTokenAccount({ address, data }) {
|
|
845
|
+
if (data.length < TOKEN_ACCOUNT_SIZE) {
|
|
846
|
+
throw SplTokenError.invalidTokenAccount({
|
|
847
|
+
reason: `Account data too short: expected at least ${TOKEN_ACCOUNT_SIZE} bytes, got ${data.length}`
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
const mintBytes = data.slice(TOKEN_ACCOUNT_MINT_OFFSET, TOKEN_ACCOUNT_MINT_OFFSET + PUBKEY_SIZE);
|
|
851
|
+
const mint = tsCdk.PublicKey.fromBytes(mintBytes);
|
|
852
|
+
const ownerBytes = data.slice(
|
|
853
|
+
TOKEN_ACCOUNT_OWNER_OFFSET,
|
|
854
|
+
TOKEN_ACCOUNT_OWNER_OFFSET + PUBKEY_SIZE
|
|
855
|
+
);
|
|
856
|
+
const owner = tsCdk.PublicKey.fromBytes(ownerBytes);
|
|
857
|
+
const amount = readU64LE2({ data, offset: TOKEN_ACCOUNT_AMOUNT_OFFSET });
|
|
858
|
+
const delegate = readCOptionPubkey2({ data, offset: TOKEN_ACCOUNT_DELEGATE_OFFSET });
|
|
859
|
+
const stateValue = data[TOKEN_ACCOUNT_STATE_OFFSET];
|
|
860
|
+
if (stateValue > 2) {
|
|
861
|
+
throw SplTokenError.invalidTokenAccount({ reason: `Invalid account state: ${stateValue}` });
|
|
862
|
+
}
|
|
863
|
+
const state = stateValue;
|
|
864
|
+
if (state === 0 /* Uninitialized */) {
|
|
865
|
+
throw SplTokenError.accountNotInitialized({ address: address.toString() });
|
|
866
|
+
}
|
|
867
|
+
const isNative = readCOptionU64({ data, offset: TOKEN_ACCOUNT_IS_NATIVE_OFFSET });
|
|
868
|
+
const delegatedAmount = readU64LE2({ data, offset: TOKEN_ACCOUNT_DELEGATED_AMOUNT_OFFSET });
|
|
869
|
+
const closeAuthority = readCOptionPubkey2({ data, offset: TOKEN_ACCOUNT_CLOSE_AUTHORITY_OFFSET });
|
|
870
|
+
return {
|
|
871
|
+
address,
|
|
872
|
+
mint,
|
|
873
|
+
owner,
|
|
874
|
+
amount,
|
|
875
|
+
delegate,
|
|
876
|
+
state,
|
|
877
|
+
isNative,
|
|
878
|
+
delegatedAmount,
|
|
879
|
+
closeAuthority
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
function readU16LE({ data, offset }) {
|
|
883
|
+
return data[offset] | data[offset + 1] << 8;
|
|
884
|
+
}
|
|
885
|
+
function readU32LE3({ data, offset }) {
|
|
886
|
+
return (data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24) >>> 0;
|
|
887
|
+
}
|
|
888
|
+
function readCOptionPubkey3({
|
|
889
|
+
data,
|
|
890
|
+
offset
|
|
891
|
+
}) {
|
|
892
|
+
const tag = readU32LE3({ data, offset });
|
|
893
|
+
if (tag === COPTION_SOME) {
|
|
894
|
+
const pubkeyBytes = data.slice(offset + 4, offset + 4 + PUBKEY_SIZE);
|
|
895
|
+
return tsCdk.PublicKey.fromBytes(pubkeyBytes);
|
|
896
|
+
}
|
|
897
|
+
return null;
|
|
898
|
+
}
|
|
899
|
+
function readLengthPrefixedString({
|
|
900
|
+
data,
|
|
901
|
+
offset
|
|
902
|
+
}) {
|
|
903
|
+
if (offset + 4 > data.length) {
|
|
904
|
+
throw SplTokenError.invalidMetadata({ reason: "String length prefix extends beyond data" });
|
|
905
|
+
}
|
|
906
|
+
const length = readU32LE3({ data, offset });
|
|
907
|
+
if (offset + 4 + length > data.length) {
|
|
908
|
+
throw SplTokenError.invalidMetadata({
|
|
909
|
+
reason: `String data extends beyond buffer: need ${length} bytes at offset ${offset + 4}`
|
|
910
|
+
});
|
|
911
|
+
}
|
|
912
|
+
const stringBytes = data.slice(offset + 4, offset + 4 + length);
|
|
913
|
+
try {
|
|
914
|
+
const str = new TextDecoder().decode(stringBytes);
|
|
915
|
+
return [str, 4 + length];
|
|
916
|
+
} catch (error) {
|
|
917
|
+
throw SplTokenError.invalidMetadata({
|
|
918
|
+
reason: `Invalid UTF-8 string at offset ${offset}`
|
|
919
|
+
});
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
function parseExtensions({
|
|
923
|
+
data,
|
|
924
|
+
extensionsOffset
|
|
925
|
+
}) {
|
|
926
|
+
const extensions = [];
|
|
927
|
+
let offset = extensionsOffset;
|
|
928
|
+
while (offset + TLV_TYPE_SIZE + TLV_LENGTH_SIZE <= data.length) {
|
|
929
|
+
const type = readU16LE({ data, offset });
|
|
930
|
+
const length = readU16LE({ data, offset: offset + TLV_TYPE_SIZE });
|
|
931
|
+
if (type === 0 && length === 0) {
|
|
932
|
+
break;
|
|
933
|
+
}
|
|
934
|
+
const dataStart = offset + TLV_TYPE_SIZE + TLV_LENGTH_SIZE;
|
|
935
|
+
const dataEnd = dataStart + length;
|
|
936
|
+
if (dataEnd > data.length) {
|
|
937
|
+
throw SplTokenError.invalidExtension({
|
|
938
|
+
reason: `Extension data extends beyond buffer: type=${type}, length=${length}`
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
extensions.push({
|
|
942
|
+
type,
|
|
943
|
+
data: data.slice(dataStart, dataEnd)
|
|
944
|
+
});
|
|
945
|
+
offset = dataEnd;
|
|
946
|
+
}
|
|
947
|
+
return extensions;
|
|
948
|
+
}
|
|
949
|
+
function parseMetadataPointer({ data }) {
|
|
950
|
+
if (data.length < 72) {
|
|
951
|
+
throw SplTokenError.invalidExtension({
|
|
952
|
+
reason: `MetadataPointer too short: expected 72 bytes, got ${data.length}`
|
|
953
|
+
});
|
|
954
|
+
}
|
|
955
|
+
const authority = readCOptionPubkey3({ data, offset: 0 });
|
|
956
|
+
const metadataAddress = readCOptionPubkey3({ data, offset: 36 });
|
|
957
|
+
return { authority, metadataAddress };
|
|
958
|
+
}
|
|
959
|
+
function parseTokenMetadataExtension({
|
|
960
|
+
data,
|
|
961
|
+
mint
|
|
962
|
+
}) {
|
|
963
|
+
if (data.length < 64) {
|
|
964
|
+
throw SplTokenError.invalidMetadata({
|
|
965
|
+
reason: `TokenMetadata too short: expected at least 64 bytes, got ${data.length}`
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
let offset = 0;
|
|
969
|
+
const updateAuthorityBytes = data.slice(offset, offset + PUBKEY_SIZE);
|
|
970
|
+
const isZeroAuthority = updateAuthorityBytes.every((b) => b === 0);
|
|
971
|
+
const updateAuthority = isZeroAuthority ? null : tsCdk.PublicKey.fromBytes(updateAuthorityBytes);
|
|
972
|
+
offset += PUBKEY_SIZE;
|
|
973
|
+
offset += PUBKEY_SIZE;
|
|
974
|
+
const [name, nameLen] = readLengthPrefixedString({ data, offset });
|
|
975
|
+
offset += nameLen;
|
|
976
|
+
const [symbol, symbolLen] = readLengthPrefixedString({ data, offset });
|
|
977
|
+
offset += symbolLen;
|
|
978
|
+
const [uri, uriLen] = readLengthPrefixedString({ data, offset });
|
|
979
|
+
offset += uriLen;
|
|
980
|
+
const additionalMetadata = [];
|
|
981
|
+
if (offset + 4 <= data.length) {
|
|
982
|
+
const numEntries = readU32LE3({ data, offset });
|
|
983
|
+
offset += 4;
|
|
984
|
+
for (let i = 0; i < numEntries && offset < data.length; i++) {
|
|
985
|
+
const [key, keyLen] = readLengthPrefixedString({ data, offset });
|
|
986
|
+
offset += keyLen;
|
|
987
|
+
const [value, valueLen] = readLengthPrefixedString({ data, offset });
|
|
988
|
+
offset += valueLen;
|
|
989
|
+
additionalMetadata.push([key, value]);
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
return {
|
|
993
|
+
updateAuthority,
|
|
994
|
+
mint,
|
|
995
|
+
name,
|
|
996
|
+
symbol,
|
|
997
|
+
uri,
|
|
998
|
+
additionalMetadata
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
function parseTokenMetadata({
|
|
1002
|
+
mint,
|
|
1003
|
+
data
|
|
1004
|
+
}) {
|
|
1005
|
+
if (data.length <= MINT_SIZE) {
|
|
1006
|
+
return null;
|
|
1007
|
+
}
|
|
1008
|
+
const accountType = data[MINT_SIZE];
|
|
1009
|
+
if (accountType !== 1 /* Mint */) {
|
|
1010
|
+
return null;
|
|
1011
|
+
}
|
|
1012
|
+
const extensions = parseExtensions({ data, extensionsOffset: MINT_EXTENSIONS_OFFSET });
|
|
1013
|
+
const metadataExt = extensions.find((ext) => ext.type === 19 /* TokenMetadata */);
|
|
1014
|
+
if (!metadataExt) {
|
|
1015
|
+
return null;
|
|
1016
|
+
}
|
|
1017
|
+
return parseTokenMetadataExtension({ data: metadataExt.data, mint });
|
|
1018
|
+
}
|
|
1019
|
+
function parseMetadataPointerExtension({
|
|
1020
|
+
data
|
|
1021
|
+
}) {
|
|
1022
|
+
if (data.length <= MINT_SIZE) {
|
|
1023
|
+
return null;
|
|
1024
|
+
}
|
|
1025
|
+
const accountType = data[MINT_SIZE];
|
|
1026
|
+
if (accountType !== 1 /* Mint */) {
|
|
1027
|
+
return null;
|
|
1028
|
+
}
|
|
1029
|
+
const extensions = parseExtensions({ data, extensionsOffset: MINT_EXTENSIONS_OFFSET });
|
|
1030
|
+
const pointerExt = extensions.find((ext) => ext.type === 18 /* MetadataPointer */);
|
|
1031
|
+
if (!pointerExt) {
|
|
1032
|
+
return null;
|
|
1033
|
+
}
|
|
1034
|
+
return parseMetadataPointer({ data: pointerExt.data });
|
|
1035
|
+
}
|
|
1036
|
+
function getMintExtensions({ data }) {
|
|
1037
|
+
if (data.length <= MINT_SIZE) {
|
|
1038
|
+
return [];
|
|
1039
|
+
}
|
|
1040
|
+
const accountType = data[MINT_SIZE];
|
|
1041
|
+
if (accountType !== 1 /* Mint */) {
|
|
1042
|
+
return [];
|
|
1043
|
+
}
|
|
1044
|
+
return parseExtensions({ data, extensionsOffset: MINT_EXTENSIONS_OFFSET });
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// src/client/spl-token-client.ts
|
|
1048
|
+
function decodeAccountData(data) {
|
|
1049
|
+
if (data instanceof Uint8Array) return data;
|
|
1050
|
+
const encoded = data[0];
|
|
1051
|
+
const binaryStr = atob(encoded);
|
|
1052
|
+
const bytes = new Uint8Array(binaryStr.length);
|
|
1053
|
+
for (let i = 0; i < binaryStr.length; i++) {
|
|
1054
|
+
bytes[i] = binaryStr.charCodeAt(i);
|
|
1055
|
+
}
|
|
1056
|
+
return bytes;
|
|
1057
|
+
}
|
|
1058
|
+
var SplTokenClient = class {
|
|
1059
|
+
client;
|
|
1060
|
+
programId;
|
|
1061
|
+
/**
|
|
1062
|
+
* Creates a new SplTokenClient.
|
|
1063
|
+
*
|
|
1064
|
+
* @param options - Client configuration options
|
|
1065
|
+
*/
|
|
1066
|
+
constructor({
|
|
1067
|
+
client,
|
|
1068
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
1069
|
+
}) {
|
|
1070
|
+
this.client = client;
|
|
1071
|
+
this.programId = programId;
|
|
1072
|
+
}
|
|
1073
|
+
/**
|
|
1074
|
+
* Gets the token program ID this client is configured to use.
|
|
1075
|
+
*/
|
|
1076
|
+
getProgramId() {
|
|
1077
|
+
return this.programId;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Retrieves mint account information.
|
|
1081
|
+
*
|
|
1082
|
+
* @param options - Options containing the mint public key
|
|
1083
|
+
* @returns Parsed mint information including supply, decimals, and authorities
|
|
1084
|
+
* @throws {SplTokenError} If the mint account doesn't exist or is invalid
|
|
1085
|
+
*
|
|
1086
|
+
* @example
|
|
1087
|
+
* ```typescript
|
|
1088
|
+
* const mintInfo = await tokenClient.getMintInfo({ mint: mintPubkey });
|
|
1089
|
+
* console.log(`Supply: ${mintInfo.supply}`);
|
|
1090
|
+
* console.log(`Decimals: ${mintInfo.decimals}`);
|
|
1091
|
+
* console.log(`Mint Authority: ${mintInfo.mintAuthority?.toString() ?? 'disabled'}`);
|
|
1092
|
+
* ```
|
|
1093
|
+
*/
|
|
1094
|
+
async getMintInfo({ mint }) {
|
|
1095
|
+
const accountInfo = await this.client.getAccountInfo(mint);
|
|
1096
|
+
if (!accountInfo) {
|
|
1097
|
+
throw SplTokenError.mintNotFound({ address: mint.toString() });
|
|
1098
|
+
}
|
|
1099
|
+
return parseMintAccount({ address: mint, data: decodeAccountData(accountInfo.data) });
|
|
1100
|
+
}
|
|
1101
|
+
/**
|
|
1102
|
+
* Retrieves Token-2022 native metadata from a mint.
|
|
1103
|
+
*
|
|
1104
|
+
* @param options - Options containing the mint public key
|
|
1105
|
+
* @returns Parsed token metadata, or null if no metadata extension exists
|
|
1106
|
+
* @throws {SplTokenError} If the mint account doesn't exist
|
|
1107
|
+
*
|
|
1108
|
+
* @example
|
|
1109
|
+
* ```typescript
|
|
1110
|
+
* const metadata = await tokenClient.getTokenMetadata({ mint: mintPubkey });
|
|
1111
|
+
* if (metadata) {
|
|
1112
|
+
* console.log(`Name: ${metadata.name}`);
|
|
1113
|
+
* console.log(`Symbol: ${metadata.symbol}`);
|
|
1114
|
+
* console.log(`URI: ${metadata.uri}`);
|
|
1115
|
+
* }
|
|
1116
|
+
* ```
|
|
1117
|
+
*/
|
|
1118
|
+
async getTokenMetadata({ mint }) {
|
|
1119
|
+
const accountInfo = await this.client.getAccountInfo(mint);
|
|
1120
|
+
if (!accountInfo) {
|
|
1121
|
+
throw SplTokenError.mintNotFound({ address: mint.toString() });
|
|
1122
|
+
}
|
|
1123
|
+
return parseTokenMetadata({ mint, data: decodeAccountData(accountInfo.data) });
|
|
1124
|
+
}
|
|
1125
|
+
/**
|
|
1126
|
+
* Retrieves token account information.
|
|
1127
|
+
*
|
|
1128
|
+
* @param options - Options containing the token account public key
|
|
1129
|
+
* @returns Parsed token account information
|
|
1130
|
+
* @throws {SplTokenError} If the account doesn't exist or is invalid
|
|
1131
|
+
*/
|
|
1132
|
+
async getTokenAccountInfo({
|
|
1133
|
+
tokenAccount
|
|
1134
|
+
}) {
|
|
1135
|
+
const accountInfo = await this.client.getAccountInfo(tokenAccount);
|
|
1136
|
+
if (!accountInfo) {
|
|
1137
|
+
throw SplTokenError.tokenAccountNotFound({ address: tokenAccount.toString() });
|
|
1138
|
+
}
|
|
1139
|
+
return parseTokenAccount({ address: tokenAccount, data: decodeAccountData(accountInfo.data) });
|
|
1140
|
+
}
|
|
1141
|
+
/**
|
|
1142
|
+
* Gets the token balance for a wallet.
|
|
1143
|
+
*
|
|
1144
|
+
* Automatically derives the Associated Token Address for the wallet/mint
|
|
1145
|
+
* combination and retrieves the balance.
|
|
1146
|
+
*
|
|
1147
|
+
* @param options - Options containing wallet and mint public keys
|
|
1148
|
+
* @returns The token balance in smallest units, or 0n if the ATA doesn't exist
|
|
1149
|
+
*
|
|
1150
|
+
* @example
|
|
1151
|
+
* ```typescript
|
|
1152
|
+
* const balance = await tokenClient.getBalance({ wallet: walletPubkey, mint: mintPubkey });
|
|
1153
|
+
* console.log(`Token balance: ${balance}`);
|
|
1154
|
+
* ```
|
|
1155
|
+
*/
|
|
1156
|
+
async getBalance({ wallet, mint }) {
|
|
1157
|
+
const ata = getAssociatedTokenAddressSync({ wallet, mint, programId: this.programId });
|
|
1158
|
+
const accountInfo = await this.client.getAccountInfo(ata);
|
|
1159
|
+
if (!accountInfo) {
|
|
1160
|
+
return 0n;
|
|
1161
|
+
}
|
|
1162
|
+
const tokenAccount = parseTokenAccount({ address: ata, data: decodeAccountData(accountInfo.data) });
|
|
1163
|
+
return tokenAccount.amount;
|
|
1164
|
+
}
|
|
1165
|
+
/**
|
|
1166
|
+
* Derives the Associated Token Address for a wallet and mint.
|
|
1167
|
+
*
|
|
1168
|
+
* @param options - Options containing wallet and mint public keys
|
|
1169
|
+
* @returns The derived ATA address and bump seed
|
|
1170
|
+
*
|
|
1171
|
+
* @example
|
|
1172
|
+
* ```typescript
|
|
1173
|
+
* const { address, bump } = tokenClient.getAssociatedTokenAddress({ wallet: walletPubkey, mint: mintPubkey });
|
|
1174
|
+
* console.log(`ATA: ${address.toString()}`);
|
|
1175
|
+
* ```
|
|
1176
|
+
*/
|
|
1177
|
+
getAssociatedTokenAddress({
|
|
1178
|
+
wallet,
|
|
1179
|
+
mint
|
|
1180
|
+
}) {
|
|
1181
|
+
return findAssociatedTokenAddress({ wallet, mint, programId: this.programId });
|
|
1182
|
+
}
|
|
1183
|
+
/**
|
|
1184
|
+
* Checks if an Associated Token Account exists.
|
|
1185
|
+
*
|
|
1186
|
+
* @param options - Options containing wallet and mint public keys
|
|
1187
|
+
* @returns True if the ATA exists, false otherwise
|
|
1188
|
+
*/
|
|
1189
|
+
async ataExists({ wallet, mint }) {
|
|
1190
|
+
const ata = getAssociatedTokenAddressSync({ wallet, mint, programId: this.programId });
|
|
1191
|
+
const accountInfo = await this.client.getAccountInfo(ata);
|
|
1192
|
+
return accountInfo !== null;
|
|
1193
|
+
}
|
|
1194
|
+
/**
|
|
1195
|
+
* Creates instructions for a token transfer.
|
|
1196
|
+
*
|
|
1197
|
+
* This builds the necessary instructions for transferring tokens,
|
|
1198
|
+
* optionally creating the destination ATA if it doesn't exist.
|
|
1199
|
+
*
|
|
1200
|
+
* @param params - Transfer parameters
|
|
1201
|
+
* @returns Array of instructions to execute
|
|
1202
|
+
* @throws {SplTokenError} If the mint doesn't exist
|
|
1203
|
+
*
|
|
1204
|
+
* @example
|
|
1205
|
+
* ```typescript
|
|
1206
|
+
* const instructions = await tokenClient.createTransferInstructions({
|
|
1207
|
+
* source: senderWallet,
|
|
1208
|
+
* destination: recipientWallet,
|
|
1209
|
+
* mint: mintPubkey,
|
|
1210
|
+
* amount: 1000000n,
|
|
1211
|
+
* decimals: 6,
|
|
1212
|
+
* createDestinationAta: true,
|
|
1213
|
+
* });
|
|
1214
|
+
* ```
|
|
1215
|
+
*/
|
|
1216
|
+
async createTransferInstructions(params) {
|
|
1217
|
+
const { source, destination, mint, amount, decimals, createDestinationAta = true } = params;
|
|
1218
|
+
const instructions = [];
|
|
1219
|
+
const sourceAta = getAssociatedTokenAddressSync({
|
|
1220
|
+
wallet: source,
|
|
1221
|
+
mint,
|
|
1222
|
+
programId: this.programId
|
|
1223
|
+
});
|
|
1224
|
+
const destinationAta = getAssociatedTokenAddressSync({
|
|
1225
|
+
wallet: destination,
|
|
1226
|
+
mint,
|
|
1227
|
+
programId: this.programId
|
|
1228
|
+
});
|
|
1229
|
+
if (createDestinationAta) {
|
|
1230
|
+
const destExists = await this.ataExists({ wallet: destination, mint });
|
|
1231
|
+
if (!destExists) {
|
|
1232
|
+
instructions.push(
|
|
1233
|
+
createAssociatedTokenAccountIdempotentInstruction({
|
|
1234
|
+
payer: source,
|
|
1235
|
+
associatedToken: destinationAta,
|
|
1236
|
+
owner: destination,
|
|
1237
|
+
mint,
|
|
1238
|
+
programId: this.programId
|
|
1239
|
+
})
|
|
1240
|
+
);
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
instructions.push(
|
|
1244
|
+
transferCheckedInstruction({
|
|
1245
|
+
source: sourceAta,
|
|
1246
|
+
mint,
|
|
1247
|
+
destination: destinationAta,
|
|
1248
|
+
authority: source,
|
|
1249
|
+
amount,
|
|
1250
|
+
decimals,
|
|
1251
|
+
programId: this.programId
|
|
1252
|
+
})
|
|
1253
|
+
);
|
|
1254
|
+
return instructions;
|
|
1255
|
+
}
|
|
1256
|
+
/**
|
|
1257
|
+
* Options for creating a transfer transaction.
|
|
1258
|
+
*/
|
|
1259
|
+
/**
|
|
1260
|
+
* Creates a transaction for a token transfer.
|
|
1261
|
+
*
|
|
1262
|
+
* Builds a complete transaction with all necessary instructions for
|
|
1263
|
+
* transferring tokens, including ATA creation if needed.
|
|
1264
|
+
*
|
|
1265
|
+
* @param options - Options containing params and validFrom
|
|
1266
|
+
* @returns Built transaction ready for signing
|
|
1267
|
+
*
|
|
1268
|
+
* @example
|
|
1269
|
+
* ```typescript
|
|
1270
|
+
* const blockHeight = await rialoClient.getBlockHeight();
|
|
1271
|
+
* const configHashPrefix = await rialoClient.getConfigHashPrefix();
|
|
1272
|
+
* const tx = await tokenClient.createTransferTransaction({
|
|
1273
|
+
* params: {
|
|
1274
|
+
* source: senderWallet,
|
|
1275
|
+
* destination: recipientWallet,
|
|
1276
|
+
* mint: mintPubkey,
|
|
1277
|
+
* amount: 1000000n,
|
|
1278
|
+
* decimals: 6,
|
|
1279
|
+
* },
|
|
1280
|
+
* validFrom: blockHeight,
|
|
1281
|
+
* configHashPrefix,
|
|
1282
|
+
* });
|
|
1283
|
+
*
|
|
1284
|
+
* // Sign and send
|
|
1285
|
+
* const signedTx = tx.sign([signer]);
|
|
1286
|
+
* const signature = await rialoClient.sendTransaction(signedTx.serialize());
|
|
1287
|
+
* ```
|
|
1288
|
+
*/
|
|
1289
|
+
async createTransferTransaction({
|
|
1290
|
+
params,
|
|
1291
|
+
validFrom,
|
|
1292
|
+
configHashPrefix
|
|
1293
|
+
}) {
|
|
1294
|
+
const instructions = await this.createTransferInstructions(params);
|
|
1295
|
+
const builder = tsCdk.TransactionBuilder.create().setPayer(params.source).setValidFrom(validFrom).setConfigHashPrefix(configHashPrefix);
|
|
1296
|
+
for (const ix of instructions) {
|
|
1297
|
+
builder.addInstruction(ix);
|
|
1298
|
+
}
|
|
1299
|
+
return builder.build();
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Transfers tokens from one wallet to another.
|
|
1303
|
+
*
|
|
1304
|
+
* This is a high-level convenience method that:
|
|
1305
|
+
* 1. Creates the destination ATA if needed
|
|
1306
|
+
* 2. Builds the transfer transaction
|
|
1307
|
+
* 3. Signs and sends the transaction
|
|
1308
|
+
* 4. Waits for confirmation
|
|
1309
|
+
*
|
|
1310
|
+
* @param options - Options containing params, validFrom, and signer
|
|
1311
|
+
* @returns Transaction signature
|
|
1312
|
+
*
|
|
1313
|
+
* @example
|
|
1314
|
+
* ```typescript
|
|
1315
|
+
* const blockHeight = await rialoClient.getBlockHeight();
|
|
1316
|
+
* const configHashPrefix = await rialoClient.getConfigHashPrefix();
|
|
1317
|
+
* const signature = await tokenClient.transfer({
|
|
1318
|
+
* params: {
|
|
1319
|
+
* source: senderWallet,
|
|
1320
|
+
* destination: recipientWallet,
|
|
1321
|
+
* mint: mintPubkey,
|
|
1322
|
+
* amount: 1000000n,
|
|
1323
|
+
* decimals: 6,
|
|
1324
|
+
* },
|
|
1325
|
+
* validFrom: blockHeight,
|
|
1326
|
+
* configHashPrefix,
|
|
1327
|
+
* signer: senderSigner,
|
|
1328
|
+
* });
|
|
1329
|
+
* console.log(`Transfer complete: ${signature}`);
|
|
1330
|
+
* ```
|
|
1331
|
+
*/
|
|
1332
|
+
async transfer({
|
|
1333
|
+
params,
|
|
1334
|
+
validFrom,
|
|
1335
|
+
configHashPrefix,
|
|
1336
|
+
signer
|
|
1337
|
+
}) {
|
|
1338
|
+
const tx = await this.createTransferTransaction({ params, validFrom, configHashPrefix });
|
|
1339
|
+
const signedTx = await tx.signWith(signer);
|
|
1340
|
+
const result = await this.client.sendAndConfirmTransaction(signedTx.serialize());
|
|
1341
|
+
return result.signature;
|
|
1342
|
+
}
|
|
1343
|
+
};
|
|
1344
|
+
function createSplTokenClient({
|
|
1345
|
+
client,
|
|
1346
|
+
programId
|
|
1347
|
+
}) {
|
|
1348
|
+
return new SplTokenClient({ client, programId });
|
|
1349
|
+
}
|
|
1350
|
+
/*! Bundled license information:
|
|
1351
|
+
|
|
1352
|
+
@noble/hashes/utils.js:
|
|
1353
|
+
(*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) *)
|
|
1354
|
+
*/
|
|
1355
|
+
|
|
1356
|
+
exports.ASSOCIATED_TOKEN_PROGRAM_ID = ASSOCIATED_TOKEN_PROGRAM_ID;
|
|
1357
|
+
exports.AccountType = AccountType;
|
|
1358
|
+
exports.ExtensionType = ExtensionType;
|
|
1359
|
+
exports.MINT_SIZE = MINT_SIZE;
|
|
1360
|
+
exports.SplTokenClient = SplTokenClient;
|
|
1361
|
+
exports.SplTokenError = SplTokenError;
|
|
1362
|
+
exports.SplTokenErrorCode = SplTokenErrorCode;
|
|
1363
|
+
exports.TOKEN_2022_PROGRAM_ID = TOKEN_2022_PROGRAM_ID;
|
|
1364
|
+
exports.TOKEN_ACCOUNT_SIZE = TOKEN_ACCOUNT_SIZE;
|
|
1365
|
+
exports.TOKEN_PROGRAM_ID = TOKEN_PROGRAM_ID;
|
|
1366
|
+
exports.TokenAccountState = TokenAccountState;
|
|
1367
|
+
exports.TokenInstruction = TokenInstruction;
|
|
1368
|
+
exports.createAssociatedTokenAccountIdempotentInstruction = createAssociatedTokenAccountIdempotentInstruction;
|
|
1369
|
+
exports.createAssociatedTokenAccountInstruction = createAssociatedTokenAccountInstruction;
|
|
1370
|
+
exports.createSplTokenClient = createSplTokenClient;
|
|
1371
|
+
exports.findAssociatedTokenAddress = findAssociatedTokenAddress;
|
|
1372
|
+
exports.getAssociatedTokenAddressSync = getAssociatedTokenAddressSync;
|
|
1373
|
+
exports.getMintExtensions = getMintExtensions;
|
|
1374
|
+
exports.initializeMintInstruction = initializeMintInstruction;
|
|
1375
|
+
exports.mintToInstruction = mintToInstruction;
|
|
1376
|
+
exports.parseMetadataPointerExtension = parseMetadataPointerExtension;
|
|
1377
|
+
exports.parseMintAccount = parseMintAccount;
|
|
1378
|
+
exports.parseTokenAccount = parseTokenAccount;
|
|
1379
|
+
exports.parseTokenMetadata = parseTokenMetadata;
|
|
1380
|
+
exports.transferCheckedInstruction = transferCheckedInstruction;
|
|
1381
|
+
exports.transferInstruction = transferInstruction;
|
|
1382
|
+
//# sourceMappingURL=index.js.map
|
|
1383
|
+
//# sourceMappingURL=index.js.map
|