@rialo/spl-token 0.3.0-alpha.0 → 0.3.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/dist/index.d.mts +1374 -164
- package/dist/index.d.ts +1374 -164
- package/dist/index.js +2235 -682
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2201 -684
- package/dist/index.mjs.map +1 -1
- package/package.json +16 -4
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var tsCdk = require('@rialo/ts-cdk');
|
|
4
4
|
|
|
5
|
-
// src/
|
|
5
|
+
// src/builders/mint-builder.ts
|
|
6
6
|
|
|
7
7
|
// src/constants.ts
|
|
8
8
|
var TOKEN_2022_PROGRAM_ID = "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb";
|
|
@@ -85,157 +85,501 @@ var TokenInstruction = /* @__PURE__ */ ((TokenInstruction2) => {
|
|
|
85
85
|
TokenInstruction2[TokenInstruction2["InitializeAccount3"] = 18] = "InitializeAccount3";
|
|
86
86
|
TokenInstruction2[TokenInstruction2["InitializeMultisig2"] = 19] = "InitializeMultisig2";
|
|
87
87
|
TokenInstruction2[TokenInstruction2["InitializeMint2"] = 20] = "InitializeMint2";
|
|
88
|
+
TokenInstruction2[TokenInstruction2["TransferFeeExtension"] = 26] = "TransferFeeExtension";
|
|
89
|
+
TokenInstruction2[TokenInstruction2["InitializeNonTransferableMint"] = 32] = "InitializeNonTransferableMint";
|
|
90
|
+
TokenInstruction2[TokenInstruction2["InitializePermanentDelegate"] = 35] = "InitializePermanentDelegate";
|
|
91
|
+
TokenInstruction2[TokenInstruction2["TransferHookExtension"] = 36] = "TransferHookExtension";
|
|
92
|
+
TokenInstruction2[TokenInstruction2["MetadataPointerExtension"] = 39] = "MetadataPointerExtension";
|
|
88
93
|
return TokenInstruction2;
|
|
89
94
|
})(TokenInstruction || {});
|
|
90
95
|
var TLV_TYPE_SIZE = 2;
|
|
91
96
|
var TLV_LENGTH_SIZE = 2;
|
|
92
|
-
var MINT_EXTENSIONS_OFFSET =
|
|
97
|
+
var MINT_EXTENSIONS_OFFSET = TOKEN_ACCOUNT_SIZE + 1;
|
|
98
|
+
var TOKEN_ACCOUNT_EXTENSIONS_OFFSET = TOKEN_ACCOUNT_SIZE + 1;
|
|
93
99
|
|
|
94
|
-
//
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
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
|
-
}
|
|
100
|
+
// node_modules/@noble/hashes/utils.js
|
|
101
|
+
function isBytes(a) {
|
|
102
|
+
return a instanceof Uint8Array || ArrayBuffer.isView(a) && a.constructor.name === "Uint8Array";
|
|
103
|
+
}
|
|
104
|
+
function abytes(value, length, title = "") {
|
|
105
|
+
const bytes = isBytes(value);
|
|
106
|
+
const len = value?.length;
|
|
107
|
+
const needsLen = length !== void 0;
|
|
108
|
+
if (!bytes || needsLen) {
|
|
109
|
+
const prefix = title && `"${title}" `;
|
|
110
|
+
const ofLen = "";
|
|
111
|
+
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
112
|
+
throw new Error(prefix + "expected Uint8Array" + ofLen + ", got " + got);
|
|
119
113
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
114
|
+
return value;
|
|
115
|
+
}
|
|
116
|
+
function aexists(instance, checkFinished = true) {
|
|
117
|
+
if (instance.destroyed)
|
|
118
|
+
throw new Error("Hash instance has been destroyed");
|
|
119
|
+
if (checkFinished && instance.finished)
|
|
120
|
+
throw new Error("Hash#digest() has already been called");
|
|
121
|
+
}
|
|
122
|
+
function aoutput(out, instance) {
|
|
123
|
+
abytes(out, void 0, "digestInto() output");
|
|
124
|
+
const min = instance.outputLen;
|
|
125
|
+
if (out.length < min) {
|
|
126
|
+
throw new Error('"digestInto() output" expected to be of length >=' + min);
|
|
130
127
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
*/
|
|
136
|
-
static invalidTokenAccount({ reason }) {
|
|
137
|
-
return new _SplTokenError({
|
|
138
|
-
code: "INVALID_TOKEN_ACCOUNT" /* INVALID_TOKEN_ACCOUNT */,
|
|
139
|
-
message: `Invalid token account: ${reason}`
|
|
140
|
-
});
|
|
128
|
+
}
|
|
129
|
+
function clean(...arrays) {
|
|
130
|
+
for (let i = 0; i < arrays.length; i++) {
|
|
131
|
+
arrays[i].fill(0);
|
|
141
132
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
133
|
+
}
|
|
134
|
+
function createView(arr) {
|
|
135
|
+
return new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
|
|
136
|
+
}
|
|
137
|
+
function rotr(word, shift) {
|
|
138
|
+
return word << 32 - shift | word >>> shift;
|
|
139
|
+
}
|
|
140
|
+
function createHasher(hashCons, info = {}) {
|
|
141
|
+
const hashC = (msg, opts) => hashCons(opts).update(msg).digest();
|
|
142
|
+
const tmp = hashCons(void 0);
|
|
143
|
+
hashC.outputLen = tmp.outputLen;
|
|
144
|
+
hashC.blockLen = tmp.blockLen;
|
|
145
|
+
hashC.create = (opts) => hashCons(opts);
|
|
146
|
+
Object.assign(hashC, info);
|
|
147
|
+
return Object.freeze(hashC);
|
|
148
|
+
}
|
|
149
|
+
var oidNist = (suffix) => ({
|
|
150
|
+
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
// node_modules/@noble/hashes/_md.js
|
|
154
|
+
function Chi(a, b, c) {
|
|
155
|
+
return a & b ^ ~a & c;
|
|
156
|
+
}
|
|
157
|
+
function Maj(a, b, c) {
|
|
158
|
+
return a & b ^ a & c ^ b & c;
|
|
159
|
+
}
|
|
160
|
+
var HashMD = class {
|
|
161
|
+
blockLen;
|
|
162
|
+
outputLen;
|
|
163
|
+
padOffset;
|
|
164
|
+
isLE;
|
|
165
|
+
// For partial updates less than block size
|
|
166
|
+
buffer;
|
|
167
|
+
view;
|
|
168
|
+
finished = false;
|
|
169
|
+
length = 0;
|
|
170
|
+
pos = 0;
|
|
171
|
+
destroyed = false;
|
|
172
|
+
constructor(blockLen, outputLen, padOffset, isLE) {
|
|
173
|
+
this.blockLen = blockLen;
|
|
174
|
+
this.outputLen = outputLen;
|
|
175
|
+
this.padOffset = padOffset;
|
|
176
|
+
this.isLE = isLE;
|
|
177
|
+
this.buffer = new Uint8Array(blockLen);
|
|
178
|
+
this.view = createView(this.buffer);
|
|
153
179
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
180
|
+
update(data) {
|
|
181
|
+
aexists(this);
|
|
182
|
+
abytes(data);
|
|
183
|
+
const { view, buffer, blockLen } = this;
|
|
184
|
+
const len = data.length;
|
|
185
|
+
for (let pos = 0; pos < len; ) {
|
|
186
|
+
const take = Math.min(blockLen - this.pos, len - pos);
|
|
187
|
+
if (take === blockLen) {
|
|
188
|
+
const dataView = createView(data);
|
|
189
|
+
for (; blockLen <= len - pos; pos += blockLen)
|
|
190
|
+
this.process(dataView, pos);
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
buffer.set(data.subarray(pos, pos + take), this.pos);
|
|
194
|
+
this.pos += take;
|
|
195
|
+
pos += take;
|
|
196
|
+
if (this.pos === blockLen) {
|
|
197
|
+
this.process(view, 0);
|
|
198
|
+
this.pos = 0;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
this.length += data.length;
|
|
202
|
+
this.roundClean();
|
|
203
|
+
return this;
|
|
165
204
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
205
|
+
digestInto(out) {
|
|
206
|
+
aexists(this);
|
|
207
|
+
aoutput(out, this);
|
|
208
|
+
this.finished = true;
|
|
209
|
+
const { buffer, view, blockLen, isLE } = this;
|
|
210
|
+
let { pos } = this;
|
|
211
|
+
buffer[pos++] = 128;
|
|
212
|
+
clean(this.buffer.subarray(pos));
|
|
213
|
+
if (this.padOffset > blockLen - pos) {
|
|
214
|
+
this.process(view, 0);
|
|
215
|
+
pos = 0;
|
|
216
|
+
}
|
|
217
|
+
for (let i = pos; i < blockLen; i++)
|
|
218
|
+
buffer[i] = 0;
|
|
219
|
+
view.setBigUint64(blockLen - 8, BigInt(this.length * 8), isLE);
|
|
220
|
+
this.process(view, 0);
|
|
221
|
+
const oview = createView(out);
|
|
222
|
+
const len = this.outputLen;
|
|
223
|
+
if (len % 4)
|
|
224
|
+
throw new Error("_sha2: outputLen must be aligned to 32bit");
|
|
225
|
+
const outLen = len / 4;
|
|
226
|
+
const state = this.get();
|
|
227
|
+
if (outLen > state.length)
|
|
228
|
+
throw new Error("_sha2: outputLen bigger than state");
|
|
229
|
+
for (let i = 0; i < outLen; i++)
|
|
230
|
+
oview.setUint32(4 * i, state[i], isLE);
|
|
177
231
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
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
|
-
});
|
|
232
|
+
digest() {
|
|
233
|
+
const { buffer, outputLen } = this;
|
|
234
|
+
this.digestInto(buffer);
|
|
235
|
+
const res = buffer.slice(0, outputLen);
|
|
236
|
+
this.destroy();
|
|
237
|
+
return res;
|
|
192
238
|
}
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
239
|
+
_cloneInto(to) {
|
|
240
|
+
to ||= new this.constructor();
|
|
241
|
+
to.set(...this.get());
|
|
242
|
+
const { blockLen, buffer, length, finished, destroyed, pos } = this;
|
|
243
|
+
to.destroyed = destroyed;
|
|
244
|
+
to.finished = finished;
|
|
245
|
+
to.length = length;
|
|
246
|
+
to.pos = pos;
|
|
247
|
+
if (length % blockLen)
|
|
248
|
+
to.buffer.set(buffer);
|
|
249
|
+
return to;
|
|
203
250
|
}
|
|
204
|
-
|
|
205
|
-
|
|
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
|
-
});
|
|
251
|
+
clone() {
|
|
252
|
+
return this._cloneInto();
|
|
214
253
|
}
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
254
|
+
};
|
|
255
|
+
var SHA256_IV = /* @__PURE__ */ Uint32Array.from([
|
|
256
|
+
1779033703,
|
|
257
|
+
3144134277,
|
|
258
|
+
1013904242,
|
|
259
|
+
2773480762,
|
|
260
|
+
1359893119,
|
|
261
|
+
2600822924,
|
|
262
|
+
528734635,
|
|
263
|
+
1541459225
|
|
264
|
+
]);
|
|
265
|
+
|
|
266
|
+
// node_modules/@noble/hashes/sha2.js
|
|
267
|
+
var SHA256_K = /* @__PURE__ */ Uint32Array.from([
|
|
268
|
+
1116352408,
|
|
269
|
+
1899447441,
|
|
270
|
+
3049323471,
|
|
271
|
+
3921009573,
|
|
272
|
+
961987163,
|
|
273
|
+
1508970993,
|
|
274
|
+
2453635748,
|
|
275
|
+
2870763221,
|
|
276
|
+
3624381080,
|
|
277
|
+
310598401,
|
|
278
|
+
607225278,
|
|
279
|
+
1426881987,
|
|
280
|
+
1925078388,
|
|
281
|
+
2162078206,
|
|
282
|
+
2614888103,
|
|
283
|
+
3248222580,
|
|
284
|
+
3835390401,
|
|
285
|
+
4022224774,
|
|
286
|
+
264347078,
|
|
287
|
+
604807628,
|
|
288
|
+
770255983,
|
|
289
|
+
1249150122,
|
|
290
|
+
1555081692,
|
|
291
|
+
1996064986,
|
|
292
|
+
2554220882,
|
|
293
|
+
2821834349,
|
|
294
|
+
2952996808,
|
|
295
|
+
3210313671,
|
|
296
|
+
3336571891,
|
|
297
|
+
3584528711,
|
|
298
|
+
113926993,
|
|
299
|
+
338241895,
|
|
300
|
+
666307205,
|
|
301
|
+
773529912,
|
|
302
|
+
1294757372,
|
|
303
|
+
1396182291,
|
|
304
|
+
1695183700,
|
|
305
|
+
1986661051,
|
|
306
|
+
2177026350,
|
|
307
|
+
2456956037,
|
|
308
|
+
2730485921,
|
|
309
|
+
2820302411,
|
|
310
|
+
3259730800,
|
|
311
|
+
3345764771,
|
|
312
|
+
3516065817,
|
|
313
|
+
3600352804,
|
|
314
|
+
4094571909,
|
|
315
|
+
275423344,
|
|
316
|
+
430227734,
|
|
317
|
+
506948616,
|
|
318
|
+
659060556,
|
|
319
|
+
883997877,
|
|
320
|
+
958139571,
|
|
321
|
+
1322822218,
|
|
322
|
+
1537002063,
|
|
323
|
+
1747873779,
|
|
324
|
+
1955562222,
|
|
325
|
+
2024104815,
|
|
326
|
+
2227730452,
|
|
327
|
+
2361852424,
|
|
328
|
+
2428436474,
|
|
329
|
+
2756734187,
|
|
330
|
+
3204031479,
|
|
331
|
+
3329325298
|
|
332
|
+
]);
|
|
333
|
+
var SHA256_W = /* @__PURE__ */ new Uint32Array(64);
|
|
334
|
+
var SHA2_32B = class extends HashMD {
|
|
335
|
+
constructor(outputLen) {
|
|
336
|
+
super(64, outputLen, 8, false);
|
|
225
337
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
338
|
+
get() {
|
|
339
|
+
const { A, B, C, D, E, F, G, H } = this;
|
|
340
|
+
return [A, B, C, D, E, F, G, H];
|
|
341
|
+
}
|
|
342
|
+
// prettier-ignore
|
|
343
|
+
set(A, B, C, D, E, F, G, H) {
|
|
344
|
+
this.A = A | 0;
|
|
345
|
+
this.B = B | 0;
|
|
346
|
+
this.C = C | 0;
|
|
347
|
+
this.D = D | 0;
|
|
348
|
+
this.E = E | 0;
|
|
349
|
+
this.F = F | 0;
|
|
350
|
+
this.G = G | 0;
|
|
351
|
+
this.H = H | 0;
|
|
352
|
+
}
|
|
353
|
+
process(view, offset) {
|
|
354
|
+
for (let i = 0; i < 16; i++, offset += 4)
|
|
355
|
+
SHA256_W[i] = view.getUint32(offset, false);
|
|
356
|
+
for (let i = 16; i < 64; i++) {
|
|
357
|
+
const W15 = SHA256_W[i - 15];
|
|
358
|
+
const W2 = SHA256_W[i - 2];
|
|
359
|
+
const s0 = rotr(W15, 7) ^ rotr(W15, 18) ^ W15 >>> 3;
|
|
360
|
+
const s1 = rotr(W2, 17) ^ rotr(W2, 19) ^ W2 >>> 10;
|
|
361
|
+
SHA256_W[i] = s1 + SHA256_W[i - 7] + s0 + SHA256_W[i - 16] | 0;
|
|
362
|
+
}
|
|
363
|
+
let { A, B, C, D, E, F, G, H } = this;
|
|
364
|
+
for (let i = 0; i < 64; i++) {
|
|
365
|
+
const sigma1 = rotr(E, 6) ^ rotr(E, 11) ^ rotr(E, 25);
|
|
366
|
+
const T1 = H + sigma1 + Chi(E, F, G) + SHA256_K[i] + SHA256_W[i] | 0;
|
|
367
|
+
const sigma0 = rotr(A, 2) ^ rotr(A, 13) ^ rotr(A, 22);
|
|
368
|
+
const T2 = sigma0 + Maj(A, B, C) | 0;
|
|
369
|
+
H = G;
|
|
370
|
+
G = F;
|
|
371
|
+
F = E;
|
|
372
|
+
E = D + T1 | 0;
|
|
373
|
+
D = C;
|
|
374
|
+
C = B;
|
|
375
|
+
B = A;
|
|
376
|
+
A = T1 + T2 | 0;
|
|
377
|
+
}
|
|
378
|
+
A = A + this.A | 0;
|
|
379
|
+
B = B + this.B | 0;
|
|
380
|
+
C = C + this.C | 0;
|
|
381
|
+
D = D + this.D | 0;
|
|
382
|
+
E = E + this.E | 0;
|
|
383
|
+
F = F + this.F | 0;
|
|
384
|
+
G = G + this.G | 0;
|
|
385
|
+
H = H + this.H | 0;
|
|
386
|
+
this.set(A, B, C, D, E, F, G, H);
|
|
387
|
+
}
|
|
388
|
+
roundClean() {
|
|
389
|
+
clean(SHA256_W);
|
|
390
|
+
}
|
|
391
|
+
destroy() {
|
|
392
|
+
this.set(0, 0, 0, 0, 0, 0, 0, 0);
|
|
393
|
+
clean(this.buffer);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
var _SHA256 = class extends SHA2_32B {
|
|
397
|
+
// We cannot use array here since array allows indexing by variable
|
|
398
|
+
// which means optimizer/compiler cannot use registers.
|
|
399
|
+
A = SHA256_IV[0] | 0;
|
|
400
|
+
B = SHA256_IV[1] | 0;
|
|
401
|
+
C = SHA256_IV[2] | 0;
|
|
402
|
+
D = SHA256_IV[3] | 0;
|
|
403
|
+
E = SHA256_IV[4] | 0;
|
|
404
|
+
F = SHA256_IV[5] | 0;
|
|
405
|
+
G = SHA256_IV[6] | 0;
|
|
406
|
+
H = SHA256_IV[7] | 0;
|
|
407
|
+
constructor() {
|
|
408
|
+
super(32);
|
|
409
|
+
}
|
|
410
|
+
};
|
|
411
|
+
var sha256 = /* @__PURE__ */ createHasher(
|
|
412
|
+
() => new _SHA256(),
|
|
413
|
+
/* @__PURE__ */ oidNist(1)
|
|
414
|
+
);
|
|
415
|
+
var TOKEN_METADATA_NAMESPACE = "rialo_s_spl_token_metadata_interface";
|
|
416
|
+
var TOKEN_METADATA_DISCRIMINATOR_LENGTH = 8;
|
|
417
|
+
function metadataDiscriminator(label) {
|
|
418
|
+
const input = new TextEncoder().encode(`${TOKEN_METADATA_NAMESPACE}:${label}`);
|
|
419
|
+
return sha256(input).slice(0, TOKEN_METADATA_DISCRIMINATOR_LENGTH);
|
|
420
|
+
}
|
|
421
|
+
function writeU32LE({
|
|
422
|
+
data,
|
|
423
|
+
offset,
|
|
424
|
+
value
|
|
425
|
+
}) {
|
|
426
|
+
data[offset] = value & 255;
|
|
427
|
+
data[offset + 1] = value >>> 8 & 255;
|
|
428
|
+
data[offset + 2] = value >>> 16 & 255;
|
|
429
|
+
data[offset + 3] = value >>> 24 & 255;
|
|
430
|
+
}
|
|
431
|
+
function encodeLengthPrefixedString(value) {
|
|
432
|
+
const bytes = new TextEncoder().encode(value);
|
|
433
|
+
const buffer = new Uint8Array(4 + bytes.length);
|
|
434
|
+
writeU32LE({ data: buffer, offset: 0, value: bytes.length });
|
|
435
|
+
buffer.set(bytes, 4);
|
|
436
|
+
return buffer;
|
|
437
|
+
}
|
|
438
|
+
function encodeAdditionalMetadata(additionalMetadata) {
|
|
439
|
+
const entries = additionalMetadata.flatMap(([key, value]) => [
|
|
440
|
+
encodeLengthPrefixedString(key),
|
|
441
|
+
encodeLengthPrefixedString(value)
|
|
442
|
+
]);
|
|
443
|
+
const totalLength = 4 + entries.reduce((sum, entry) => sum + entry.length, 0);
|
|
444
|
+
const buffer = new Uint8Array(totalLength);
|
|
445
|
+
writeU32LE({ data: buffer, offset: 0, value: additionalMetadata.length });
|
|
446
|
+
let offset = 4;
|
|
447
|
+
for (const entry of entries) {
|
|
448
|
+
buffer.set(entry, offset);
|
|
449
|
+
offset += entry.length;
|
|
450
|
+
}
|
|
451
|
+
return buffer;
|
|
452
|
+
}
|
|
453
|
+
function getTokenMetadataDataSize({
|
|
454
|
+
name,
|
|
455
|
+
symbol,
|
|
456
|
+
uri,
|
|
457
|
+
additionalMetadata = []
|
|
458
|
+
}) {
|
|
459
|
+
return 32 + 32 + encodeLengthPrefixedString(name).length + encodeLengthPrefixedString(symbol).length + encodeLengthPrefixedString(uri).length + encodeAdditionalMetadata(additionalMetadata).length;
|
|
460
|
+
}
|
|
461
|
+
function initializeTokenMetadataInstruction({
|
|
462
|
+
mint,
|
|
463
|
+
updateAuthority,
|
|
464
|
+
mintAuthority,
|
|
465
|
+
name,
|
|
466
|
+
symbol,
|
|
467
|
+
uri,
|
|
468
|
+
additionalMetadata = [],
|
|
469
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
470
|
+
}) {
|
|
471
|
+
const nameBytes = encodeLengthPrefixedString(name);
|
|
472
|
+
const symbolBytes = encodeLengthPrefixedString(symbol);
|
|
473
|
+
const uriBytes = encodeLengthPrefixedString(uri);
|
|
474
|
+
const hasAdditionalMetadata = additionalMetadata.length > 0;
|
|
475
|
+
const additionalBytes = hasAdditionalMetadata ? encodeAdditionalMetadata(additionalMetadata) : null;
|
|
476
|
+
const dataLength = TOKEN_METADATA_DISCRIMINATOR_LENGTH + nameBytes.length + symbolBytes.length + uriBytes.length + (additionalBytes?.length ?? 0);
|
|
477
|
+
const data = new Uint8Array(dataLength);
|
|
478
|
+
data.set(metadataDiscriminator("initialize_account"), 0);
|
|
479
|
+
let offset = TOKEN_METADATA_DISCRIMINATOR_LENGTH;
|
|
480
|
+
data.set(nameBytes, offset);
|
|
481
|
+
offset += nameBytes.length;
|
|
482
|
+
data.set(symbolBytes, offset);
|
|
483
|
+
offset += symbolBytes.length;
|
|
484
|
+
data.set(uriBytes, offset);
|
|
485
|
+
if (additionalBytes) {
|
|
486
|
+
offset += uriBytes.length;
|
|
487
|
+
data.set(additionalBytes, offset);
|
|
237
488
|
}
|
|
489
|
+
return {
|
|
490
|
+
programId,
|
|
491
|
+
accounts: [
|
|
492
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
493
|
+
{ pubkey: updateAuthority, isSigner: false, isWritable: false },
|
|
494
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
495
|
+
{ pubkey: mintAuthority, isSigner: true, isWritable: false }
|
|
496
|
+
],
|
|
497
|
+
data
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
// src/helpers/size.ts
|
|
502
|
+
var TLV_HEADER_SIZE = TLV_TYPE_SIZE + TLV_LENGTH_SIZE;
|
|
503
|
+
var ACCOUNT_TYPE_SIZE = 1;
|
|
504
|
+
var EXTENSION_SIZES = {
|
|
505
|
+
[1 /* TransferFeeConfig */]: 108,
|
|
506
|
+
[2 /* TransferFeeAmount */]: 8,
|
|
507
|
+
[3 /* MintCloseAuthority */]: 32,
|
|
508
|
+
[4 /* ConfidentialTransferMint */]: 97,
|
|
509
|
+
[5 /* ConfidentialTransferAccount */]: 286,
|
|
510
|
+
[6 /* DefaultAccountState */]: 1,
|
|
511
|
+
[7 /* ImmutableOwner */]: 0,
|
|
512
|
+
[8 /* MemoTransfer */]: 1,
|
|
513
|
+
[9 /* NonTransferable */]: 0,
|
|
514
|
+
[10 /* InterestBearingConfig */]: 52,
|
|
515
|
+
[11 /* CpiGuard */]: 1,
|
|
516
|
+
[12 /* PermanentDelegate */]: 32,
|
|
517
|
+
[13 /* NonTransferableAccount */]: 0,
|
|
518
|
+
[14 /* TransferHook */]: 64,
|
|
519
|
+
[15 /* TransferHookAccount */]: 1,
|
|
520
|
+
[16 /* ConfidentialTransferFeeConfig */]: 64,
|
|
521
|
+
[17 /* ConfidentialTransferFeeAmount */]: 32,
|
|
522
|
+
[18 /* MetadataPointer */]: 64,
|
|
523
|
+
// TokenMetadata is variable-sized, must use getMetadataExtensionSize
|
|
524
|
+
[20 /* GroupPointer */]: 64,
|
|
525
|
+
[21 /* TokenGroup */]: 72,
|
|
526
|
+
[22 /* GroupMemberPointer */]: 64,
|
|
527
|
+
[23 /* TokenGroupMember */]: 68
|
|
238
528
|
};
|
|
529
|
+
function getMintSizeWithExtensions({
|
|
530
|
+
extensions,
|
|
531
|
+
metadataSize
|
|
532
|
+
}) {
|
|
533
|
+
if (extensions.length === 0) {
|
|
534
|
+
return MINT_SIZE;
|
|
535
|
+
}
|
|
536
|
+
let totalSize = TOKEN_ACCOUNT_SIZE + ACCOUNT_TYPE_SIZE;
|
|
537
|
+
for (const extension of extensions) {
|
|
538
|
+
if (extension === 19 /* TokenMetadata */) {
|
|
539
|
+
if (metadataSize === void 0) {
|
|
540
|
+
throw new Error(
|
|
541
|
+
"metadataSize is required when ExtensionType.TokenMetadata is included. Use getMetadataExtensionSize() to calculate it."
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
totalSize += TLV_HEADER_SIZE + metadataSize;
|
|
545
|
+
} else {
|
|
546
|
+
const extSize = EXTENSION_SIZES[extension];
|
|
547
|
+
if (extSize === void 0) {
|
|
548
|
+
throw new Error(`Unknown extension type: ${extension}`);
|
|
549
|
+
}
|
|
550
|
+
totalSize += TLV_HEADER_SIZE + extSize;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
return totalSize;
|
|
554
|
+
}
|
|
555
|
+
function getMetadataExtensionSize({
|
|
556
|
+
name,
|
|
557
|
+
symbol,
|
|
558
|
+
uri,
|
|
559
|
+
additionalMetadata = []
|
|
560
|
+
}) {
|
|
561
|
+
return getTokenMetadataDataSize({ name, symbol, uri, additionalMetadata });
|
|
562
|
+
}
|
|
563
|
+
async function getMinRentForMint(client, options) {
|
|
564
|
+
const size = getMintSizeWithExtensions(options);
|
|
565
|
+
return await client.getMinimumBalanceForRentExemption(BigInt(size));
|
|
566
|
+
}
|
|
567
|
+
function getMintSizeWithMetadata({
|
|
568
|
+
name,
|
|
569
|
+
symbol,
|
|
570
|
+
uri,
|
|
571
|
+
additionalMetadata = []
|
|
572
|
+
}) {
|
|
573
|
+
const metadataSize = getMetadataExtensionSize({ name, symbol, uri, additionalMetadata });
|
|
574
|
+
return getMintSizeWithExtensions({
|
|
575
|
+
extensions: [18 /* MetadataPointer */, 19 /* TokenMetadata */],
|
|
576
|
+
metadataSize
|
|
577
|
+
});
|
|
578
|
+
}
|
|
579
|
+
async function getMinRentForMintWithMetadata(client, metadata) {
|
|
580
|
+
const size = getMintSizeWithMetadata(metadata);
|
|
581
|
+
return await client.getMinimumBalanceForRentExemption(BigInt(size));
|
|
582
|
+
}
|
|
239
583
|
function createAssociatedTokenAccountInstruction({
|
|
240
584
|
payer,
|
|
241
585
|
associatedToken,
|
|
@@ -283,7 +627,7 @@ function createAssociatedTokenAccountIdempotentInstruction({
|
|
|
283
627
|
};
|
|
284
628
|
}
|
|
285
629
|
|
|
286
|
-
// src/
|
|
630
|
+
// src/utils/bytes.ts
|
|
287
631
|
function writeU64LE({
|
|
288
632
|
data,
|
|
289
633
|
offset,
|
|
@@ -293,8 +637,96 @@ function writeU64LE({
|
|
|
293
637
|
data[offset + i] = Number(value >> BigInt(i * 8) & 0xffn);
|
|
294
638
|
}
|
|
295
639
|
}
|
|
640
|
+
function writeU16LE({
|
|
641
|
+
data,
|
|
642
|
+
offset,
|
|
643
|
+
value
|
|
644
|
+
}) {
|
|
645
|
+
data[offset] = value & 255;
|
|
646
|
+
data[offset + 1] = value >> 8 & 255;
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// src/instructions/utils.ts
|
|
650
|
+
function isAuthoritySigner({ signers }) {
|
|
651
|
+
return (signers?.length ?? 0) === 0;
|
|
652
|
+
}
|
|
653
|
+
function writeOptionalNonZeroPubkey({
|
|
654
|
+
data,
|
|
655
|
+
offset,
|
|
656
|
+
value
|
|
657
|
+
}) {
|
|
658
|
+
if (value) {
|
|
659
|
+
data.set(value.toBytes(), offset);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
function writeCOptionPubkey({
|
|
663
|
+
data,
|
|
664
|
+
offset,
|
|
665
|
+
value
|
|
666
|
+
}) {
|
|
667
|
+
if (value) {
|
|
668
|
+
data[offset] = 1;
|
|
669
|
+
data.set(value.toBytes(), offset + 1);
|
|
670
|
+
return 33;
|
|
671
|
+
}
|
|
672
|
+
data[offset] = 0;
|
|
673
|
+
return 1;
|
|
674
|
+
}
|
|
675
|
+
function appendSigners({
|
|
676
|
+
accounts,
|
|
677
|
+
signers
|
|
678
|
+
}) {
|
|
679
|
+
for (const signer of signers ?? []) {
|
|
680
|
+
accounts.push({ pubkey: signer, isSigner: true, isWritable: false });
|
|
681
|
+
}
|
|
682
|
+
}
|
|
296
683
|
|
|
297
|
-
// src/instructions/
|
|
684
|
+
// src/instructions/metadata-pointer.ts
|
|
685
|
+
var METADATA_POINTER_INSTRUCTION_INITIALIZE = 0;
|
|
686
|
+
var METADATA_POINTER_INSTRUCTION_UPDATE = 1;
|
|
687
|
+
function initializeMetadataPointerInstruction({
|
|
688
|
+
mint,
|
|
689
|
+
authority,
|
|
690
|
+
metadataAddress,
|
|
691
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
692
|
+
}) {
|
|
693
|
+
const data = new Uint8Array(66);
|
|
694
|
+
data[0] = 39 /* MetadataPointerExtension */;
|
|
695
|
+
data[1] = METADATA_POINTER_INSTRUCTION_INITIALIZE;
|
|
696
|
+
writeOptionalNonZeroPubkey({ data, offset: 2, value: authority ?? null });
|
|
697
|
+
writeOptionalNonZeroPubkey({
|
|
698
|
+
data,
|
|
699
|
+
offset: 34,
|
|
700
|
+
value: metadataAddress ?? null
|
|
701
|
+
});
|
|
702
|
+
return {
|
|
703
|
+
programId,
|
|
704
|
+
accounts: [{ pubkey: mint, isSigner: false, isWritable: true }],
|
|
705
|
+
data
|
|
706
|
+
};
|
|
707
|
+
}
|
|
708
|
+
function updateMetadataPointerInstruction({
|
|
709
|
+
mint,
|
|
710
|
+
authority,
|
|
711
|
+
metadataAddress,
|
|
712
|
+
signers,
|
|
713
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
714
|
+
}) {
|
|
715
|
+
const data = new Uint8Array(34);
|
|
716
|
+
data[0] = 39 /* MetadataPointerExtension */;
|
|
717
|
+
data[1] = METADATA_POINTER_INSTRUCTION_UPDATE;
|
|
718
|
+
writeOptionalNonZeroPubkey({
|
|
719
|
+
data,
|
|
720
|
+
offset: 2,
|
|
721
|
+
value: metadataAddress ?? null
|
|
722
|
+
});
|
|
723
|
+
const accounts = [
|
|
724
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
725
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
726
|
+
];
|
|
727
|
+
appendSigners({ accounts, signers });
|
|
728
|
+
return { programId, accounts, data };
|
|
729
|
+
}
|
|
298
730
|
function initializeMintInstruction({
|
|
299
731
|
mint,
|
|
300
732
|
decimals,
|
|
@@ -330,29 +762,43 @@ function mintToInstruction({
|
|
|
330
762
|
destination,
|
|
331
763
|
authority,
|
|
332
764
|
amount,
|
|
765
|
+
signers,
|
|
333
766
|
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
334
767
|
}) {
|
|
335
768
|
const data = new Uint8Array(9);
|
|
336
769
|
data[0] = 7 /* MintTo */;
|
|
337
770
|
writeU64LE({ data, offset: 1, value: amount });
|
|
771
|
+
const accounts = [
|
|
772
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
773
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
774
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
775
|
+
];
|
|
776
|
+
appendSigners({ accounts, signers });
|
|
777
|
+
return { programId, accounts, data };
|
|
778
|
+
}
|
|
779
|
+
function initializeNonTransferableMintInstruction({
|
|
780
|
+
mint,
|
|
781
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
782
|
+
}) {
|
|
338
783
|
return {
|
|
339
784
|
programId,
|
|
340
|
-
accounts: [
|
|
341
|
-
|
|
342
|
-
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
343
|
-
{ pubkey: authority, isSigner: true, isWritable: false }
|
|
344
|
-
],
|
|
345
|
-
data
|
|
785
|
+
accounts: [{ pubkey: mint, isSigner: false, isWritable: true }],
|
|
786
|
+
data: new Uint8Array([32 /* InitializeNonTransferableMint */])
|
|
346
787
|
};
|
|
347
788
|
}
|
|
348
|
-
function
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
789
|
+
function initializePermanentDelegateInstruction({
|
|
790
|
+
mint,
|
|
791
|
+
delegate,
|
|
792
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
352
793
|
}) {
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
794
|
+
const data = new Uint8Array(33);
|
|
795
|
+
data[0] = 35 /* InitializePermanentDelegate */;
|
|
796
|
+
data.set(delegate.toBytes(), 1);
|
|
797
|
+
return {
|
|
798
|
+
programId,
|
|
799
|
+
accounts: [{ pubkey: mint, isSigner: false, isWritable: true }],
|
|
800
|
+
data
|
|
801
|
+
};
|
|
356
802
|
}
|
|
357
803
|
function transferCheckedInstruction({
|
|
358
804
|
source,
|
|
@@ -361,359 +807,289 @@ function transferCheckedInstruction({
|
|
|
361
807
|
authority,
|
|
362
808
|
amount,
|
|
363
809
|
decimals,
|
|
810
|
+
signers,
|
|
364
811
|
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
365
812
|
}) {
|
|
366
813
|
const data = new Uint8Array(10);
|
|
367
814
|
data[0] = 12 /* TransferChecked */;
|
|
368
|
-
|
|
815
|
+
writeU64LE({ data, offset: 1, value: amount });
|
|
369
816
|
data[9] = decimals;
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
data
|
|
379
|
-
};
|
|
817
|
+
const accounts = [
|
|
818
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
819
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
820
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
821
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
822
|
+
];
|
|
823
|
+
appendSigners({ accounts, signers });
|
|
824
|
+
return { programId, accounts, data };
|
|
380
825
|
}
|
|
381
826
|
function transferInstruction({
|
|
382
827
|
source,
|
|
383
828
|
destination,
|
|
384
829
|
authority,
|
|
385
830
|
amount,
|
|
831
|
+
signers,
|
|
386
832
|
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
387
833
|
}) {
|
|
388
834
|
const data = new Uint8Array(9);
|
|
389
835
|
data[0] = 3 /* Transfer */;
|
|
390
|
-
|
|
836
|
+
writeU64LE({ data, offset: 1, value: amount });
|
|
837
|
+
const accounts = [
|
|
838
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
839
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
840
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
841
|
+
];
|
|
842
|
+
appendSigners({ accounts, signers });
|
|
843
|
+
return { programId, accounts, data };
|
|
844
|
+
}
|
|
845
|
+
var TRANSFER_FEE_INSTRUCTION_INITIALIZE_CONFIG = 0;
|
|
846
|
+
var TRANSFER_FEE_INSTRUCTION_TRANSFER_CHECKED_WITH_FEE = 1;
|
|
847
|
+
var TRANSFER_FEE_INSTRUCTION_SET_TRANSFER_FEE = 5;
|
|
848
|
+
function initializeTransferFeeConfigInstruction({
|
|
849
|
+
mint,
|
|
850
|
+
transferFeeConfigAuthority,
|
|
851
|
+
withdrawWithheldAuthority,
|
|
852
|
+
transferFeeBasisPoints,
|
|
853
|
+
maximumFee,
|
|
854
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
855
|
+
}) {
|
|
856
|
+
const authorityLength = transferFeeConfigAuthority ? 33 : 1;
|
|
857
|
+
const withdrawLength = withdrawWithheldAuthority ? 33 : 1;
|
|
858
|
+
const data = new Uint8Array(2 + authorityLength + withdrawLength + 2 + 8);
|
|
859
|
+
data[0] = 26 /* TransferFeeExtension */;
|
|
860
|
+
data[1] = TRANSFER_FEE_INSTRUCTION_INITIALIZE_CONFIG;
|
|
861
|
+
let offset = 2;
|
|
862
|
+
offset += writeCOptionPubkey({
|
|
863
|
+
data,
|
|
864
|
+
offset,
|
|
865
|
+
value: transferFeeConfigAuthority ?? null
|
|
866
|
+
});
|
|
867
|
+
offset += writeCOptionPubkey({
|
|
868
|
+
data,
|
|
869
|
+
offset,
|
|
870
|
+
value: withdrawWithheldAuthority ?? null
|
|
871
|
+
});
|
|
872
|
+
writeU16LE({ data, offset, value: transferFeeBasisPoints });
|
|
873
|
+
offset += 2;
|
|
874
|
+
writeU64LE({ data, offset, value: maximumFee });
|
|
391
875
|
return {
|
|
392
876
|
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
|
-
],
|
|
877
|
+
accounts: [{ pubkey: mint, isSigner: false, isWritable: true }],
|
|
398
878
|
data
|
|
399
879
|
};
|
|
400
880
|
}
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
}
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
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);
|
|
881
|
+
function transferCheckedWithFeeInstruction({
|
|
882
|
+
source,
|
|
883
|
+
mint,
|
|
884
|
+
destination,
|
|
885
|
+
authority,
|
|
886
|
+
amount,
|
|
887
|
+
decimals,
|
|
888
|
+
fee,
|
|
889
|
+
signers,
|
|
890
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
891
|
+
}) {
|
|
892
|
+
const data = new Uint8Array(2 + 8 + 1 + 8);
|
|
893
|
+
data[0] = 26 /* TransferFeeExtension */;
|
|
894
|
+
data[1] = TRANSFER_FEE_INSTRUCTION_TRANSFER_CHECKED_WITH_FEE;
|
|
895
|
+
writeU64LE({ data, offset: 2, value: amount });
|
|
896
|
+
data[10] = decimals;
|
|
897
|
+
writeU64LE({ data, offset: 11, value: fee });
|
|
898
|
+
const accounts = [
|
|
899
|
+
{ pubkey: source, isSigner: false, isWritable: true },
|
|
900
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
901
|
+
{ pubkey: destination, isSigner: false, isWritable: true },
|
|
902
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
903
|
+
];
|
|
904
|
+
appendSigners({ accounts, signers });
|
|
905
|
+
return { programId, accounts, data };
|
|
438
906
|
}
|
|
439
|
-
function
|
|
440
|
-
|
|
907
|
+
function setTransferFeeInstruction({
|
|
908
|
+
mint,
|
|
909
|
+
authority,
|
|
910
|
+
transferFeeBasisPoints,
|
|
911
|
+
maximumFee,
|
|
912
|
+
signers,
|
|
913
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
914
|
+
}) {
|
|
915
|
+
const data = new Uint8Array(2 + 2 + 8);
|
|
916
|
+
data[0] = 26 /* TransferFeeExtension */;
|
|
917
|
+
data[1] = TRANSFER_FEE_INSTRUCTION_SET_TRANSFER_FEE;
|
|
918
|
+
writeU16LE({ data, offset: 2, value: transferFeeBasisPoints });
|
|
919
|
+
writeU64LE({ data, offset: 4, value: maximumFee });
|
|
920
|
+
const accounts = [
|
|
921
|
+
{ pubkey: mint, isSigner: false, isWritable: true },
|
|
922
|
+
{ pubkey: authority, isSigner: isAuthoritySigner({ signers }), isWritable: false }
|
|
923
|
+
];
|
|
924
|
+
appendSigners({ accounts, signers });
|
|
925
|
+
return { programId, accounts, data };
|
|
441
926
|
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
927
|
+
var TRANSFER_HOOK_INSTRUCTION_INITIALIZE = 0;
|
|
928
|
+
function initializeTransferHookInstruction({
|
|
929
|
+
mint,
|
|
930
|
+
authority,
|
|
931
|
+
hookProgramId,
|
|
932
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
933
|
+
}) {
|
|
934
|
+
const data = new Uint8Array(66);
|
|
935
|
+
data[0] = 36 /* TransferHookExtension */;
|
|
936
|
+
data[1] = TRANSFER_HOOK_INSTRUCTION_INITIALIZE;
|
|
937
|
+
data.set(authority.toBytes(), 2);
|
|
938
|
+
data.set(hookProgramId.toBytes(), 34);
|
|
939
|
+
return {
|
|
940
|
+
programId,
|
|
941
|
+
accounts: [{ pubkey: mint, isSigner: false, isWritable: true }],
|
|
942
|
+
data
|
|
943
|
+
};
|
|
450
944
|
}
|
|
451
|
-
var oidNist = (suffix) => ({
|
|
452
|
-
oid: Uint8Array.from([6, 9, 96, 134, 72, 1, 101, 3, 4, 2, suffix])
|
|
453
|
-
});
|
|
454
945
|
|
|
455
|
-
//
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
this.
|
|
476
|
-
this.
|
|
477
|
-
|
|
478
|
-
|
|
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;
|
|
946
|
+
// src/errors.ts
|
|
947
|
+
var SplTokenErrorCode = /* @__PURE__ */ ((SplTokenErrorCode2) => {
|
|
948
|
+
SplTokenErrorCode2["INVALID_MINT"] = "INVALID_MINT";
|
|
949
|
+
SplTokenErrorCode2["INVALID_TOKEN_ACCOUNT"] = "INVALID_TOKEN_ACCOUNT";
|
|
950
|
+
SplTokenErrorCode2["TOKEN_ACCOUNT_NOT_FOUND"] = "TOKEN_ACCOUNT_NOT_FOUND";
|
|
951
|
+
SplTokenErrorCode2["MINT_NOT_FOUND"] = "MINT_NOT_FOUND";
|
|
952
|
+
SplTokenErrorCode2["ACCOUNT_FROZEN"] = "ACCOUNT_FROZEN";
|
|
953
|
+
SplTokenErrorCode2["INSUFFICIENT_BALANCE"] = "INSUFFICIENT_BALANCE";
|
|
954
|
+
SplTokenErrorCode2["INVALID_EXTENSION"] = "INVALID_EXTENSION";
|
|
955
|
+
SplTokenErrorCode2["PDA_DERIVATION_FAILED"] = "PDA_DERIVATION_FAILED";
|
|
956
|
+
SplTokenErrorCode2["INVALID_METADATA"] = "INVALID_METADATA";
|
|
957
|
+
SplTokenErrorCode2["ACCOUNT_NOT_INITIALIZED"] = "ACCOUNT_NOT_INITIALIZED";
|
|
958
|
+
return SplTokenErrorCode2;
|
|
959
|
+
})(SplTokenErrorCode || {});
|
|
960
|
+
var SplTokenError = class _SplTokenError extends Error {
|
|
961
|
+
code;
|
|
962
|
+
details;
|
|
963
|
+
constructor({ code, message, details }) {
|
|
964
|
+
super(message);
|
|
965
|
+
this.name = "SplTokenError";
|
|
966
|
+
this.code = code;
|
|
967
|
+
this.details = details;
|
|
968
|
+
if (Error.captureStackTrace) {
|
|
969
|
+
Error.captureStackTrace(this, _SplTokenError);
|
|
518
970
|
}
|
|
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
971
|
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
972
|
+
/**
|
|
973
|
+
* Creates an invalid mint error.
|
|
974
|
+
*
|
|
975
|
+
* @param options - Error options containing the reason
|
|
976
|
+
*/
|
|
977
|
+
static invalidMint({ reason }) {
|
|
978
|
+
return new _SplTokenError({
|
|
979
|
+
code: "INVALID_MINT" /* INVALID_MINT */,
|
|
980
|
+
message: `Invalid mint: ${reason}`
|
|
981
|
+
});
|
|
540
982
|
}
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
return to;
|
|
983
|
+
/**
|
|
984
|
+
* Creates an invalid token account error.
|
|
985
|
+
*
|
|
986
|
+
* @param options - Error options containing the reason
|
|
987
|
+
*/
|
|
988
|
+
static invalidTokenAccount({ reason }) {
|
|
989
|
+
return new _SplTokenError({
|
|
990
|
+
code: "INVALID_TOKEN_ACCOUNT" /* INVALID_TOKEN_ACCOUNT */,
|
|
991
|
+
message: `Invalid token account: ${reason}`
|
|
992
|
+
});
|
|
552
993
|
}
|
|
553
|
-
|
|
554
|
-
|
|
994
|
+
/**
|
|
995
|
+
* Creates a token account not found error.
|
|
996
|
+
*
|
|
997
|
+
* @param options - Error options containing the address
|
|
998
|
+
*/
|
|
999
|
+
static tokenAccountNotFound({ address }) {
|
|
1000
|
+
return new _SplTokenError({
|
|
1001
|
+
code: "TOKEN_ACCOUNT_NOT_FOUND" /* TOKEN_ACCOUNT_NOT_FOUND */,
|
|
1002
|
+
message: `Token account not found: ${address}`,
|
|
1003
|
+
details: { address }
|
|
1004
|
+
});
|
|
555
1005
|
}
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
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);
|
|
1006
|
+
/**
|
|
1007
|
+
* Creates a mint not found error.
|
|
1008
|
+
*
|
|
1009
|
+
* @param options - Error options containing the address
|
|
1010
|
+
*/
|
|
1011
|
+
static mintNotFound({ address }) {
|
|
1012
|
+
return new _SplTokenError({
|
|
1013
|
+
code: "MINT_NOT_FOUND" /* MINT_NOT_FOUND */,
|
|
1014
|
+
message: `Mint not found: ${address}`,
|
|
1015
|
+
details: { address }
|
|
1016
|
+
});
|
|
639
1017
|
}
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
1018
|
+
/**
|
|
1019
|
+
* Creates an account frozen error.
|
|
1020
|
+
*
|
|
1021
|
+
* @param options - Error options containing the address
|
|
1022
|
+
*/
|
|
1023
|
+
static accountFrozen({ address }) {
|
|
1024
|
+
return new _SplTokenError({
|
|
1025
|
+
code: "ACCOUNT_FROZEN" /* ACCOUNT_FROZEN */,
|
|
1026
|
+
message: `Token account is frozen: ${address}`,
|
|
1027
|
+
details: { address }
|
|
1028
|
+
});
|
|
643
1029
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
1030
|
+
/**
|
|
1031
|
+
* Creates an insufficient balance error.
|
|
1032
|
+
*
|
|
1033
|
+
* @param options - Error options containing required and available amounts
|
|
1034
|
+
*/
|
|
1035
|
+
static insufficientBalance({
|
|
1036
|
+
required,
|
|
1037
|
+
available
|
|
1038
|
+
}) {
|
|
1039
|
+
return new _SplTokenError({
|
|
1040
|
+
code: "INSUFFICIENT_BALANCE" /* INSUFFICIENT_BALANCE */,
|
|
1041
|
+
message: `Insufficient balance: required ${required}, available ${available}`,
|
|
1042
|
+
details: { required: required.toString(), available: available.toString() }
|
|
1043
|
+
});
|
|
654
1044
|
}
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
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);
|
|
1045
|
+
/**
|
|
1046
|
+
* Creates an invalid extension error.
|
|
1047
|
+
*
|
|
1048
|
+
* @param options - Error options containing the reason
|
|
1049
|
+
*/
|
|
1050
|
+
static invalidExtension({ reason }) {
|
|
1051
|
+
return new _SplTokenError({
|
|
1052
|
+
code: "INVALID_EXTENSION" /* INVALID_EXTENSION */,
|
|
1053
|
+
message: `Invalid extension: ${reason}`
|
|
1054
|
+
});
|
|
689
1055
|
}
|
|
690
|
-
|
|
691
|
-
|
|
1056
|
+
/**
|
|
1057
|
+
* Creates a PDA derivation failed error.
|
|
1058
|
+
*
|
|
1059
|
+
* @param options - Error options containing the reason
|
|
1060
|
+
*/
|
|
1061
|
+
static pdaDerivationFailed({ reason }) {
|
|
1062
|
+
return new _SplTokenError({
|
|
1063
|
+
code: "PDA_DERIVATION_FAILED" /* PDA_DERIVATION_FAILED */,
|
|
1064
|
+
message: `PDA derivation failed: ${reason}`
|
|
1065
|
+
});
|
|
692
1066
|
}
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
1067
|
+
/**
|
|
1068
|
+
* Creates an invalid metadata error.
|
|
1069
|
+
*
|
|
1070
|
+
* @param options - Error options containing the reason
|
|
1071
|
+
*/
|
|
1072
|
+
static invalidMetadata({ reason }) {
|
|
1073
|
+
return new _SplTokenError({
|
|
1074
|
+
code: "INVALID_METADATA" /* INVALID_METADATA */,
|
|
1075
|
+
message: `Invalid metadata: ${reason}`
|
|
1076
|
+
});
|
|
696
1077
|
}
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
H = SHA256_IV[7] | 0;
|
|
709
|
-
constructor() {
|
|
710
|
-
super(32);
|
|
1078
|
+
/**
|
|
1079
|
+
* Creates an account not initialized error.
|
|
1080
|
+
*
|
|
1081
|
+
* @param options - Error options containing the address
|
|
1082
|
+
*/
|
|
1083
|
+
static accountNotInitialized({ address }) {
|
|
1084
|
+
return new _SplTokenError({
|
|
1085
|
+
code: "ACCOUNT_NOT_INITIALIZED" /* ACCOUNT_NOT_INITIALIZED */,
|
|
1086
|
+
message: `Account not initialized: ${address}`,
|
|
1087
|
+
details: { address }
|
|
1088
|
+
});
|
|
711
1089
|
}
|
|
712
1090
|
};
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
/* @__PURE__ */ oidNist(1)
|
|
716
|
-
);
|
|
1091
|
+
|
|
1092
|
+
// src/pda/ata.ts
|
|
717
1093
|
function createProgramAddress({
|
|
718
1094
|
seeds,
|
|
719
1095
|
programId
|
|
@@ -745,29 +1121,418 @@ function createProgramAddress({
|
|
|
745
1121
|
};
|
|
746
1122
|
}
|
|
747
1123
|
}
|
|
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;
|
|
1124
|
+
return null;
|
|
1125
|
+
}
|
|
1126
|
+
function findAssociatedTokenAddress({
|
|
1127
|
+
wallet,
|
|
1128
|
+
mint,
|
|
1129
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
1130
|
+
}) {
|
|
1131
|
+
const associatedTokenProgramId = tsCdk.PublicKey.fromString(ASSOCIATED_TOKEN_PROGRAM_ID);
|
|
1132
|
+
const seeds = [wallet.toBytes(), programId.toBytes(), mint.toBytes()];
|
|
1133
|
+
const result = createProgramAddress({ seeds, programId: associatedTokenProgramId });
|
|
1134
|
+
if (!result) {
|
|
1135
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
1136
|
+
reason: `Could not find valid PDA for wallet=${wallet.toString()}, mint=${mint.toString()}`
|
|
1137
|
+
});
|
|
1138
|
+
}
|
|
1139
|
+
return result;
|
|
1140
|
+
}
|
|
1141
|
+
function getAssociatedTokenAddressSync({
|
|
1142
|
+
wallet,
|
|
1143
|
+
mint,
|
|
1144
|
+
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
1145
|
+
}) {
|
|
1146
|
+
return findAssociatedTokenAddress({ wallet, mint, programId }).address;
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
// src/builders/mint-builder.ts
|
|
1150
|
+
var MintBuilder = class _MintBuilder {
|
|
1151
|
+
client;
|
|
1152
|
+
programId;
|
|
1153
|
+
// Default of 9 matches SOL and most major Solana tokens (e.g. USDC uses 6, native SOL uses 9).
|
|
1154
|
+
// SPL Token-2022 stores decimals as a u8, so the valid range is 0–255.
|
|
1155
|
+
decimals = 9;
|
|
1156
|
+
mintAuthority = null;
|
|
1157
|
+
freezeAuthority = null;
|
|
1158
|
+
metadata = null;
|
|
1159
|
+
transferFee = null;
|
|
1160
|
+
nonTransferable = false;
|
|
1161
|
+
permanentDelegate = null;
|
|
1162
|
+
transferHook = null;
|
|
1163
|
+
initialSupply = null;
|
|
1164
|
+
constructor(tokenClient, client) {
|
|
1165
|
+
this.client = client;
|
|
1166
|
+
this.programId = tokenClient.getProgramId();
|
|
1167
|
+
}
|
|
1168
|
+
/**
|
|
1169
|
+
* Creates a new MintBuilder instance.
|
|
1170
|
+
*
|
|
1171
|
+
* @param tokenClient - SplTokenClient instance
|
|
1172
|
+
* @returns A new MintBuilder
|
|
1173
|
+
*
|
|
1174
|
+
* @example
|
|
1175
|
+
* ```typescript
|
|
1176
|
+
* const builder = MintBuilder.create(tokenClient);
|
|
1177
|
+
* ```
|
|
1178
|
+
*/
|
|
1179
|
+
static create(tokenClient) {
|
|
1180
|
+
return new _MintBuilder(tokenClient, tokenClient.getRialoClient());
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Sets the number of decimals for the token.
|
|
1184
|
+
*
|
|
1185
|
+
* SPL Token-2022 stores decimals as a u8, so values from 0 to 255 are
|
|
1186
|
+
* valid at the protocol level. Common choices are 6 (USDC-style) or 9
|
|
1187
|
+
* (SOL-style). Values above 9 are uncommon on Solana but fully supported.
|
|
1188
|
+
*
|
|
1189
|
+
* @param decimals - Number of decimals (0-255)
|
|
1190
|
+
* @returns this for chaining
|
|
1191
|
+
*/
|
|
1192
|
+
withDecimals(decimals) {
|
|
1193
|
+
if (decimals < 0 || decimals > 255) {
|
|
1194
|
+
throw new Error("Decimals must be between 0 and 255");
|
|
1195
|
+
}
|
|
1196
|
+
this.decimals = decimals;
|
|
1197
|
+
return this;
|
|
1198
|
+
}
|
|
1199
|
+
/**
|
|
1200
|
+
* Sets the mint authority.
|
|
1201
|
+
*
|
|
1202
|
+
* @param authority - Public key of the mint authority
|
|
1203
|
+
* @returns this for chaining
|
|
1204
|
+
*/
|
|
1205
|
+
withMintAuthority(authority) {
|
|
1206
|
+
this.mintAuthority = authority;
|
|
1207
|
+
return this;
|
|
1208
|
+
}
|
|
1209
|
+
/**
|
|
1210
|
+
* Sets the freeze authority.
|
|
1211
|
+
*
|
|
1212
|
+
* @param authority - Public key of the freeze authority
|
|
1213
|
+
* @returns this for chaining
|
|
1214
|
+
*/
|
|
1215
|
+
withFreezeAuthority(authority) {
|
|
1216
|
+
this.freezeAuthority = authority;
|
|
1217
|
+
return this;
|
|
1218
|
+
}
|
|
1219
|
+
/**
|
|
1220
|
+
* Configures token metadata extension.
|
|
1221
|
+
*
|
|
1222
|
+
* This enables both MetadataPointer and TokenMetadata extensions,
|
|
1223
|
+
* with the metadata stored directly on the mint account.
|
|
1224
|
+
*
|
|
1225
|
+
* @param metadata - Token metadata configuration
|
|
1226
|
+
* @returns this for chaining
|
|
1227
|
+
*/
|
|
1228
|
+
withMetadata(metadata) {
|
|
1229
|
+
this.metadata = metadata;
|
|
1230
|
+
return this;
|
|
1231
|
+
}
|
|
1232
|
+
/**
|
|
1233
|
+
* Configures transfer fee extension.
|
|
1234
|
+
*
|
|
1235
|
+
* @param config - Transfer fee configuration
|
|
1236
|
+
* @returns this for chaining
|
|
1237
|
+
*/
|
|
1238
|
+
withTransferFee(config) {
|
|
1239
|
+
if (this.nonTransferable) {
|
|
1240
|
+
throw new Error("Cannot add transfer fee to non-transferable mint");
|
|
1241
|
+
}
|
|
1242
|
+
this.transferFee = config;
|
|
1243
|
+
return this;
|
|
1244
|
+
}
|
|
1245
|
+
/**
|
|
1246
|
+
* Makes the mint non-transferable.
|
|
1247
|
+
*
|
|
1248
|
+
* Non-transferable tokens (soulbound tokens) cannot be transferred
|
|
1249
|
+
* after minting.
|
|
1250
|
+
*
|
|
1251
|
+
* @returns this for chaining
|
|
1252
|
+
*/
|
|
1253
|
+
withNonTransferable() {
|
|
1254
|
+
if (this.transferFee) {
|
|
1255
|
+
throw new Error(
|
|
1256
|
+
"Cannot make mint non-transferable when transfer fee is configured"
|
|
1257
|
+
);
|
|
1258
|
+
}
|
|
1259
|
+
this.nonTransferable = true;
|
|
1260
|
+
return this;
|
|
1261
|
+
}
|
|
1262
|
+
/**
|
|
1263
|
+
* Configures permanent delegate extension.
|
|
1264
|
+
*
|
|
1265
|
+
* A permanent delegate has unrestricted transfer and burn authority
|
|
1266
|
+
* over all token accounts for this mint.
|
|
1267
|
+
*
|
|
1268
|
+
* @param delegate - Public key of the permanent delegate
|
|
1269
|
+
* @returns this for chaining
|
|
1270
|
+
*/
|
|
1271
|
+
withPermanentDelegate(delegate) {
|
|
1272
|
+
this.permanentDelegate = delegate;
|
|
1273
|
+
return this;
|
|
1274
|
+
}
|
|
1275
|
+
/**
|
|
1276
|
+
* Configures transfer hook extension.
|
|
1277
|
+
*
|
|
1278
|
+
* A transfer hook invokes a specified program on every token transfer,
|
|
1279
|
+
* enabling custom transfer logic (e.g., compliance checks, royalties).
|
|
1280
|
+
*
|
|
1281
|
+
* @param config - Transfer hook configuration
|
|
1282
|
+
* @returns this for chaining
|
|
1283
|
+
*/
|
|
1284
|
+
withTransferHook(config) {
|
|
1285
|
+
this.transferHook = config;
|
|
1286
|
+
return this;
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Configures initial token supply to mint after creation.
|
|
1290
|
+
*
|
|
1291
|
+
* The tokens will be minted to an Associated Token Account (ATA)
|
|
1292
|
+
* derived from the destination wallet.
|
|
1293
|
+
*
|
|
1294
|
+
* @param config - Initial supply configuration
|
|
1295
|
+
* @returns this for chaining
|
|
1296
|
+
*/
|
|
1297
|
+
withInitialSupply(config) {
|
|
1298
|
+
this.initialSupply = config;
|
|
1299
|
+
return this;
|
|
1300
|
+
}
|
|
1301
|
+
/**
|
|
1302
|
+
* Builds the mint transaction without sending.
|
|
1303
|
+
*
|
|
1304
|
+
* @param options - Build options
|
|
1305
|
+
* @returns Build result with transaction and addresses
|
|
1306
|
+
*
|
|
1307
|
+
* @example
|
|
1308
|
+
* ```typescript
|
|
1309
|
+
* const { transaction, mintAddress } = await builder.build({
|
|
1310
|
+
* payer: authority,
|
|
1311
|
+
* mintKeypair,
|
|
1312
|
+
* validFrom: BigInt(Date.now()),
|
|
1313
|
+
* });
|
|
1314
|
+
*
|
|
1315
|
+
* // Sign manually
|
|
1316
|
+
* const signed = transaction.sign(authorityKeypair).sign(mintKeypair);
|
|
1317
|
+
* await client.sendAndConfirmTransaction(signed.serialize());
|
|
1318
|
+
* ```
|
|
1319
|
+
*/
|
|
1320
|
+
async build(options) {
|
|
1321
|
+
const { payer, mintKeypair, validFrom } = options;
|
|
1322
|
+
const mintAddress = mintKeypair.publicKey;
|
|
1323
|
+
if (!this.mintAuthority) {
|
|
1324
|
+
throw new Error(
|
|
1325
|
+
"Mint authority is required. Call withMintAuthority() first."
|
|
1326
|
+
);
|
|
1327
|
+
}
|
|
1328
|
+
const extensions = this.getExtensions();
|
|
1329
|
+
const createAccountExtensions = extensions.filter(
|
|
1330
|
+
(ext) => ext !== 19 /* TokenMetadata */
|
|
1331
|
+
);
|
|
1332
|
+
const createAccountSize = getMintSizeWithExtensions({
|
|
1333
|
+
extensions: createAccountExtensions,
|
|
1334
|
+
metadataSize: void 0
|
|
1335
|
+
});
|
|
1336
|
+
let rentSize = createAccountSize;
|
|
1337
|
+
if (this.metadata) {
|
|
1338
|
+
const metadataSize = getMetadataExtensionSize({
|
|
1339
|
+
name: this.metadata.name,
|
|
1340
|
+
symbol: this.metadata.symbol,
|
|
1341
|
+
uri: this.metadata.uri,
|
|
1342
|
+
additionalMetadata: this.metadata.additionalMetadata
|
|
1343
|
+
});
|
|
1344
|
+
rentSize = getMintSizeWithExtensions({
|
|
1345
|
+
extensions,
|
|
1346
|
+
metadataSize
|
|
1347
|
+
});
|
|
1348
|
+
}
|
|
1349
|
+
const rent = await this.client.getMinimumBalanceForRentExemption(
|
|
1350
|
+
BigInt(rentSize)
|
|
1351
|
+
);
|
|
1352
|
+
const instructions = [];
|
|
1353
|
+
instructions.push(
|
|
1354
|
+
tsCdk.createAccount(
|
|
1355
|
+
payer,
|
|
1356
|
+
mintAddress,
|
|
1357
|
+
rent,
|
|
1358
|
+
BigInt(createAccountSize),
|
|
1359
|
+
this.programId
|
|
1360
|
+
)
|
|
1361
|
+
);
|
|
1362
|
+
if (this.metadata) {
|
|
1363
|
+
instructions.push(
|
|
1364
|
+
initializeMetadataPointerInstruction({
|
|
1365
|
+
mint: mintAddress,
|
|
1366
|
+
authority: this.mintAuthority,
|
|
1367
|
+
metadataAddress: mintAddress,
|
|
1368
|
+
// Self-referential for on-mint metadata
|
|
1369
|
+
programId: this.programId
|
|
1370
|
+
})
|
|
1371
|
+
);
|
|
1372
|
+
}
|
|
1373
|
+
if (this.transferFee) {
|
|
1374
|
+
instructions.push(
|
|
1375
|
+
initializeTransferFeeConfigInstruction({
|
|
1376
|
+
mint: mintAddress,
|
|
1377
|
+
transferFeeConfigAuthority: this.transferFee.transferFeeConfigAuthority,
|
|
1378
|
+
withdrawWithheldAuthority: this.transferFee.withdrawWithheldAuthority,
|
|
1379
|
+
transferFeeBasisPoints: this.transferFee.transferFeeBasisPoints,
|
|
1380
|
+
maximumFee: this.transferFee.maximumFee,
|
|
1381
|
+
programId: this.programId
|
|
1382
|
+
})
|
|
1383
|
+
);
|
|
1384
|
+
}
|
|
1385
|
+
if (this.nonTransferable) {
|
|
1386
|
+
instructions.push(
|
|
1387
|
+
initializeNonTransferableMintInstruction({
|
|
1388
|
+
mint: mintAddress,
|
|
1389
|
+
programId: this.programId
|
|
1390
|
+
})
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
if (this.permanentDelegate) {
|
|
1394
|
+
instructions.push(
|
|
1395
|
+
initializePermanentDelegateInstruction({
|
|
1396
|
+
mint: mintAddress,
|
|
1397
|
+
delegate: this.permanentDelegate,
|
|
1398
|
+
programId: this.programId
|
|
1399
|
+
})
|
|
1400
|
+
);
|
|
1401
|
+
}
|
|
1402
|
+
if (this.transferHook) {
|
|
1403
|
+
instructions.push(
|
|
1404
|
+
initializeTransferHookInstruction({
|
|
1405
|
+
mint: mintAddress,
|
|
1406
|
+
authority: this.transferHook.authority,
|
|
1407
|
+
hookProgramId: this.transferHook.programId,
|
|
1408
|
+
programId: this.programId
|
|
1409
|
+
})
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
instructions.push(
|
|
1413
|
+
initializeMintInstruction({
|
|
1414
|
+
mint: mintAddress,
|
|
1415
|
+
decimals: this.decimals,
|
|
1416
|
+
mintAuthority: this.mintAuthority,
|
|
1417
|
+
freezeAuthority: this.freezeAuthority ?? void 0,
|
|
1418
|
+
programId: this.programId
|
|
1419
|
+
})
|
|
1420
|
+
);
|
|
1421
|
+
if (this.metadata) {
|
|
1422
|
+
instructions.push(
|
|
1423
|
+
initializeTokenMetadataInstruction({
|
|
1424
|
+
mint: mintAddress,
|
|
1425
|
+
updateAuthority: this.mintAuthority,
|
|
1426
|
+
mintAuthority: this.mintAuthority,
|
|
1427
|
+
name: this.metadata.name,
|
|
1428
|
+
symbol: this.metadata.symbol,
|
|
1429
|
+
uri: this.metadata.uri,
|
|
1430
|
+
additionalMetadata: this.metadata.additionalMetadata,
|
|
1431
|
+
programId: this.programId
|
|
1432
|
+
})
|
|
1433
|
+
);
|
|
1434
|
+
}
|
|
1435
|
+
let ataAddress;
|
|
1436
|
+
if (this.initialSupply) {
|
|
1437
|
+
ataAddress = getAssociatedTokenAddressSync({
|
|
1438
|
+
wallet: this.initialSupply.destination,
|
|
1439
|
+
mint: mintAddress,
|
|
1440
|
+
programId: this.programId
|
|
1441
|
+
});
|
|
1442
|
+
instructions.push(
|
|
1443
|
+
createAssociatedTokenAccountIdempotentInstruction({
|
|
1444
|
+
payer,
|
|
1445
|
+
associatedToken: ataAddress,
|
|
1446
|
+
owner: this.initialSupply.destination,
|
|
1447
|
+
mint: mintAddress,
|
|
1448
|
+
programId: this.programId
|
|
1449
|
+
})
|
|
1450
|
+
);
|
|
1451
|
+
instructions.push(
|
|
1452
|
+
mintToInstruction({
|
|
1453
|
+
mint: mintAddress,
|
|
1454
|
+
destination: ataAddress,
|
|
1455
|
+
authority: this.mintAuthority,
|
|
1456
|
+
amount: this.initialSupply.amount,
|
|
1457
|
+
programId: this.programId
|
|
1458
|
+
})
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
const configHashPrefix = await this.client.getConfigHashPrefix();
|
|
1462
|
+
const builder = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).setConfigHashPrefix(configHashPrefix);
|
|
1463
|
+
for (const instruction of instructions) {
|
|
1464
|
+
builder.addInstruction(instruction);
|
|
1465
|
+
}
|
|
1466
|
+
return {
|
|
1467
|
+
transaction: builder.build(),
|
|
1468
|
+
mintAddress,
|
|
1469
|
+
ataAddress
|
|
1470
|
+
};
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Builds, signs, and sends the mint transaction.
|
|
1474
|
+
*
|
|
1475
|
+
* @param options - Send options including signers
|
|
1476
|
+
* @returns Send result with signature and addresses
|
|
1477
|
+
*
|
|
1478
|
+
* @example
|
|
1479
|
+
* ```typescript
|
|
1480
|
+
* const { signature, mintAddress } = await builder.send({
|
|
1481
|
+
* payer: authority,
|
|
1482
|
+
* mintKeypair,
|
|
1483
|
+
* validFrom: BigInt(Date.now()),
|
|
1484
|
+
* signers: [authorityKeypair, mintKeypair],
|
|
1485
|
+
* });
|
|
1486
|
+
* ```
|
|
1487
|
+
*/
|
|
1488
|
+
async send(options) {
|
|
1489
|
+
const { signers, ...buildOptions } = options;
|
|
1490
|
+
if (signers.length === 0) {
|
|
1491
|
+
throw new Error("At least one signer is required");
|
|
1492
|
+
}
|
|
1493
|
+
const { transaction, mintAddress, ataAddress } = await this.build(buildOptions);
|
|
1494
|
+
let signedTx = transaction;
|
|
1495
|
+
for (const signer of signers) {
|
|
1496
|
+
signedTx = signedTx.sign(signer);
|
|
1497
|
+
}
|
|
1498
|
+
const result = await this.client.sendAndConfirmTransaction(
|
|
1499
|
+
signedTx.serialize()
|
|
1500
|
+
);
|
|
1501
|
+
return {
|
|
1502
|
+
signature: result.signature,
|
|
1503
|
+
mintAddress,
|
|
1504
|
+
ataAddress
|
|
1505
|
+
};
|
|
1506
|
+
}
|
|
1507
|
+
/**
|
|
1508
|
+
* Returns the list of extensions that will be enabled.
|
|
1509
|
+
*/
|
|
1510
|
+
getExtensions() {
|
|
1511
|
+
const extensions = [];
|
|
1512
|
+
if (this.metadata) {
|
|
1513
|
+
extensions.push(18 /* MetadataPointer */);
|
|
1514
|
+
extensions.push(19 /* TokenMetadata */);
|
|
1515
|
+
}
|
|
1516
|
+
if (this.transferFee) {
|
|
1517
|
+
extensions.push(1 /* TransferFeeConfig */);
|
|
1518
|
+
}
|
|
1519
|
+
if (this.nonTransferable) {
|
|
1520
|
+
extensions.push(9 /* NonTransferable */);
|
|
1521
|
+
}
|
|
1522
|
+
if (this.permanentDelegate) {
|
|
1523
|
+
extensions.push(12 /* PermanentDelegate */);
|
|
1524
|
+
}
|
|
1525
|
+
if (this.transferHook) {
|
|
1526
|
+
extensions.push(14 /* TransferHook */);
|
|
1527
|
+
}
|
|
1528
|
+
return extensions;
|
|
1529
|
+
}
|
|
1530
|
+
};
|
|
1531
|
+
function readU16LE({ data, offset }) {
|
|
1532
|
+
return data[offset] | data[offset + 1] << 8;
|
|
764
1533
|
}
|
|
765
|
-
function
|
|
766
|
-
|
|
767
|
-
mint,
|
|
768
|
-
programId = tsCdk.PublicKey.fromString(TOKEN_2022_PROGRAM_ID)
|
|
769
|
-
}) {
|
|
770
|
-
return findAssociatedTokenAddress({ wallet, mint, programId }).address;
|
|
1534
|
+
function readU32LE({ data, offset }) {
|
|
1535
|
+
return (data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24) >>> 0;
|
|
771
1536
|
}
|
|
772
1537
|
function readU64LE({ data, offset }) {
|
|
773
1538
|
let value = 0n;
|
|
@@ -776,13 +1541,15 @@ function readU64LE({ data, offset }) {
|
|
|
776
1541
|
}
|
|
777
1542
|
return value;
|
|
778
1543
|
}
|
|
779
|
-
function readU32LE({ data, offset }) {
|
|
780
|
-
return (data[offset] | data[offset + 1] << 8 | data[offset + 2] << 16 | data[offset + 3] << 24) >>> 0;
|
|
781
|
-
}
|
|
782
1544
|
function readCOptionPubkey({
|
|
783
1545
|
data,
|
|
784
1546
|
offset
|
|
785
1547
|
}) {
|
|
1548
|
+
if (data.length < offset + 4 + PUBKEY_SIZE) {
|
|
1549
|
+
throw SplTokenError.invalidExtension({
|
|
1550
|
+
reason: `COption<Pubkey> out of bounds: need ${offset + 4 + PUBKEY_SIZE} bytes, got ${data.length}`
|
|
1551
|
+
});
|
|
1552
|
+
}
|
|
786
1553
|
const tag = readU32LE({ data, offset });
|
|
787
1554
|
if (tag === COPTION_SOME) {
|
|
788
1555
|
const pubkeyBytes = data.slice(offset + 4, offset + 4 + PUBKEY_SIZE);
|
|
@@ -790,122 +1557,192 @@ function readCOptionPubkey({
|
|
|
790
1557
|
}
|
|
791
1558
|
return null;
|
|
792
1559
|
}
|
|
793
|
-
function
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
1560
|
+
function readOptionalNonZeroPubkey({
|
|
1561
|
+
data,
|
|
1562
|
+
offset
|
|
1563
|
+
}) {
|
|
1564
|
+
const pubkeyBytes = data.slice(offset, offset + PUBKEY_SIZE);
|
|
1565
|
+
const isZero = pubkeyBytes.every((byte) => byte === 0);
|
|
1566
|
+
return isZero ? null : tsCdk.PublicKey.fromBytes(pubkeyBytes);
|
|
1567
|
+
}
|
|
1568
|
+
function readPubkey({ data, offset }) {
|
|
1569
|
+
return tsCdk.PublicKey.fromBytes(data.slice(offset, offset + PUBKEY_SIZE));
|
|
1570
|
+
}
|
|
1571
|
+
|
|
1572
|
+
// src/state/extensions.ts
|
|
1573
|
+
function parseTlvExtensions({
|
|
1574
|
+
data,
|
|
1575
|
+
extensionsOffset
|
|
1576
|
+
}) {
|
|
1577
|
+
const extensions = [];
|
|
1578
|
+
let offset = extensionsOffset;
|
|
1579
|
+
while (offset + TLV_TYPE_SIZE + TLV_LENGTH_SIZE <= data.length) {
|
|
1580
|
+
const type = readU16LE({ data, offset });
|
|
1581
|
+
const length = readU16LE({ data, offset: offset + TLV_TYPE_SIZE });
|
|
1582
|
+
if (type === 0 /* Uninitialized */ && length === 0) {
|
|
1583
|
+
break;
|
|
1584
|
+
}
|
|
1585
|
+
const dataStart = offset + TLV_TYPE_SIZE + TLV_LENGTH_SIZE;
|
|
1586
|
+
const dataEnd = dataStart + length;
|
|
1587
|
+
if (dataEnd > data.length) {
|
|
1588
|
+
throw SplTokenError.invalidExtension({
|
|
1589
|
+
reason: `Extension data extends beyond buffer: type=${type}, length=${length}`
|
|
1590
|
+
});
|
|
1591
|
+
}
|
|
1592
|
+
extensions.push({
|
|
1593
|
+
type,
|
|
1594
|
+
data: data.slice(dataStart, dataEnd)
|
|
797
1595
|
});
|
|
1596
|
+
offset = dataEnd;
|
|
798
1597
|
}
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
1598
|
+
return extensions;
|
|
1599
|
+
}
|
|
1600
|
+
function getMintExtensions({ data }) {
|
|
1601
|
+
if (data.length <= TOKEN_ACCOUNT_SIZE) {
|
|
1602
|
+
return [];
|
|
1603
|
+
}
|
|
1604
|
+
const accountType = data[TOKEN_ACCOUNT_SIZE];
|
|
1605
|
+
if (accountType !== 1 /* Mint */) {
|
|
1606
|
+
return [];
|
|
806
1607
|
}
|
|
1608
|
+
return parseTlvExtensions({ data, extensionsOffset: MINT_EXTENSIONS_OFFSET });
|
|
1609
|
+
}
|
|
1610
|
+
function getTokenAccountExtensions({ data }) {
|
|
1611
|
+
if (data.length <= TOKEN_ACCOUNT_SIZE) {
|
|
1612
|
+
return [];
|
|
1613
|
+
}
|
|
1614
|
+
const accountType = data[TOKEN_ACCOUNT_SIZE];
|
|
1615
|
+
if (accountType !== 2 /* Account */) {
|
|
1616
|
+
return [];
|
|
1617
|
+
}
|
|
1618
|
+
return parseTlvExtensions({
|
|
1619
|
+
data,
|
|
1620
|
+
extensionsOffset: TOKEN_ACCOUNT_EXTENSIONS_OFFSET
|
|
1621
|
+
});
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1624
|
+
// src/state/extension-parsers.ts
|
|
1625
|
+
var TRANSFER_FEE_CONFIG_SIZE = 108;
|
|
1626
|
+
var TRANSFER_FEE_AMOUNT_SIZE = 8;
|
|
1627
|
+
var METADATA_POINTER_SIZE = 64;
|
|
1628
|
+
var PUBKEY_SIZE2 = 32;
|
|
1629
|
+
var PERMANENT_DELEGATE_SIZE = 32;
|
|
1630
|
+
var TRANSFER_HOOK_SIZE = 64;
|
|
1631
|
+
var TOKEN_METADATA_MAX_SIZE = 65535;
|
|
1632
|
+
function parseTransferFee({ data, offset }) {
|
|
1633
|
+
const epoch = readU64LE({ data, offset });
|
|
1634
|
+
const maximumFee = readU64LE({ data, offset: offset + 8 });
|
|
1635
|
+
const transferFeeBasisPoints = readU16LE({ data, offset: offset + 16 });
|
|
807
1636
|
return {
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
isInitialized,
|
|
812
|
-
mintAuthority,
|
|
813
|
-
freezeAuthority
|
|
1637
|
+
epoch,
|
|
1638
|
+
maximumFee,
|
|
1639
|
+
transferFeeBasisPoints
|
|
814
1640
|
};
|
|
815
1641
|
}
|
|
816
|
-
function
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
1642
|
+
function parseTransferFeeConfigExtension({
|
|
1643
|
+
data
|
|
1644
|
+
}) {
|
|
1645
|
+
if (data.length < TRANSFER_FEE_CONFIG_SIZE) {
|
|
1646
|
+
throw SplTokenError.invalidExtension({
|
|
1647
|
+
reason: `TransferFeeConfig too short: expected ${TRANSFER_FEE_CONFIG_SIZE} bytes, got ${data.length}`
|
|
1648
|
+
});
|
|
820
1649
|
}
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
1650
|
+
const transferFeeConfigAuthority = readOptionalNonZeroPubkey({
|
|
1651
|
+
data,
|
|
1652
|
+
offset: 0
|
|
1653
|
+
});
|
|
1654
|
+
const withdrawWithheldAuthority = readOptionalNonZeroPubkey({
|
|
1655
|
+
data,
|
|
1656
|
+
offset: 32
|
|
1657
|
+
});
|
|
1658
|
+
const withheldAmount = readU64LE({ data, offset: 64 });
|
|
1659
|
+
const olderTransferFee = parseTransferFee({ data, offset: 72 });
|
|
1660
|
+
const newerTransferFee = parseTransferFee({ data, offset: 90 });
|
|
1661
|
+
return {
|
|
1662
|
+
transferFeeConfigAuthority,
|
|
1663
|
+
withdrawWithheldAuthority,
|
|
1664
|
+
withheldAmount,
|
|
1665
|
+
olderTransferFee,
|
|
1666
|
+
newerTransferFee
|
|
1667
|
+
};
|
|
825
1668
|
}
|
|
826
|
-
function
|
|
827
|
-
data
|
|
828
|
-
offset
|
|
1669
|
+
function parseTransferFeeAmountExtension({
|
|
1670
|
+
data
|
|
829
1671
|
}) {
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
1672
|
+
if (data.length < TRANSFER_FEE_AMOUNT_SIZE) {
|
|
1673
|
+
throw SplTokenError.invalidExtension({
|
|
1674
|
+
reason: `TransferFeeAmount too short: expected ${TRANSFER_FEE_AMOUNT_SIZE} bytes, got ${data.length}`
|
|
1675
|
+
});
|
|
834
1676
|
}
|
|
835
|
-
return
|
|
1677
|
+
return {
|
|
1678
|
+
withheldAmount: readU64LE({ data, offset: 0 })
|
|
1679
|
+
};
|
|
836
1680
|
}
|
|
837
|
-
function
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
1681
|
+
function parseNonTransferableExtension({
|
|
1682
|
+
data
|
|
1683
|
+
}) {
|
|
1684
|
+
if (data.length !== 0) {
|
|
1685
|
+
throw SplTokenError.invalidExtension({
|
|
1686
|
+
reason: `NonTransferable has unexpected length: expected 0 bytes, got ${data.length}`
|
|
1687
|
+
});
|
|
841
1688
|
}
|
|
842
|
-
return
|
|
1689
|
+
return { isNonTransferable: true };
|
|
843
1690
|
}
|
|
844
|
-
function
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
1691
|
+
function parseNonTransferableAccountExtension({
|
|
1692
|
+
data
|
|
1693
|
+
}) {
|
|
1694
|
+
if (data.length !== 0) {
|
|
1695
|
+
throw SplTokenError.invalidExtension({
|
|
1696
|
+
reason: `NonTransferableAccount has unexpected length: expected 0 bytes, got ${data.length}`
|
|
848
1697
|
});
|
|
849
1698
|
}
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
)
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
const stateValue = data[TOKEN_ACCOUNT_STATE_OFFSET];
|
|
860
|
-
if (stateValue > 2) {
|
|
861
|
-
throw SplTokenError.invalidTokenAccount({ reason: `Invalid account state: ${stateValue}` });
|
|
1699
|
+
return { isNonTransferableAccount: true };
|
|
1700
|
+
}
|
|
1701
|
+
function parsePermanentDelegateExtension({
|
|
1702
|
+
data
|
|
1703
|
+
}) {
|
|
1704
|
+
if (data.length < PERMANENT_DELEGATE_SIZE) {
|
|
1705
|
+
throw SplTokenError.invalidExtension({
|
|
1706
|
+
reason: `PermanentDelegate too short: expected ${PERMANENT_DELEGATE_SIZE} bytes, got ${data.length}`
|
|
1707
|
+
});
|
|
862
1708
|
}
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1709
|
+
return { delegate: readOptionalNonZeroPubkey({ data, offset: 0 }) };
|
|
1710
|
+
}
|
|
1711
|
+
function parseTransferHookExtension({ data }) {
|
|
1712
|
+
if (data.length < TRANSFER_HOOK_SIZE) {
|
|
1713
|
+
throw SplTokenError.invalidExtension({
|
|
1714
|
+
reason: `TransferHook too short: expected ${TRANSFER_HOOK_SIZE} bytes, got ${data.length}`
|
|
1715
|
+
});
|
|
866
1716
|
}
|
|
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
1717
|
return {
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
owner,
|
|
874
|
-
amount,
|
|
875
|
-
delegate,
|
|
876
|
-
state,
|
|
877
|
-
isNative,
|
|
878
|
-
delegatedAmount,
|
|
879
|
-
closeAuthority
|
|
1718
|
+
authority: readOptionalNonZeroPubkey({ data, offset: 0 }),
|
|
1719
|
+
programId: readOptionalNonZeroPubkey({ data, offset: 32 })
|
|
880
1720
|
};
|
|
881
1721
|
}
|
|
882
|
-
function
|
|
883
|
-
|
|
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
|
|
1722
|
+
function parseMetadataPointerExtensionData({
|
|
1723
|
+
data
|
|
891
1724
|
}) {
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
1725
|
+
if (data.length < METADATA_POINTER_SIZE) {
|
|
1726
|
+
throw SplTokenError.invalidExtension({
|
|
1727
|
+
reason: `MetadataPointer too short: expected ${METADATA_POINTER_SIZE} bytes, got ${data.length}`
|
|
1728
|
+
});
|
|
896
1729
|
}
|
|
897
|
-
|
|
1730
|
+
const authority = readOptionalNonZeroPubkey({ data, offset: 0 });
|
|
1731
|
+
const metadataAddress = readOptionalNonZeroPubkey({ data, offset: 32 });
|
|
1732
|
+
return { authority, metadataAddress };
|
|
898
1733
|
}
|
|
899
1734
|
function readLengthPrefixedString({
|
|
900
1735
|
data,
|
|
901
1736
|
offset
|
|
902
1737
|
}) {
|
|
903
1738
|
if (offset + 4 > data.length) {
|
|
904
|
-
throw SplTokenError.
|
|
1739
|
+
throw SplTokenError.invalidExtension({
|
|
1740
|
+
reason: "String length prefix extends beyond data"
|
|
1741
|
+
});
|
|
905
1742
|
}
|
|
906
|
-
const length =
|
|
1743
|
+
const length = readU32LE({ data, offset });
|
|
907
1744
|
if (offset + 4 + length > data.length) {
|
|
908
|
-
throw SplTokenError.
|
|
1745
|
+
throw SplTokenError.invalidExtension({
|
|
909
1746
|
reason: `String data extends beyond buffer: need ${length} bytes at offset ${offset + 4}`
|
|
910
1747
|
});
|
|
911
1748
|
}
|
|
@@ -913,47 +1750,140 @@ function readLengthPrefixedString({
|
|
|
913
1750
|
try {
|
|
914
1751
|
const str = new TextDecoder().decode(stringBytes);
|
|
915
1752
|
return [str, 4 + length];
|
|
916
|
-
} catch
|
|
917
|
-
throw SplTokenError.
|
|
1753
|
+
} catch {
|
|
1754
|
+
throw SplTokenError.invalidExtension({
|
|
918
1755
|
reason: `Invalid UTF-8 string at offset ${offset}`
|
|
919
1756
|
});
|
|
920
1757
|
}
|
|
921
1758
|
}
|
|
922
|
-
function
|
|
1759
|
+
function parseTokenMetadataExtensionData({ data }) {
|
|
1760
|
+
if (data.length < 64) {
|
|
1761
|
+
throw SplTokenError.invalidExtension({
|
|
1762
|
+
reason: `TokenMetadata too short: expected at least 64 bytes, got ${data.length}`
|
|
1763
|
+
});
|
|
1764
|
+
}
|
|
1765
|
+
if (data.length > TOKEN_METADATA_MAX_SIZE) {
|
|
1766
|
+
throw SplTokenError.invalidExtension({
|
|
1767
|
+
reason: `TokenMetadata too large: maximum ${TOKEN_METADATA_MAX_SIZE} bytes, got ${data.length}`
|
|
1768
|
+
});
|
|
1769
|
+
}
|
|
1770
|
+
let offset = 0;
|
|
1771
|
+
const updateAuthority = readOptionalNonZeroPubkey({ data, offset });
|
|
1772
|
+
offset += PUBKEY_SIZE2;
|
|
1773
|
+
const mint = readPubkey({ data, offset });
|
|
1774
|
+
offset += PUBKEY_SIZE2;
|
|
1775
|
+
const [name, nameLen] = readLengthPrefixedString({ data, offset });
|
|
1776
|
+
offset += nameLen;
|
|
1777
|
+
const [symbol, symbolLen] = readLengthPrefixedString({ data, offset });
|
|
1778
|
+
offset += symbolLen;
|
|
1779
|
+
const [uri, uriLen] = readLengthPrefixedString({ data, offset });
|
|
1780
|
+
offset += uriLen;
|
|
1781
|
+
const additionalMetadata = [];
|
|
1782
|
+
if (offset + 4 <= data.length) {
|
|
1783
|
+
const numEntries = readU32LE({ data, offset });
|
|
1784
|
+
offset += 4;
|
|
1785
|
+
for (let i = 0; i < numEntries && offset < data.length; i++) {
|
|
1786
|
+
const [key, keyLen] = readLengthPrefixedString({ data, offset });
|
|
1787
|
+
offset += keyLen;
|
|
1788
|
+
const [value, valueLen] = readLengthPrefixedString({ data, offset });
|
|
1789
|
+
offset += valueLen;
|
|
1790
|
+
additionalMetadata.push([key, value]);
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
return {
|
|
1794
|
+
updateAuthority,
|
|
1795
|
+
mint,
|
|
1796
|
+
name,
|
|
1797
|
+
symbol,
|
|
1798
|
+
uri,
|
|
1799
|
+
additionalMetadata
|
|
1800
|
+
};
|
|
1801
|
+
}
|
|
1802
|
+
function parseExtension({ extension }) {
|
|
1803
|
+
switch (extension.type) {
|
|
1804
|
+
case 1 /* TransferFeeConfig */:
|
|
1805
|
+
return {
|
|
1806
|
+
type: 1 /* TransferFeeConfig */,
|
|
1807
|
+
value: parseTransferFeeConfigExtension({ data: extension.data })
|
|
1808
|
+
};
|
|
1809
|
+
case 2 /* TransferFeeAmount */:
|
|
1810
|
+
return {
|
|
1811
|
+
type: 2 /* TransferFeeAmount */,
|
|
1812
|
+
value: parseTransferFeeAmountExtension({ data: extension.data })
|
|
1813
|
+
};
|
|
1814
|
+
case 9 /* NonTransferable */:
|
|
1815
|
+
return {
|
|
1816
|
+
type: 9 /* NonTransferable */,
|
|
1817
|
+
value: parseNonTransferableExtension({ data: extension.data })
|
|
1818
|
+
};
|
|
1819
|
+
case 13 /* NonTransferableAccount */:
|
|
1820
|
+
return {
|
|
1821
|
+
type: 13 /* NonTransferableAccount */,
|
|
1822
|
+
value: parseNonTransferableAccountExtension({ data: extension.data })
|
|
1823
|
+
};
|
|
1824
|
+
case 18 /* MetadataPointer */:
|
|
1825
|
+
return {
|
|
1826
|
+
type: 18 /* MetadataPointer */,
|
|
1827
|
+
value: parseMetadataPointerExtensionData({ data: extension.data })
|
|
1828
|
+
};
|
|
1829
|
+
case 19 /* TokenMetadata */:
|
|
1830
|
+
return {
|
|
1831
|
+
type: 19 /* TokenMetadata */,
|
|
1832
|
+
value: parseTokenMetadataExtensionData({ data: extension.data })
|
|
1833
|
+
};
|
|
1834
|
+
case 12 /* PermanentDelegate */:
|
|
1835
|
+
return {
|
|
1836
|
+
type: 12 /* PermanentDelegate */,
|
|
1837
|
+
value: parsePermanentDelegateExtension({ data: extension.data })
|
|
1838
|
+
};
|
|
1839
|
+
case 14 /* TransferHook */:
|
|
1840
|
+
return {
|
|
1841
|
+
type: 14 /* TransferHook */,
|
|
1842
|
+
value: parseTransferHookExtension({ data: extension.data })
|
|
1843
|
+
};
|
|
1844
|
+
default:
|
|
1845
|
+
return null;
|
|
1846
|
+
}
|
|
1847
|
+
}
|
|
1848
|
+
function getMintExtensionStates({ data }) {
|
|
1849
|
+
return getMintExtensions({ data }).map((extension) => parseExtension({ extension })).filter((extension) => extension !== null);
|
|
1850
|
+
}
|
|
1851
|
+
function getTokenAccountExtensionStates({ data }) {
|
|
1852
|
+
return getTokenAccountExtensions({ data }).map((extension) => parseExtension({ extension })).filter((extension) => extension !== null);
|
|
1853
|
+
}
|
|
1854
|
+
function readLengthPrefixedString2({
|
|
923
1855
|
data,
|
|
924
|
-
|
|
1856
|
+
offset
|
|
925
1857
|
}) {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
1858
|
+
if (offset + 4 > data.length) {
|
|
1859
|
+
throw SplTokenError.invalidMetadata({
|
|
1860
|
+
reason: "String length prefix extends beyond data"
|
|
1861
|
+
});
|
|
1862
|
+
}
|
|
1863
|
+
const length = readU32LE({ data, offset });
|
|
1864
|
+
if (offset + 4 + length > data.length) {
|
|
1865
|
+
throw SplTokenError.invalidMetadata({
|
|
1866
|
+
reason: `String data extends beyond buffer: need ${length} bytes at offset ${offset + 4}`
|
|
1867
|
+
});
|
|
1868
|
+
}
|
|
1869
|
+
const stringBytes = data.slice(offset + 4, offset + 4 + length);
|
|
1870
|
+
try {
|
|
1871
|
+
const str = new TextDecoder().decode(stringBytes);
|
|
1872
|
+
return [str, 4 + length];
|
|
1873
|
+
} catch {
|
|
1874
|
+
throw SplTokenError.invalidMetadata({
|
|
1875
|
+
reason: `Invalid UTF-8 string at offset ${offset}`
|
|
944
1876
|
});
|
|
945
|
-
offset = dataEnd;
|
|
946
1877
|
}
|
|
947
|
-
return extensions;
|
|
948
1878
|
}
|
|
949
1879
|
function parseMetadataPointer({ data }) {
|
|
950
|
-
if (data.length <
|
|
1880
|
+
if (data.length < 64) {
|
|
951
1881
|
throw SplTokenError.invalidExtension({
|
|
952
|
-
reason: `MetadataPointer too short: expected
|
|
1882
|
+
reason: `MetadataPointer too short: expected 64 bytes, got ${data.length}`
|
|
953
1883
|
});
|
|
954
1884
|
}
|
|
955
|
-
const authority =
|
|
956
|
-
const metadataAddress =
|
|
1885
|
+
const authority = readOptionalNonZeroPubkey({ data, offset: 0 });
|
|
1886
|
+
const metadataAddress = readOptionalNonZeroPubkey({ data, offset: 32 });
|
|
957
1887
|
return { authority, metadataAddress };
|
|
958
1888
|
}
|
|
959
1889
|
function parseTokenMetadataExtension({
|
|
@@ -971,20 +1901,20 @@ function parseTokenMetadataExtension({
|
|
|
971
1901
|
const updateAuthority = isZeroAuthority ? null : tsCdk.PublicKey.fromBytes(updateAuthorityBytes);
|
|
972
1902
|
offset += PUBKEY_SIZE;
|
|
973
1903
|
offset += PUBKEY_SIZE;
|
|
974
|
-
const [name, nameLen] =
|
|
1904
|
+
const [name, nameLen] = readLengthPrefixedString2({ data, offset });
|
|
975
1905
|
offset += nameLen;
|
|
976
|
-
const [symbol, symbolLen] =
|
|
1906
|
+
const [symbol, symbolLen] = readLengthPrefixedString2({ data, offset });
|
|
977
1907
|
offset += symbolLen;
|
|
978
|
-
const [uri, uriLen] =
|
|
1908
|
+
const [uri, uriLen] = readLengthPrefixedString2({ data, offset });
|
|
979
1909
|
offset += uriLen;
|
|
980
1910
|
const additionalMetadata = [];
|
|
981
1911
|
if (offset + 4 <= data.length) {
|
|
982
|
-
const numEntries =
|
|
1912
|
+
const numEntries = readU32LE({ data, offset });
|
|
983
1913
|
offset += 4;
|
|
984
1914
|
for (let i = 0; i < numEntries && offset < data.length; i++) {
|
|
985
|
-
const [key, keyLen] =
|
|
1915
|
+
const [key, keyLen] = readLengthPrefixedString2({ data, offset });
|
|
986
1916
|
offset += keyLen;
|
|
987
|
-
const [value, valueLen] =
|
|
1917
|
+
const [value, valueLen] = readLengthPrefixedString2({ data, offset });
|
|
988
1918
|
offset += valueLen;
|
|
989
1919
|
additionalMetadata.push([key, value]);
|
|
990
1920
|
}
|
|
@@ -1002,14 +1932,17 @@ function parseTokenMetadata({
|
|
|
1002
1932
|
mint,
|
|
1003
1933
|
data
|
|
1004
1934
|
}) {
|
|
1005
|
-
if (data.length <=
|
|
1935
|
+
if (data.length <= TOKEN_ACCOUNT_SIZE) {
|
|
1006
1936
|
return null;
|
|
1007
1937
|
}
|
|
1008
|
-
const accountType = data[
|
|
1938
|
+
const accountType = data[TOKEN_ACCOUNT_SIZE];
|
|
1009
1939
|
if (accountType !== 1 /* Mint */) {
|
|
1010
1940
|
return null;
|
|
1011
1941
|
}
|
|
1012
|
-
const extensions =
|
|
1942
|
+
const extensions = parseTlvExtensions({
|
|
1943
|
+
data,
|
|
1944
|
+
extensionsOffset: MINT_EXTENSIONS_OFFSET
|
|
1945
|
+
});
|
|
1013
1946
|
const metadataExt = extensions.find((ext) => ext.type === 19 /* TokenMetadata */);
|
|
1014
1947
|
if (!metadataExt) {
|
|
1015
1948
|
return null;
|
|
@@ -1019,29 +1952,321 @@ function parseTokenMetadata({
|
|
|
1019
1952
|
function parseMetadataPointerExtension({
|
|
1020
1953
|
data
|
|
1021
1954
|
}) {
|
|
1022
|
-
if (data.length <=
|
|
1955
|
+
if (data.length <= TOKEN_ACCOUNT_SIZE) {
|
|
1023
1956
|
return null;
|
|
1024
1957
|
}
|
|
1025
|
-
const accountType = data[
|
|
1958
|
+
const accountType = data[TOKEN_ACCOUNT_SIZE];
|
|
1026
1959
|
if (accountType !== 1 /* Mint */) {
|
|
1027
1960
|
return null;
|
|
1028
1961
|
}
|
|
1029
|
-
const extensions =
|
|
1962
|
+
const extensions = parseTlvExtensions({
|
|
1963
|
+
data,
|
|
1964
|
+
extensionsOffset: MINT_EXTENSIONS_OFFSET
|
|
1965
|
+
});
|
|
1030
1966
|
const pointerExt = extensions.find((ext) => ext.type === 18 /* MetadataPointer */);
|
|
1031
1967
|
if (!pointerExt) {
|
|
1032
1968
|
return null;
|
|
1033
1969
|
}
|
|
1034
1970
|
return parseMetadataPointer({ data: pointerExt.data });
|
|
1035
1971
|
}
|
|
1036
|
-
|
|
1037
|
-
|
|
1972
|
+
|
|
1973
|
+
// src/state/mint.ts
|
|
1974
|
+
function parseMintAccount({ address, data }) {
|
|
1975
|
+
if (data.length < MINT_SIZE) {
|
|
1976
|
+
throw SplTokenError.invalidMint({
|
|
1977
|
+
reason: `Account data too short: expected at least ${MINT_SIZE} bytes, got ${data.length}`
|
|
1978
|
+
});
|
|
1979
|
+
}
|
|
1980
|
+
const mintAuthority = readCOptionPubkey({ data, offset: 0 });
|
|
1981
|
+
const supply = readU64LE({ data, offset: MINT_SUPPLY_OFFSET });
|
|
1982
|
+
const decimals = data[MINT_DECIMALS_OFFSET];
|
|
1983
|
+
const isInitialized = data[MINT_IS_INITIALIZED_OFFSET] !== 0;
|
|
1984
|
+
const freezeAuthority = readCOptionPubkey({
|
|
1985
|
+
data,
|
|
1986
|
+
offset: MINT_FREEZE_AUTHORITY_OFFSET
|
|
1987
|
+
});
|
|
1988
|
+
if (!isInitialized) {
|
|
1989
|
+
throw SplTokenError.accountNotInitialized({ address: address.toString() });
|
|
1990
|
+
}
|
|
1991
|
+
return {
|
|
1992
|
+
address,
|
|
1993
|
+
supply,
|
|
1994
|
+
decimals,
|
|
1995
|
+
isInitialized,
|
|
1996
|
+
mintAuthority,
|
|
1997
|
+
freezeAuthority
|
|
1998
|
+
};
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// src/state/token-account.ts
|
|
2002
|
+
function readCOptionU64({ data, offset }) {
|
|
2003
|
+
const tag = readU32LE({ data, offset });
|
|
2004
|
+
if (tag === COPTION_SOME) {
|
|
2005
|
+
return readU64LE({ data, offset: offset + 4 });
|
|
2006
|
+
}
|
|
2007
|
+
return null;
|
|
2008
|
+
}
|
|
2009
|
+
function parseTokenAccount({ address, data }) {
|
|
2010
|
+
if (data.length < TOKEN_ACCOUNT_SIZE) {
|
|
2011
|
+
throw SplTokenError.invalidTokenAccount({
|
|
2012
|
+
reason: `Account data too short: expected at least ${TOKEN_ACCOUNT_SIZE} bytes, got ${data.length}`
|
|
2013
|
+
});
|
|
2014
|
+
}
|
|
2015
|
+
const mint = readPubkey({ data, offset: TOKEN_ACCOUNT_MINT_OFFSET });
|
|
2016
|
+
const owner = readPubkey({ data, offset: TOKEN_ACCOUNT_OWNER_OFFSET });
|
|
2017
|
+
const amount = readU64LE({ data, offset: TOKEN_ACCOUNT_AMOUNT_OFFSET });
|
|
2018
|
+
const delegate = readCOptionPubkey({
|
|
2019
|
+
data,
|
|
2020
|
+
offset: TOKEN_ACCOUNT_DELEGATE_OFFSET
|
|
2021
|
+
});
|
|
2022
|
+
const stateValue = data[TOKEN_ACCOUNT_STATE_OFFSET];
|
|
2023
|
+
if (stateValue > 2) {
|
|
2024
|
+
throw SplTokenError.invalidTokenAccount({
|
|
2025
|
+
reason: `Invalid account state: ${stateValue}`
|
|
2026
|
+
});
|
|
2027
|
+
}
|
|
2028
|
+
const state = stateValue;
|
|
2029
|
+
if (state === 0 /* Uninitialized */) {
|
|
2030
|
+
throw SplTokenError.accountNotInitialized({ address: address.toString() });
|
|
2031
|
+
}
|
|
2032
|
+
const isNative = readCOptionU64({
|
|
2033
|
+
data,
|
|
2034
|
+
offset: TOKEN_ACCOUNT_IS_NATIVE_OFFSET
|
|
2035
|
+
});
|
|
2036
|
+
const delegatedAmount = readU64LE({
|
|
2037
|
+
data,
|
|
2038
|
+
offset: TOKEN_ACCOUNT_DELEGATED_AMOUNT_OFFSET
|
|
2039
|
+
});
|
|
2040
|
+
const closeAuthority = readCOptionPubkey({
|
|
2041
|
+
data,
|
|
2042
|
+
offset: TOKEN_ACCOUNT_CLOSE_AUTHORITY_OFFSET
|
|
2043
|
+
});
|
|
2044
|
+
return {
|
|
2045
|
+
address,
|
|
2046
|
+
mint,
|
|
2047
|
+
owner,
|
|
2048
|
+
amount,
|
|
2049
|
+
delegate,
|
|
2050
|
+
state,
|
|
2051
|
+
isNative,
|
|
2052
|
+
delegatedAmount,
|
|
2053
|
+
closeAuthority
|
|
2054
|
+
};
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
// src/transfer-hook/extra-account-meta.ts
|
|
2058
|
+
var EXTRA_ACCOUNT_META_SIZE = 35;
|
|
2059
|
+
function parseExtraAccountMeta(data, offset) {
|
|
2060
|
+
return {
|
|
2061
|
+
discriminator: data[offset],
|
|
2062
|
+
addressConfig: data.slice(offset + 1, offset + 33),
|
|
2063
|
+
isSigner: data[offset + 33] !== 0,
|
|
2064
|
+
isWritable: data[offset + 34] !== 0
|
|
2065
|
+
};
|
|
2066
|
+
}
|
|
2067
|
+
var EXECUTE_DISCRIMINATOR = sha256(
|
|
2068
|
+
new TextEncoder().encode("rialo-s-spl-transfer-hook-interface:execute")
|
|
2069
|
+
).slice(0, 8);
|
|
2070
|
+
var TLV_HEADER_SIZE2 = 16;
|
|
2071
|
+
function parseExtraAccountMetaList(data) {
|
|
2072
|
+
if (data.length < TLV_HEADER_SIZE2) {
|
|
1038
2073
|
return [];
|
|
1039
2074
|
}
|
|
1040
|
-
const
|
|
1041
|
-
|
|
2075
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
2076
|
+
const count = view.getUint32(12, true);
|
|
2077
|
+
if (count === 0) {
|
|
1042
2078
|
return [];
|
|
1043
2079
|
}
|
|
1044
|
-
|
|
2080
|
+
const entries = [];
|
|
2081
|
+
let cursor = TLV_HEADER_SIZE2;
|
|
2082
|
+
for (let i = 0; i < count; i++) {
|
|
2083
|
+
if (cursor + EXTRA_ACCOUNT_META_SIZE > data.length) {
|
|
2084
|
+
break;
|
|
2085
|
+
}
|
|
2086
|
+
entries.push(parseExtraAccountMeta(data, cursor));
|
|
2087
|
+
cursor += EXTRA_ACCOUNT_META_SIZE;
|
|
2088
|
+
}
|
|
2089
|
+
return entries;
|
|
2090
|
+
}
|
|
2091
|
+
function buildExecuteInstructionData(amount) {
|
|
2092
|
+
const data = new Uint8Array(16);
|
|
2093
|
+
data.set(EXECUTE_DISCRIMINATOR, 0);
|
|
2094
|
+
writeU64LE({ data, offset: 8, value: amount });
|
|
2095
|
+
return data;
|
|
2096
|
+
}
|
|
2097
|
+
function getExtraAccountMetaAddress(mint, hookProgramId) {
|
|
2098
|
+
const [pda] = tsCdk.PublicKey.findProgramAddress(
|
|
2099
|
+
["extra-account-metas", mint.toBytes()],
|
|
2100
|
+
hookProgramId
|
|
2101
|
+
);
|
|
2102
|
+
return pda;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
// src/transfer-hook/seeds.ts
|
|
2106
|
+
async function unpackSeeds(params) {
|
|
2107
|
+
const { addressConfig, previousMetas, instructionData, fetchAccountData } = params;
|
|
2108
|
+
const seeds = [];
|
|
2109
|
+
let cursor = 0;
|
|
2110
|
+
if (addressConfig.length < 32) {
|
|
2111
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
2112
|
+
reason: `addressConfig must be at least 32 bytes, got ${addressConfig.length}`
|
|
2113
|
+
});
|
|
2114
|
+
}
|
|
2115
|
+
while (cursor < 32) {
|
|
2116
|
+
const discriminator = addressConfig[cursor];
|
|
2117
|
+
if (discriminator === 0) {
|
|
2118
|
+
break;
|
|
2119
|
+
}
|
|
2120
|
+
cursor++;
|
|
2121
|
+
switch (discriminator) {
|
|
2122
|
+
case 1: {
|
|
2123
|
+
const length = addressConfig[cursor++];
|
|
2124
|
+
seeds.push(addressConfig.slice(cursor, cursor + length));
|
|
2125
|
+
cursor += length;
|
|
2126
|
+
break;
|
|
2127
|
+
}
|
|
2128
|
+
case 2: {
|
|
2129
|
+
const offset = addressConfig[cursor++];
|
|
2130
|
+
const length = addressConfig[cursor++];
|
|
2131
|
+
seeds.push(instructionData.slice(offset, offset + length));
|
|
2132
|
+
break;
|
|
2133
|
+
}
|
|
2134
|
+
case 3: {
|
|
2135
|
+
const index = addressConfig[cursor++];
|
|
2136
|
+
seeds.push(previousMetas[index].pubkey.toBytes());
|
|
2137
|
+
break;
|
|
2138
|
+
}
|
|
2139
|
+
case 4: {
|
|
2140
|
+
const accountIndex = addressConfig[cursor++];
|
|
2141
|
+
const dataOffset = addressConfig[cursor++];
|
|
2142
|
+
const length = addressConfig[cursor++];
|
|
2143
|
+
const data = await fetchAccountData(previousMetas[accountIndex].pubkey);
|
|
2144
|
+
if (data) {
|
|
2145
|
+
seeds.push(data.slice(dataOffset, dataOffset + length));
|
|
2146
|
+
}
|
|
2147
|
+
break;
|
|
2148
|
+
}
|
|
2149
|
+
default: {
|
|
2150
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
2151
|
+
reason: `Unknown seed discriminator ${discriminator} at addressConfig offset ${cursor - 1}`
|
|
2152
|
+
});
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2156
|
+
return seeds;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
// src/transfer-hook/resolve-extra-accounts.ts
|
|
2160
|
+
async function resolveExtraAccountMeta(params) {
|
|
2161
|
+
const { meta, previousMetas, instructionData, hookProgramId, fetchAccountData } = params;
|
|
2162
|
+
if (meta.discriminator === 0) {
|
|
2163
|
+
return {
|
|
2164
|
+
pubkey: tsCdk.PublicKey.fromBytes(meta.addressConfig),
|
|
2165
|
+
isSigner: meta.isSigner,
|
|
2166
|
+
isWritable: meta.isWritable
|
|
2167
|
+
};
|
|
2168
|
+
}
|
|
2169
|
+
if (meta.discriminator === 1) {
|
|
2170
|
+
const seeds2 = await unpackSeeds({
|
|
2171
|
+
addressConfig: meta.addressConfig,
|
|
2172
|
+
previousMetas,
|
|
2173
|
+
instructionData,
|
|
2174
|
+
fetchAccountData
|
|
2175
|
+
});
|
|
2176
|
+
const [pda2] = tsCdk.PublicKey.findProgramAddress(seeds2, hookProgramId);
|
|
2177
|
+
return {
|
|
2178
|
+
pubkey: pda2,
|
|
2179
|
+
isSigner: meta.isSigner,
|
|
2180
|
+
isWritable: meta.isWritable
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
if (meta.discriminator === 2) {
|
|
2184
|
+
const accountIndex2 = meta.addressConfig[0];
|
|
2185
|
+
const dataOffset = meta.addressConfig[1];
|
|
2186
|
+
const data = await fetchAccountData(previousMetas[accountIndex2].pubkey);
|
|
2187
|
+
if (!data) {
|
|
2188
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
2189
|
+
reason: `Failed to fetch account data for discriminator 2 resolution: account at index ${accountIndex2} returned no data`
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
2192
|
+
if (data.length < dataOffset + 32) {
|
|
2193
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
2194
|
+
reason: `Account data too short for discriminator 2 resolution: expected at least ${dataOffset + 32} bytes at offset ${dataOffset}, but data is only ${data.length} bytes`
|
|
2195
|
+
});
|
|
2196
|
+
}
|
|
2197
|
+
const extracted = data.slice(dataOffset, dataOffset + 32);
|
|
2198
|
+
return {
|
|
2199
|
+
pubkey: tsCdk.PublicKey.fromBytes(extracted),
|
|
2200
|
+
isSigner: meta.isSigner,
|
|
2201
|
+
isWritable: meta.isWritable
|
|
2202
|
+
};
|
|
2203
|
+
}
|
|
2204
|
+
const accountIndex = meta.discriminator - 128;
|
|
2205
|
+
if (accountIndex >= previousMetas.length) {
|
|
2206
|
+
throw SplTokenError.pdaDerivationFailed({
|
|
2207
|
+
reason: `External PDA resolution failed: accountIndex ${accountIndex} (discriminator ${meta.discriminator}) is out of bounds for previousMetas of length ${previousMetas.length}`
|
|
2208
|
+
});
|
|
2209
|
+
}
|
|
2210
|
+
const programId = previousMetas[accountIndex].pubkey;
|
|
2211
|
+
const seeds = await unpackSeeds({
|
|
2212
|
+
addressConfig: meta.addressConfig,
|
|
2213
|
+
previousMetas,
|
|
2214
|
+
instructionData,
|
|
2215
|
+
fetchAccountData
|
|
2216
|
+
});
|
|
2217
|
+
const [pda] = tsCdk.PublicKey.findProgramAddress(seeds, programId);
|
|
2218
|
+
return {
|
|
2219
|
+
pubkey: pda,
|
|
2220
|
+
isSigner: meta.isSigner,
|
|
2221
|
+
isWritable: meta.isWritable
|
|
2222
|
+
};
|
|
2223
|
+
}
|
|
2224
|
+
async function resolveTransferHookExtraAccounts(params) {
|
|
2225
|
+
const { mint, hookProgramId, sourceAta, destinationAta, authority, amount, fetchAccountData } = params;
|
|
2226
|
+
const validationPda = getExtraAccountMetaAddress(mint, hookProgramId);
|
|
2227
|
+
const validationData = await fetchAccountData(validationPda);
|
|
2228
|
+
if (!validationData) {
|
|
2229
|
+
return [
|
|
2230
|
+
{ pubkey: hookProgramId, isSigner: false, isWritable: false },
|
|
2231
|
+
{ pubkey: validationPda, isSigner: false, isWritable: false }
|
|
2232
|
+
];
|
|
2233
|
+
}
|
|
2234
|
+
const extraMetas = parseExtraAccountMetaList(validationData);
|
|
2235
|
+
if (extraMetas.length === 0) {
|
|
2236
|
+
return [
|
|
2237
|
+
{ pubkey: hookProgramId, isSigner: false, isWritable: false },
|
|
2238
|
+
{ pubkey: validationPda, isSigner: false, isWritable: false }
|
|
2239
|
+
];
|
|
2240
|
+
}
|
|
2241
|
+
const instructionData = buildExecuteInstructionData(amount);
|
|
2242
|
+
const baseMetas = [
|
|
2243
|
+
{ pubkey: sourceAta, isSigner: false, isWritable: true },
|
|
2244
|
+
{ pubkey: mint, isSigner: false, isWritable: false },
|
|
2245
|
+
{ pubkey: destinationAta, isSigner: false, isWritable: true },
|
|
2246
|
+
{ pubkey: authority, isSigner: false, isWritable: false },
|
|
2247
|
+
{ pubkey: validationPda, isSigner: false, isWritable: false }
|
|
2248
|
+
];
|
|
2249
|
+
const resolvedExtras = [];
|
|
2250
|
+
for (const meta of extraMetas) {
|
|
2251
|
+
const previousMetas = [...baseMetas, ...resolvedExtras];
|
|
2252
|
+
const resolved = await resolveExtraAccountMeta({
|
|
2253
|
+
meta,
|
|
2254
|
+
previousMetas,
|
|
2255
|
+
instructionData,
|
|
2256
|
+
hookProgramId,
|
|
2257
|
+
fetchAccountData
|
|
2258
|
+
});
|
|
2259
|
+
resolvedExtras.push(resolved);
|
|
2260
|
+
}
|
|
2261
|
+
const deEscalated = resolvedExtras.map((account) => ({
|
|
2262
|
+
...account,
|
|
2263
|
+
isSigner: false
|
|
2264
|
+
}));
|
|
2265
|
+
return [
|
|
2266
|
+
...deEscalated,
|
|
2267
|
+
{ pubkey: hookProgramId, isSigner: false, isWritable: false },
|
|
2268
|
+
{ pubkey: validationPda, isSigner: false, isWritable: false }
|
|
2269
|
+
];
|
|
1045
2270
|
}
|
|
1046
2271
|
|
|
1047
2272
|
// src/client/spl-token-client.ts
|
|
@@ -1071,11 +2296,20 @@ var SplTokenClient = class {
|
|
|
1071
2296
|
this.programId = programId;
|
|
1072
2297
|
}
|
|
1073
2298
|
/**
|
|
1074
|
-
*
|
|
2299
|
+
* Returns the Token-2022 program ID used by this client.
|
|
1075
2300
|
*/
|
|
1076
2301
|
getProgramId() {
|
|
1077
2302
|
return this.programId;
|
|
1078
2303
|
}
|
|
2304
|
+
/**
|
|
2305
|
+
* Returns the underlying RialoClient.
|
|
2306
|
+
*
|
|
2307
|
+
* Useful for advanced operations that need direct RPC access,
|
|
2308
|
+
* such as MintBuilder which needs to calculate rent.
|
|
2309
|
+
*/
|
|
2310
|
+
getRialoClient() {
|
|
2311
|
+
return this.client;
|
|
2312
|
+
}
|
|
1079
2313
|
/**
|
|
1080
2314
|
* Retrieves mint account information.
|
|
1081
2315
|
*
|
|
@@ -1085,10 +2319,8 @@ var SplTokenClient = class {
|
|
|
1085
2319
|
*
|
|
1086
2320
|
* @example
|
|
1087
2321
|
* ```typescript
|
|
1088
|
-
* const mintInfo = await tokenClient.getMintInfo({ mint
|
|
1089
|
-
* console.log(
|
|
1090
|
-
* console.log(`Decimals: ${mintInfo.decimals}`);
|
|
1091
|
-
* console.log(`Mint Authority: ${mintInfo.mintAuthority?.toString() ?? 'disabled'}`);
|
|
2322
|
+
* const mintInfo = await tokenClient.getMintInfo({ mint });
|
|
2323
|
+
* console.log(mintInfo.decimals);
|
|
1092
2324
|
* ```
|
|
1093
2325
|
*/
|
|
1094
2326
|
async getMintInfo({ mint }) {
|
|
@@ -1096,7 +2328,10 @@ var SplTokenClient = class {
|
|
|
1096
2328
|
if (!accountInfo) {
|
|
1097
2329
|
throw SplTokenError.mintNotFound({ address: mint.toString() });
|
|
1098
2330
|
}
|
|
1099
|
-
return parseMintAccount({
|
|
2331
|
+
return parseMintAccount({
|
|
2332
|
+
address: mint,
|
|
2333
|
+
data: decodeAccountData(accountInfo.data)
|
|
2334
|
+
});
|
|
1100
2335
|
}
|
|
1101
2336
|
/**
|
|
1102
2337
|
* Retrieves Token-2022 native metadata from a mint.
|
|
@@ -1107,20 +2342,52 @@ var SplTokenClient = class {
|
|
|
1107
2342
|
*
|
|
1108
2343
|
* @example
|
|
1109
2344
|
* ```typescript
|
|
1110
|
-
* const metadata = await tokenClient.getTokenMetadata({ mint
|
|
2345
|
+
* const metadata = await tokenClient.getTokenMetadata({ mint });
|
|
1111
2346
|
* if (metadata) {
|
|
1112
|
-
* console.log(
|
|
1113
|
-
* console.log(`Symbol: ${metadata.symbol}`);
|
|
1114
|
-
* console.log(`URI: ${metadata.uri}`);
|
|
2347
|
+
* console.log(metadata.name, metadata.symbol);
|
|
1115
2348
|
* }
|
|
1116
2349
|
* ```
|
|
1117
2350
|
*/
|
|
1118
|
-
async getTokenMetadata({
|
|
2351
|
+
async getTokenMetadata({
|
|
2352
|
+
mint
|
|
2353
|
+
}) {
|
|
2354
|
+
const accountInfo = await this.client.getAccountInfo(mint);
|
|
2355
|
+
if (!accountInfo) {
|
|
2356
|
+
throw SplTokenError.mintNotFound({ address: mint.toString() });
|
|
2357
|
+
}
|
|
2358
|
+
return parseTokenMetadata({
|
|
2359
|
+
mint,
|
|
2360
|
+
data: decodeAccountData(accountInfo.data)
|
|
2361
|
+
});
|
|
2362
|
+
}
|
|
2363
|
+
/**
|
|
2364
|
+
* Retrieves complete mint account data in a single RPC call.
|
|
2365
|
+
*
|
|
2366
|
+
* Returns parsed mint info, token metadata, and raw extensions from one
|
|
2367
|
+
* `getAccountInfo` call, avoiding the redundant RPC calls that occur when
|
|
2368
|
+
* calling `getMintInfo()` and `getTokenMetadata()` separately.
|
|
2369
|
+
*
|
|
2370
|
+
* Raw extensions include ALL extension types (including PermanentDelegate,
|
|
2371
|
+
* TransferHook, etc.) unlike `getMintExtensionStates()` which only parses
|
|
2372
|
+
* a subset.
|
|
2373
|
+
*
|
|
2374
|
+
* @param options - Options containing the mint public key
|
|
2375
|
+
* @returns Combined mint info, metadata, and raw extensions
|
|
2376
|
+
* @throws {SplTokenError} If the mint account doesn't exist
|
|
2377
|
+
*/
|
|
2378
|
+
async getMintAccountData({
|
|
2379
|
+
mint
|
|
2380
|
+
}) {
|
|
1119
2381
|
const accountInfo = await this.client.getAccountInfo(mint);
|
|
1120
2382
|
if (!accountInfo) {
|
|
1121
2383
|
throw SplTokenError.mintNotFound({ address: mint.toString() });
|
|
1122
2384
|
}
|
|
1123
|
-
|
|
2385
|
+
const data = decodeAccountData(accountInfo.data);
|
|
2386
|
+
return {
|
|
2387
|
+
mintInfo: parseMintAccount({ address: mint, data }),
|
|
2388
|
+
metadata: parseTokenMetadata({ mint, data }),
|
|
2389
|
+
rawExtensions: getMintExtensions({ data })
|
|
2390
|
+
};
|
|
1124
2391
|
}
|
|
1125
2392
|
/**
|
|
1126
2393
|
* Retrieves token account information.
|
|
@@ -1134,9 +2401,14 @@ var SplTokenClient = class {
|
|
|
1134
2401
|
}) {
|
|
1135
2402
|
const accountInfo = await this.client.getAccountInfo(tokenAccount);
|
|
1136
2403
|
if (!accountInfo) {
|
|
1137
|
-
throw SplTokenError.tokenAccountNotFound({
|
|
2404
|
+
throw SplTokenError.tokenAccountNotFound({
|
|
2405
|
+
address: tokenAccount.toString()
|
|
2406
|
+
});
|
|
1138
2407
|
}
|
|
1139
|
-
return parseTokenAccount({
|
|
2408
|
+
return parseTokenAccount({
|
|
2409
|
+
address: tokenAccount,
|
|
2410
|
+
data: decodeAccountData(accountInfo.data)
|
|
2411
|
+
});
|
|
1140
2412
|
}
|
|
1141
2413
|
/**
|
|
1142
2414
|
* Gets the token balance for a wallet.
|
|
@@ -1153,13 +2425,23 @@ var SplTokenClient = class {
|
|
|
1153
2425
|
* console.log(`Token balance: ${balance}`);
|
|
1154
2426
|
* ```
|
|
1155
2427
|
*/
|
|
1156
|
-
async getBalance({
|
|
1157
|
-
|
|
2428
|
+
async getBalance({
|
|
2429
|
+
wallet,
|
|
2430
|
+
mint
|
|
2431
|
+
}) {
|
|
2432
|
+
const ata = getAssociatedTokenAddressSync({
|
|
2433
|
+
wallet,
|
|
2434
|
+
mint,
|
|
2435
|
+
programId: this.programId
|
|
2436
|
+
});
|
|
1158
2437
|
const accountInfo = await this.client.getAccountInfo(ata);
|
|
1159
2438
|
if (!accountInfo) {
|
|
1160
2439
|
return 0n;
|
|
1161
2440
|
}
|
|
1162
|
-
const tokenAccount = parseTokenAccount({
|
|
2441
|
+
const tokenAccount = parseTokenAccount({
|
|
2442
|
+
address: ata,
|
|
2443
|
+
data: decodeAccountData(accountInfo.data)
|
|
2444
|
+
});
|
|
1163
2445
|
return tokenAccount.amount;
|
|
1164
2446
|
}
|
|
1165
2447
|
/**
|
|
@@ -1167,6 +2449,7 @@ var SplTokenClient = class {
|
|
|
1167
2449
|
*
|
|
1168
2450
|
* @param options - Options containing wallet and mint public keys
|
|
1169
2451
|
* @returns The derived ATA address and bump seed
|
|
2452
|
+
* @throws {SplTokenError} If the ATA derivation fails
|
|
1170
2453
|
*
|
|
1171
2454
|
* @example
|
|
1172
2455
|
* ```typescript
|
|
@@ -1178,7 +2461,11 @@ var SplTokenClient = class {
|
|
|
1178
2461
|
wallet,
|
|
1179
2462
|
mint
|
|
1180
2463
|
}) {
|
|
1181
|
-
return findAssociatedTokenAddress({
|
|
2464
|
+
return findAssociatedTokenAddress({
|
|
2465
|
+
wallet,
|
|
2466
|
+
mint,
|
|
2467
|
+
programId: this.programId
|
|
2468
|
+
});
|
|
1182
2469
|
}
|
|
1183
2470
|
/**
|
|
1184
2471
|
* Checks if an Associated Token Account exists.
|
|
@@ -1186,20 +2473,26 @@ var SplTokenClient = class {
|
|
|
1186
2473
|
* @param options - Options containing wallet and mint public keys
|
|
1187
2474
|
* @returns True if the ATA exists, false otherwise
|
|
1188
2475
|
*/
|
|
1189
|
-
async ataExists({
|
|
1190
|
-
|
|
2476
|
+
async ataExists({
|
|
2477
|
+
wallet,
|
|
2478
|
+
mint
|
|
2479
|
+
}) {
|
|
2480
|
+
const ata = getAssociatedTokenAddressSync({
|
|
2481
|
+
wallet,
|
|
2482
|
+
mint,
|
|
2483
|
+
programId: this.programId
|
|
2484
|
+
});
|
|
1191
2485
|
const accountInfo = await this.client.getAccountInfo(ata);
|
|
1192
2486
|
return accountInfo !== null;
|
|
1193
2487
|
}
|
|
1194
2488
|
/**
|
|
1195
2489
|
* Creates instructions for a token transfer.
|
|
1196
2490
|
*
|
|
1197
|
-
*
|
|
2491
|
+
* Builds the necessary instructions for transferring tokens,
|
|
1198
2492
|
* optionally creating the destination ATA if it doesn't exist.
|
|
1199
2493
|
*
|
|
1200
2494
|
* @param params - Transfer parameters
|
|
1201
2495
|
* @returns Array of instructions to execute
|
|
1202
|
-
* @throws {SplTokenError} If the mint doesn't exist
|
|
1203
2496
|
*
|
|
1204
2497
|
* @example
|
|
1205
2498
|
* ```typescript
|
|
@@ -1214,7 +2507,14 @@ var SplTokenClient = class {
|
|
|
1214
2507
|
* ```
|
|
1215
2508
|
*/
|
|
1216
2509
|
async createTransferInstructions(params) {
|
|
1217
|
-
const {
|
|
2510
|
+
const {
|
|
2511
|
+
source,
|
|
2512
|
+
destination,
|
|
2513
|
+
mint,
|
|
2514
|
+
amount,
|
|
2515
|
+
decimals,
|
|
2516
|
+
createDestinationAta = true
|
|
2517
|
+
} = params;
|
|
1218
2518
|
const instructions = [];
|
|
1219
2519
|
const sourceAta = getAssociatedTokenAddressSync({
|
|
1220
2520
|
wallet: source,
|
|
@@ -1227,35 +2527,63 @@ var SplTokenClient = class {
|
|
|
1227
2527
|
programId: this.programId
|
|
1228
2528
|
});
|
|
1229
2529
|
if (createDestinationAta) {
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
})
|
|
1240
|
-
);
|
|
1241
|
-
}
|
|
2530
|
+
instructions.push(
|
|
2531
|
+
createAssociatedTokenAccountIdempotentInstruction({
|
|
2532
|
+
payer: source,
|
|
2533
|
+
associatedToken: destinationAta,
|
|
2534
|
+
owner: destination,
|
|
2535
|
+
mint,
|
|
2536
|
+
programId: this.programId
|
|
2537
|
+
})
|
|
2538
|
+
);
|
|
1242
2539
|
}
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
2540
|
+
if (params.transferFee) {
|
|
2541
|
+
instructions.push(
|
|
2542
|
+
transferCheckedWithFeeInstruction({
|
|
2543
|
+
source: sourceAta,
|
|
2544
|
+
mint,
|
|
2545
|
+
destination: destinationAta,
|
|
2546
|
+
authority: source,
|
|
2547
|
+
amount,
|
|
2548
|
+
decimals,
|
|
2549
|
+
fee: params.transferFee.fee,
|
|
2550
|
+
programId: this.programId
|
|
2551
|
+
})
|
|
2552
|
+
);
|
|
2553
|
+
} else {
|
|
2554
|
+
instructions.push(
|
|
2555
|
+
transferCheckedInstruction({
|
|
2556
|
+
source: sourceAta,
|
|
2557
|
+
mint,
|
|
2558
|
+
destination: destinationAta,
|
|
2559
|
+
authority: source,
|
|
2560
|
+
amount,
|
|
2561
|
+
decimals,
|
|
2562
|
+
programId: this.programId
|
|
2563
|
+
})
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
if (params.transferHook) {
|
|
2567
|
+
const { hookProgramId } = params.transferHook;
|
|
2568
|
+
const transferIx = instructions[instructions.length - 1];
|
|
2569
|
+
const extraAccounts = await resolveTransferHookExtraAccounts({
|
|
1246
2570
|
mint,
|
|
1247
|
-
|
|
2571
|
+
hookProgramId,
|
|
2572
|
+
sourceAta,
|
|
2573
|
+
destinationAta,
|
|
1248
2574
|
authority: source,
|
|
1249
2575
|
amount,
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
2576
|
+
fetchAccountData: async (pubkey) => {
|
|
2577
|
+
const info = await this.client.getAccountInfo(pubkey);
|
|
2578
|
+
return info ? decodeAccountData(info.data) : null;
|
|
2579
|
+
}
|
|
2580
|
+
});
|
|
2581
|
+
for (const account of extraAccounts) {
|
|
2582
|
+
transferIx.accounts.push(account);
|
|
2583
|
+
}
|
|
2584
|
+
}
|
|
1254
2585
|
return instructions;
|
|
1255
2586
|
}
|
|
1256
|
-
/**
|
|
1257
|
-
* Options for creating a transfer transaction.
|
|
1258
|
-
*/
|
|
1259
2587
|
/**
|
|
1260
2588
|
* Creates a transaction for a token transfer.
|
|
1261
2589
|
*
|
|
@@ -1288,18 +2616,19 @@ var SplTokenClient = class {
|
|
|
1288
2616
|
*/
|
|
1289
2617
|
async createTransferTransaction({
|
|
1290
2618
|
params,
|
|
2619
|
+
payer,
|
|
1291
2620
|
validFrom,
|
|
1292
2621
|
configHashPrefix
|
|
1293
2622
|
}) {
|
|
1294
2623
|
const instructions = await this.createTransferInstructions(params);
|
|
1295
|
-
const builder = tsCdk.TransactionBuilder.create().setPayer(
|
|
1296
|
-
for (const
|
|
1297
|
-
builder.addInstruction(
|
|
2624
|
+
const builder = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).setConfigHashPrefix(configHashPrefix);
|
|
2625
|
+
for (const instruction of instructions) {
|
|
2626
|
+
builder.addInstruction(instruction);
|
|
1298
2627
|
}
|
|
1299
2628
|
return builder.build();
|
|
1300
2629
|
}
|
|
1301
2630
|
/**
|
|
1302
|
-
* Transfers tokens
|
|
2631
|
+
* Transfers tokens and sends the transaction.
|
|
1303
2632
|
*
|
|
1304
2633
|
* This is a high-level convenience method that:
|
|
1305
2634
|
* 1. Creates the destination ATA if needed
|
|
@@ -1307,7 +2636,7 @@ var SplTokenClient = class {
|
|
|
1307
2636
|
* 3. Signs and sends the transaction
|
|
1308
2637
|
* 4. Waits for confirmation
|
|
1309
2638
|
*
|
|
1310
|
-
* @param options -
|
|
2639
|
+
* @param options - Transfer params, payer, validFrom, and signers
|
|
1311
2640
|
* @returns Transaction signature
|
|
1312
2641
|
*
|
|
1313
2642
|
* @example
|
|
@@ -1331,21 +2660,209 @@ var SplTokenClient = class {
|
|
|
1331
2660
|
*/
|
|
1332
2661
|
async transfer({
|
|
1333
2662
|
params,
|
|
2663
|
+
payer,
|
|
1334
2664
|
validFrom,
|
|
1335
2665
|
configHashPrefix,
|
|
1336
|
-
|
|
2666
|
+
signers
|
|
2667
|
+
}) {
|
|
2668
|
+
const tx = await this.createTransferTransaction({
|
|
2669
|
+
params,
|
|
2670
|
+
payer,
|
|
2671
|
+
validFrom,
|
|
2672
|
+
configHashPrefix
|
|
2673
|
+
});
|
|
2674
|
+
return this.signAndSend({ tx, signers });
|
|
2675
|
+
}
|
|
2676
|
+
/**
|
|
2677
|
+
* Initializes a mint and sends the transaction.
|
|
2678
|
+
*
|
|
2679
|
+
* @param options - Initialize mint params, payer, validFrom, and signers
|
|
2680
|
+
* @returns Transaction signature
|
|
2681
|
+
*/
|
|
2682
|
+
initializeMint({
|
|
2683
|
+
params,
|
|
2684
|
+
payer,
|
|
2685
|
+
validFrom,
|
|
2686
|
+
signers
|
|
2687
|
+
}) {
|
|
2688
|
+
const instruction = initializeMintInstruction({
|
|
2689
|
+
...params,
|
|
2690
|
+
programId: this.programId
|
|
2691
|
+
});
|
|
2692
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2693
|
+
return this.signAndSend({ tx, signers });
|
|
2694
|
+
}
|
|
2695
|
+
/**
|
|
2696
|
+
* Mints tokens and sends the transaction.
|
|
2697
|
+
*
|
|
2698
|
+
* @param options - Mint-to params, payer, validFrom, and signers
|
|
2699
|
+
* @returns Transaction signature
|
|
2700
|
+
*/
|
|
2701
|
+
mintTo({
|
|
2702
|
+
params,
|
|
2703
|
+
payer,
|
|
2704
|
+
validFrom,
|
|
2705
|
+
signers
|
|
2706
|
+
}) {
|
|
2707
|
+
const instruction = mintToInstruction({
|
|
2708
|
+
...params,
|
|
2709
|
+
programId: this.programId
|
|
2710
|
+
});
|
|
2711
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2712
|
+
return this.signAndSend({ tx, signers });
|
|
2713
|
+
}
|
|
2714
|
+
/**
|
|
2715
|
+
* Initializes token metadata on a mint.
|
|
2716
|
+
*
|
|
2717
|
+
* Use this for the on-mint TokenMetadata extension flow.
|
|
2718
|
+
*
|
|
2719
|
+
* @param options - Token metadata params, payer, validFrom, and signers
|
|
2720
|
+
* @returns Transaction signature
|
|
2721
|
+
*/
|
|
2722
|
+
initializeTokenMetadata({
|
|
2723
|
+
params,
|
|
2724
|
+
payer,
|
|
2725
|
+
validFrom,
|
|
2726
|
+
signers
|
|
2727
|
+
}) {
|
|
2728
|
+
const instruction = initializeTokenMetadataInstruction({
|
|
2729
|
+
...params,
|
|
2730
|
+
programId: params.programId ?? this.programId
|
|
2731
|
+
});
|
|
2732
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2733
|
+
return this.signAndSend({ tx, signers });
|
|
2734
|
+
}
|
|
2735
|
+
/**
|
|
2736
|
+
* Initializes a metadata pointer extension on a mint.
|
|
2737
|
+
*
|
|
2738
|
+
* Use this for the Metadata Pointer flow, where metadata lives in
|
|
2739
|
+
* a separate account and the mint stores a pointer to it.
|
|
2740
|
+
*
|
|
2741
|
+
* @param options - Metadata pointer params, payer, validFrom, and signers
|
|
2742
|
+
* @returns Transaction signature
|
|
2743
|
+
*/
|
|
2744
|
+
initializeMetadataPointer({
|
|
2745
|
+
params,
|
|
2746
|
+
payer,
|
|
2747
|
+
validFrom,
|
|
2748
|
+
signers
|
|
2749
|
+
}) {
|
|
2750
|
+
const instruction = initializeMetadataPointerInstruction({
|
|
2751
|
+
...params,
|
|
2752
|
+
programId: this.programId
|
|
2753
|
+
});
|
|
2754
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2755
|
+
return this.signAndSend({ tx, signers });
|
|
2756
|
+
}
|
|
2757
|
+
/**
|
|
2758
|
+
* Updates a metadata pointer extension on a mint.
|
|
2759
|
+
*
|
|
2760
|
+
* @param options - Metadata pointer params, payer, validFrom, and signers
|
|
2761
|
+
* @returns Transaction signature
|
|
2762
|
+
*/
|
|
2763
|
+
updateMetadataPointer({
|
|
2764
|
+
params,
|
|
2765
|
+
payer,
|
|
2766
|
+
validFrom,
|
|
2767
|
+
signers
|
|
2768
|
+
}) {
|
|
2769
|
+
const instruction = updateMetadataPointerInstruction({
|
|
2770
|
+
...params,
|
|
2771
|
+
programId: this.programId
|
|
2772
|
+
});
|
|
2773
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2774
|
+
return this.signAndSend({ tx, signers });
|
|
2775
|
+
}
|
|
2776
|
+
/**
|
|
2777
|
+
* Initializes a transfer fee config on a mint.
|
|
2778
|
+
*
|
|
2779
|
+
* @param options - Transfer fee config params, payer, validFrom, and signers
|
|
2780
|
+
* @returns Transaction signature
|
|
2781
|
+
*/
|
|
2782
|
+
initializeTransferFeeConfig({
|
|
2783
|
+
params,
|
|
2784
|
+
payer,
|
|
2785
|
+
validFrom,
|
|
2786
|
+
signers
|
|
2787
|
+
}) {
|
|
2788
|
+
const instruction = initializeTransferFeeConfigInstruction({
|
|
2789
|
+
...params,
|
|
2790
|
+
programId: this.programId
|
|
2791
|
+
});
|
|
2792
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2793
|
+
return this.signAndSend({ tx, signers });
|
|
2794
|
+
}
|
|
2795
|
+
/**
|
|
2796
|
+
* Transfers tokens with a fee and sends the transaction.
|
|
2797
|
+
*
|
|
2798
|
+
* @param options - Transfer params, payer, validFrom, and signers
|
|
2799
|
+
* @returns Transaction signature
|
|
2800
|
+
*/
|
|
2801
|
+
transferCheckedWithFee({
|
|
2802
|
+
params,
|
|
2803
|
+
payer,
|
|
2804
|
+
validFrom,
|
|
2805
|
+
signers
|
|
2806
|
+
}) {
|
|
2807
|
+
const instruction = transferCheckedWithFeeInstruction({
|
|
2808
|
+
...params,
|
|
2809
|
+
programId: this.programId
|
|
2810
|
+
});
|
|
2811
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2812
|
+
return this.signAndSend({ tx, signers });
|
|
2813
|
+
}
|
|
2814
|
+
/**
|
|
2815
|
+
* Initializes a non-transferable mint.
|
|
2816
|
+
*
|
|
2817
|
+
* @param options - Non-transferable mint params, payer, validFrom, and signers
|
|
2818
|
+
* @returns Transaction signature
|
|
2819
|
+
*/
|
|
2820
|
+
initializeNonTransferableMint({
|
|
2821
|
+
params,
|
|
2822
|
+
payer,
|
|
2823
|
+
validFrom,
|
|
2824
|
+
signers
|
|
2825
|
+
}) {
|
|
2826
|
+
const instruction = initializeNonTransferableMintInstruction({
|
|
2827
|
+
...params,
|
|
2828
|
+
programId: this.programId
|
|
2829
|
+
});
|
|
2830
|
+
const tx = tsCdk.TransactionBuilder.create().setPayer(payer).setValidFrom(validFrom).addInstruction(instruction).build();
|
|
2831
|
+
return this.signAndSend({ tx, signers });
|
|
2832
|
+
}
|
|
2833
|
+
async signAndSend({
|
|
2834
|
+
tx,
|
|
2835
|
+
signers
|
|
1337
2836
|
}) {
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
2837
|
+
if (signers.length === 0) {
|
|
2838
|
+
throw new Error("At least one signer required.");
|
|
2839
|
+
}
|
|
2840
|
+
const signedTx = await tx.signAllWith(signers);
|
|
2841
|
+
const result = await this.client.sendAndConfirmTransaction(
|
|
2842
|
+
signedTx.serialize()
|
|
2843
|
+
);
|
|
1341
2844
|
return result.signature;
|
|
1342
2845
|
}
|
|
1343
2846
|
};
|
|
1344
|
-
function createSplTokenClient({
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
2847
|
+
function createSplTokenClient(options) {
|
|
2848
|
+
return new SplTokenClient(options);
|
|
2849
|
+
}
|
|
2850
|
+
|
|
2851
|
+
// src/recipes/create-token-with-metadata.ts
|
|
2852
|
+
async function createTokenWithMetadata(tokenClient, params, options) {
|
|
2853
|
+
const builder = MintBuilder.create(tokenClient).withDecimals(params.decimals).withMintAuthority(params.mintAuthority).withMetadata(params.metadata);
|
|
2854
|
+
if (params.freezeAuthority) {
|
|
2855
|
+
builder.withFreezeAuthority(params.freezeAuthority);
|
|
2856
|
+
}
|
|
2857
|
+
if (params.initialMint) {
|
|
2858
|
+
builder.withInitialSupply(params.initialMint);
|
|
2859
|
+
}
|
|
2860
|
+
return await builder.send({
|
|
2861
|
+
payer: options.payer,
|
|
2862
|
+
mintKeypair: options.mintKeypair,
|
|
2863
|
+
validFrom: options.validFrom,
|
|
2864
|
+
signers: options.signers
|
|
2865
|
+
});
|
|
1349
2866
|
}
|
|
1350
2867
|
/*! Bundled license information:
|
|
1351
2868
|
|
|
@@ -1355,29 +2872,65 @@ function createSplTokenClient({
|
|
|
1355
2872
|
|
|
1356
2873
|
exports.ASSOCIATED_TOKEN_PROGRAM_ID = ASSOCIATED_TOKEN_PROGRAM_ID;
|
|
1357
2874
|
exports.AccountType = AccountType;
|
|
2875
|
+
exports.EXECUTE_DISCRIMINATOR = EXECUTE_DISCRIMINATOR;
|
|
2876
|
+
exports.EXTRA_ACCOUNT_META_SIZE = EXTRA_ACCOUNT_META_SIZE;
|
|
1358
2877
|
exports.ExtensionType = ExtensionType;
|
|
1359
2878
|
exports.MINT_SIZE = MINT_SIZE;
|
|
2879
|
+
exports.MintBuilder = MintBuilder;
|
|
1360
2880
|
exports.SplTokenClient = SplTokenClient;
|
|
1361
2881
|
exports.SplTokenError = SplTokenError;
|
|
1362
2882
|
exports.SplTokenErrorCode = SplTokenErrorCode;
|
|
2883
|
+
exports.TLV_LENGTH_SIZE = TLV_LENGTH_SIZE;
|
|
2884
|
+
exports.TLV_TYPE_SIZE = TLV_TYPE_SIZE;
|
|
1363
2885
|
exports.TOKEN_2022_PROGRAM_ID = TOKEN_2022_PROGRAM_ID;
|
|
1364
2886
|
exports.TOKEN_ACCOUNT_SIZE = TOKEN_ACCOUNT_SIZE;
|
|
1365
2887
|
exports.TOKEN_PROGRAM_ID = TOKEN_PROGRAM_ID;
|
|
1366
2888
|
exports.TokenAccountState = TokenAccountState;
|
|
1367
2889
|
exports.TokenInstruction = TokenInstruction;
|
|
2890
|
+
exports.buildExecuteInstructionData = buildExecuteInstructionData;
|
|
1368
2891
|
exports.createAssociatedTokenAccountIdempotentInstruction = createAssociatedTokenAccountIdempotentInstruction;
|
|
1369
2892
|
exports.createAssociatedTokenAccountInstruction = createAssociatedTokenAccountInstruction;
|
|
1370
2893
|
exports.createSplTokenClient = createSplTokenClient;
|
|
2894
|
+
exports.createTokenWithMetadata = createTokenWithMetadata;
|
|
1371
2895
|
exports.findAssociatedTokenAddress = findAssociatedTokenAddress;
|
|
1372
2896
|
exports.getAssociatedTokenAddressSync = getAssociatedTokenAddressSync;
|
|
2897
|
+
exports.getExtraAccountMetaAddress = getExtraAccountMetaAddress;
|
|
2898
|
+
exports.getMetadataExtensionSize = getMetadataExtensionSize;
|
|
2899
|
+
exports.getMinRentForMint = getMinRentForMint;
|
|
2900
|
+
exports.getMinRentForMintWithMetadata = getMinRentForMintWithMetadata;
|
|
2901
|
+
exports.getMintExtensionStates = getMintExtensionStates;
|
|
1373
2902
|
exports.getMintExtensions = getMintExtensions;
|
|
2903
|
+
exports.getMintSizeWithExtensions = getMintSizeWithExtensions;
|
|
2904
|
+
exports.getMintSizeWithMetadata = getMintSizeWithMetadata;
|
|
2905
|
+
exports.getTokenAccountExtensionStates = getTokenAccountExtensionStates;
|
|
2906
|
+
exports.getTokenAccountExtensions = getTokenAccountExtensions;
|
|
2907
|
+
exports.getTokenMetadataDataSize = getTokenMetadataDataSize;
|
|
2908
|
+
exports.initializeMetadataPointerInstruction = initializeMetadataPointerInstruction;
|
|
1374
2909
|
exports.initializeMintInstruction = initializeMintInstruction;
|
|
2910
|
+
exports.initializeNonTransferableMintInstruction = initializeNonTransferableMintInstruction;
|
|
2911
|
+
exports.initializePermanentDelegateInstruction = initializePermanentDelegateInstruction;
|
|
2912
|
+
exports.initializeTokenMetadataInstruction = initializeTokenMetadataInstruction;
|
|
2913
|
+
exports.initializeTransferFeeConfigInstruction = initializeTransferFeeConfigInstruction;
|
|
2914
|
+
exports.initializeTransferHookInstruction = initializeTransferHookInstruction;
|
|
1375
2915
|
exports.mintToInstruction = mintToInstruction;
|
|
2916
|
+
exports.parseExtension = parseExtension;
|
|
2917
|
+
exports.parseExtraAccountMetaList = parseExtraAccountMetaList;
|
|
1376
2918
|
exports.parseMetadataPointerExtension = parseMetadataPointerExtension;
|
|
2919
|
+
exports.parseMetadataPointerExtensionData = parseMetadataPointerExtensionData;
|
|
1377
2920
|
exports.parseMintAccount = parseMintAccount;
|
|
2921
|
+
exports.parsePermanentDelegateExtension = parsePermanentDelegateExtension;
|
|
1378
2922
|
exports.parseTokenAccount = parseTokenAccount;
|
|
1379
2923
|
exports.parseTokenMetadata = parseTokenMetadata;
|
|
2924
|
+
exports.parseTokenMetadataExtensionData = parseTokenMetadataExtensionData;
|
|
2925
|
+
exports.parseTransferFeeConfigExtension = parseTransferFeeConfigExtension;
|
|
2926
|
+
exports.parseTransferHookExtension = parseTransferHookExtension;
|
|
2927
|
+
exports.resolveExtraAccountMeta = resolveExtraAccountMeta;
|
|
2928
|
+
exports.resolveTransferHookExtraAccounts = resolveTransferHookExtraAccounts;
|
|
2929
|
+
exports.setTransferFeeInstruction = setTransferFeeInstruction;
|
|
1380
2930
|
exports.transferCheckedInstruction = transferCheckedInstruction;
|
|
2931
|
+
exports.transferCheckedWithFeeInstruction = transferCheckedWithFeeInstruction;
|
|
1381
2932
|
exports.transferInstruction = transferInstruction;
|
|
2933
|
+
exports.unpackSeeds = unpackSeeds;
|
|
2934
|
+
exports.updateMetadataPointerInstruction = updateMetadataPointerInstruction;
|
|
1382
2935
|
//# sourceMappingURL=index.js.map
|
|
1383
2936
|
//# sourceMappingURL=index.js.map
|