@magicblock-labs/ephemeral-rollups-sdk 0.8.8 → 0.10.1

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.
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.decodeEphemeralAta = decodeEphemeralAta;
4
37
  exports.encodeEphemeralAta = encodeEphemeralAta;
@@ -6,6 +39,7 @@ exports.decodeGlobalVault = decodeGlobalVault;
6
39
  exports.encodeGlobalVault = encodeGlobalVault;
7
40
  exports.deriveEphemeralAta = deriveEphemeralAta;
8
41
  exports.deriveVault = deriveVault;
42
+ exports.deriveRentPda = deriveRentPda;
9
43
  exports.deriveVaultAta = deriveVaultAta;
10
44
  exports.deriveShuttleEphemeralAta = deriveShuttleEphemeralAta;
11
45
  exports.deriveShuttleAta = deriveShuttleAta;
@@ -13,11 +47,15 @@ exports.deriveShuttleWalletAta = deriveShuttleWalletAta;
13
47
  exports.initEphemeralAtaIx = initEphemeralAtaIx;
14
48
  exports.initVaultAtaIx = initVaultAtaIx;
15
49
  exports.initVaultIx = initVaultIx;
50
+ exports.initRentPdaIx = initRentPdaIx;
16
51
  exports.transferToVaultIx = transferToVaultIx;
17
52
  exports.depositSplTokensIx = depositSplTokensIx;
18
53
  exports.delegateEphemeralAtaIx = delegateEphemeralAtaIx;
19
54
  exports.initShuttleEphemeralAtaIx = initShuttleEphemeralAtaIx;
20
55
  exports.delegateShuttleEphemeralAtaIx = delegateShuttleEphemeralAtaIx;
56
+ exports.setupAndDelegateShuttleEphemeralAtaWithMergeIx = setupAndDelegateShuttleEphemeralAtaWithMergeIx;
57
+ exports.depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx = depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx;
58
+ exports.withdrawThroughDelegatedShuttleWithMergeIx = withdrawThroughDelegatedShuttleWithMergeIx;
21
59
  exports.mergeShuttleIntoAtaIx = mergeShuttleIntoAtaIx;
22
60
  exports.undelegateAndCloseShuttleEphemeralAtaIx = undelegateAndCloseShuttleEphemeralAtaIx;
23
61
  exports.withdrawSplIx = withdrawSplIx;
@@ -27,14 +65,19 @@ exports.resetEataPermissionIx = resetEataPermissionIx;
27
65
  exports.delegateEataPermissionIx = delegateEataPermissionIx;
28
66
  exports.undelegateEataPermissionIx = undelegateEataPermissionIx;
29
67
  exports.delegateSpl = delegateSpl;
30
- exports.delegateSplIdempotent = delegateSplIdempotent;
31
- exports.delegatePrivateSpl = delegatePrivateSpl;
68
+ exports.delegateSplWithPrivateTransfer = delegateSplWithPrivateTransfer;
69
+ exports.transferSpl = transferSpl;
70
+ exports.withdrawSpl = withdrawSpl;
32
71
  const web3_js_1 = require("@solana/web3.js");
72
+ const blake2b_1 = require("@noble/hashes/blake2b");
73
+ const ed25519_1 = require("@noble/curves/ed25519");
74
+ const nacl = __importStar(require("tweetnacl"));
33
75
  const constants_js_1 = require("../../constants.js");
34
76
  const pda_js_1 = require("../../pda.js");
35
- const DEFAULT_PRIVATE_VALIDATOR = new web3_js_1.PublicKey("FnE6VJT5QNZdedZPnCoLsARgBwoE6DeJNjBs2H1gySXA");
77
+ const transferQueue_js_1 = require("./transferQueue.js");
36
78
  const TOKEN_PROGRAM_ID = new web3_js_1.PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
37
79
  const ASSOCIATED_TOKEN_PROGRAM_ID = new web3_js_1.PublicKey("ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL");
80
+ const QUEUED_TRANSFER_FLAG_CREATE_IDEMPOTENT_ATA = 1 << 0;
38
81
  function getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve = false, programId = TOKEN_PROGRAM_ID, associatedTokenProgramId = ASSOCIATED_TOKEN_PROGRAM_ID) {
39
82
  if (!allowOwnerOffCurve && !web3_js_1.PublicKey.isOnCurve(owner)) {
40
83
  throw new Error("Owner public key is off-curve");
@@ -57,6 +100,66 @@ function createAssociatedTokenAccountIdempotentInstruction(payer, associatedToke
57
100
  data,
58
101
  });
59
102
  }
103
+ function createTransferInstruction(source, destination, owner, amount, multiSigners = [], programId = TOKEN_PROGRAM_ID) {
104
+ const data = Buffer.alloc(9);
105
+ data[0] = 3;
106
+ data.writeBigUInt64LE(amount, 1);
107
+ const keys = [
108
+ { pubkey: source, isSigner: false, isWritable: true },
109
+ { pubkey: destination, isSigner: false, isWritable: true },
110
+ ];
111
+ if (multiSigners.length === 0) {
112
+ keys.push({ pubkey: owner, isSigner: true, isWritable: false });
113
+ }
114
+ else {
115
+ keys.push({ pubkey: owner, isSigner: false, isWritable: false });
116
+ for (const signer of multiSigners) {
117
+ keys.push({ pubkey: signer, isSigner: true, isWritable: false });
118
+ }
119
+ }
120
+ return new web3_js_1.TransactionInstruction({
121
+ programId,
122
+ keys,
123
+ data,
124
+ });
125
+ }
126
+ function encryptEd25519Recipient(plaintext, recipient) {
127
+ const recipientX25519 = (0, ed25519_1.edwardsToMontgomeryPub)(recipient.toBytes());
128
+ const ephemeral = nacl.box.keyPair();
129
+ const nonce = (0, blake2b_1.blake2b)(Buffer.concat([
130
+ Buffer.from(ephemeral.publicKey),
131
+ Buffer.from(recipientX25519),
132
+ ]), { dkLen: nacl.box.nonceLength });
133
+ const ciphertext = nacl.box(plaintext, nonce, recipientX25519, ephemeral.secretKey);
134
+ return Buffer.concat([
135
+ Buffer.from(ephemeral.publicKey),
136
+ Buffer.from(ciphertext),
137
+ ]);
138
+ }
139
+ function encodeLengthPrefixedBytes(bytes) {
140
+ if (bytes.length > 0xff) {
141
+ throw new Error("encrypted private transfer payload exceeds u8 length");
142
+ }
143
+ return Buffer.concat([Buffer.from([bytes.length]), Buffer.from(bytes)]);
144
+ }
145
+ function packPrivateTransferSuffix(minDelayMs, maxDelayMs, split, flags = 0) {
146
+ const suffix = Buffer.alloc(8 + 8 + 4 + 1);
147
+ suffix.writeBigUInt64LE(minDelayMs, 0);
148
+ suffix.writeBigUInt64LE(maxDelayMs, 8);
149
+ suffix.writeUInt32LE(split, 16);
150
+ suffix.writeUInt8(flags, 20);
151
+ return suffix;
152
+ }
153
+ function u32leBuffer(value) {
154
+ const out = Buffer.alloc(4);
155
+ out.writeUInt32LE(value, 0);
156
+ return out;
157
+ }
158
+ function u64leBuffer(value) {
159
+ const out = Buffer.alloc(8);
160
+ out.writeBigUInt64LE(value, 0);
161
+ return out;
162
+ }
60
163
  function decodeEphemeralAta(info) {
61
164
  if (info.data.length < 72) {
62
165
  throw new Error("Invalid EphemeralAta account data length");
@@ -95,6 +198,9 @@ function deriveEphemeralAta(owner, mint) {
95
198
  function deriveVault(mint) {
96
199
  return web3_js_1.PublicKey.findProgramAddressSync([mint.toBuffer()], constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
97
200
  }
201
+ function deriveRentPda() {
202
+ return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from("rent")], constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
203
+ }
98
204
  function deriveVaultAta(mint, vault) {
99
205
  return getAssociatedTokenAddressSync(mint, vault, true);
100
206
  }
@@ -114,7 +220,7 @@ function deriveShuttleAta(shuttleEphemeralAta, mint) {
114
220
  function deriveShuttleWalletAta(mint, shuttleEphemeralAta) {
115
221
  return getAssociatedTokenAddressSync(mint, shuttleEphemeralAta, true);
116
222
  }
117
- function initEphemeralAtaIx(ephemeralAta, owner, mint, payer, bump) {
223
+ function initEphemeralAtaIx(ephemeralAta, owner, mint, payer) {
118
224
  return new web3_js_1.TransactionInstruction({
119
225
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
120
226
  keys: [
@@ -124,13 +230,14 @@ function initEphemeralAtaIx(ephemeralAta, owner, mint, payer, bump) {
124
230
  { pubkey: mint, isSigner: false, isWritable: false },
125
231
  { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
126
232
  ],
127
- data: Buffer.from([0, bump]),
233
+ data: Buffer.from([0]),
128
234
  });
129
235
  }
130
236
  function initVaultAtaIx(payer, vaultAta, vault, mint) {
131
237
  return createAssociatedTokenAccountIdempotentInstruction(payer, vaultAta, vault, mint);
132
238
  }
133
- function initVaultIx(vault, mint, payer, bump) {
239
+ function initVaultIx(vault, mint, payer) {
240
+ const [vaultEphemeralAta] = deriveEphemeralAta(vault, mint);
134
241
  const vaultAta = deriveVaultAta(mint, vault);
135
242
  return new web3_js_1.TransactionInstruction({
136
243
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
@@ -138,6 +245,7 @@ function initVaultIx(vault, mint, payer, bump) {
138
245
  { pubkey: vault, isSigner: false, isWritable: true },
139
246
  { pubkey: payer, isSigner: true, isWritable: true },
140
247
  { pubkey: mint, isSigner: false, isWritable: false },
248
+ { pubkey: vaultEphemeralAta, isSigner: false, isWritable: true },
141
249
  { pubkey: vaultAta, isSigner: false, isWritable: true },
142
250
  { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
143
251
  {
@@ -147,7 +255,18 @@ function initVaultIx(vault, mint, payer, bump) {
147
255
  },
148
256
  { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
149
257
  ],
150
- data: Buffer.from([1, bump]),
258
+ data: Buffer.from([1]),
259
+ });
260
+ }
261
+ function initRentPdaIx(payer, rentPda) {
262
+ return new web3_js_1.TransactionInstruction({
263
+ programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
264
+ keys: [
265
+ { pubkey: payer, isSigner: true, isWritable: true },
266
+ { pubkey: rentPda, isSigner: false, isWritable: true },
267
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
268
+ ],
269
+ data: Buffer.from([23]),
151
270
  });
152
271
  }
153
272
  function transferToVaultIx(ephemeralAta, vault, mint, sourceAta, vaultAta, owner, amount) {
@@ -162,16 +281,16 @@ function transferToVaultIx(ephemeralAta, vault, mint, sourceAta, vaultAta, owner
162
281
  { pubkey: owner, isSigner: true, isWritable: false },
163
282
  { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
164
283
  ],
165
- data: Buffer.from([2, ...u64le(amount)]),
284
+ data: encodeAmountInstructionData(2, amount),
166
285
  });
167
286
  }
168
287
  function depositSplTokensIx(ephemeralAta, vault, mint, sourceAta, vaultAta, owner, amount) {
169
288
  return transferToVaultIx(ephemeralAta, vault, mint, sourceAta, vaultAta, owner, amount);
170
289
  }
171
- function delegateEphemeralAtaIx(payer, ephemeralAta, bump, validator) {
290
+ function delegateEphemeralAtaIx(payer, ephemeralAta, validator) {
172
291
  const data = validator
173
- ? Buffer.concat([Buffer.from([4, bump]), validator.toBuffer()])
174
- : Buffer.from([4, bump]);
292
+ ? Buffer.concat([Buffer.from([4]), validator.toBuffer()])
293
+ : Buffer.from([4]);
175
294
  return new web3_js_1.TransactionInstruction({
176
295
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
177
296
  keys: [
@@ -203,16 +322,15 @@ function delegateEphemeralAtaIx(payer, ephemeralAta, bump, validator) {
203
322
  data,
204
323
  });
205
324
  }
206
- function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId, bump) {
325
+ function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId) {
207
326
  if (!Number.isInteger(shuttleId) ||
208
327
  shuttleId < 0 ||
209
328
  shuttleId > 4294967295) {
210
329
  throw new Error("shuttleId must fit in u32");
211
330
  }
212
- const data = Buffer.alloc(6);
331
+ const data = Buffer.alloc(5);
213
332
  data[0] = 11;
214
333
  data.writeUInt32LE(shuttleId, 1);
215
- data[5] = bump;
216
334
  return new web3_js_1.TransactionInstruction({
217
335
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
218
336
  keys: [
@@ -233,10 +351,10 @@ function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shutt
233
351
  data,
234
352
  });
235
353
  }
236
- function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, bump, validator) {
354
+ function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, validator) {
237
355
  const data = validator
238
- ? Buffer.concat([Buffer.from([13, bump]), validator.toBuffer()])
239
- : Buffer.from([13, bump]);
356
+ ? Buffer.concat([Buffer.from([13]), validator.toBuffer()])
357
+ : Buffer.from([13]);
240
358
  return new web3_js_1.TransactionInstruction({
241
359
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
242
360
  keys: [
@@ -269,6 +387,206 @@ function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, b
269
387
  data,
270
388
  });
271
389
  }
390
+ function setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, sourceAta, destinationAta, shuttleWalletAta, mint, shuttleId, amount, validator) {
391
+ if (!Number.isInteger(shuttleId) ||
392
+ shuttleId < 0 ||
393
+ shuttleId > 4294967295) {
394
+ throw new Error("shuttleId must fit in u32");
395
+ }
396
+ const [rentPda] = deriveRentPda();
397
+ const [vault] = deriveVault(mint);
398
+ const vaultAta = deriveVaultAta(mint, vault);
399
+ const data = validator ? Buffer.alloc(45) : Buffer.alloc(13);
400
+ data[0] = 24;
401
+ data.writeUInt32LE(shuttleId, 1);
402
+ data.writeBigUInt64LE(amount, 5);
403
+ if (validator) {
404
+ validator.toBuffer().copy(data, 13);
405
+ }
406
+ return new web3_js_1.TransactionInstruction({
407
+ programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
408
+ keys: [
409
+ { pubkey: payer, isSigner: true, isWritable: true },
410
+ { pubkey: rentPda, isSigner: false, isWritable: true },
411
+ { pubkey: shuttleEphemeralAta, isSigner: false, isWritable: true },
412
+ { pubkey: shuttleAta, isSigner: false, isWritable: true },
413
+ { pubkey: shuttleWalletAta, isSigner: false, isWritable: true },
414
+ { pubkey: owner, isSigner: true, isWritable: false },
415
+ {
416
+ pubkey: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
417
+ isSigner: false,
418
+ isWritable: false,
419
+ },
420
+ {
421
+ pubkey: (0, pda_js_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID),
422
+ isSigner: false,
423
+ isWritable: true,
424
+ },
425
+ {
426
+ pubkey: (0, pda_js_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta),
427
+ isSigner: false,
428
+ isWritable: true,
429
+ },
430
+ {
431
+ pubkey: (0, pda_js_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta),
432
+ isSigner: false,
433
+ isWritable: true,
434
+ },
435
+ { pubkey: constants_js_1.DELEGATION_PROGRAM_ID, isSigner: false, isWritable: false },
436
+ {
437
+ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
438
+ isSigner: false,
439
+ isWritable: false,
440
+ },
441
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
442
+ { pubkey: destinationAta, isSigner: false, isWritable: true },
443
+ { pubkey: mint, isSigner: false, isWritable: false },
444
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
445
+ { pubkey: vault, isSigner: false, isWritable: false },
446
+ { pubkey: sourceAta, isSigner: false, isWritable: true },
447
+ { pubkey: vaultAta, isSigner: false, isWritable: true },
448
+ ],
449
+ data,
450
+ });
451
+ }
452
+ function depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx(payer, shuttleEphemeralAta, shuttleAta, owner, sourceAta, destinationOwner, shuttleWalletAta, mint, shuttleId, amount, minDelayMs, maxDelayMs, split, validator) {
453
+ if (!Number.isInteger(shuttleId) ||
454
+ shuttleId < 0 ||
455
+ shuttleId > 4294967295) {
456
+ throw new Error("shuttleId must fit in u32");
457
+ }
458
+ if (!Number.isInteger(split) || split <= 0 || split > 4294967295) {
459
+ throw new Error("split must fit in u32");
460
+ }
461
+ if (amount < 0n || minDelayMs < 0n || maxDelayMs < 0n) {
462
+ throw new Error("amount and delays must be non-negative");
463
+ }
464
+ if (maxDelayMs < minDelayMs) {
465
+ throw new Error("maxDelayMs must be greater than or equal to minDelayMs");
466
+ }
467
+ if (validator == null) {
468
+ throw new Error("validator is required for encrypted private transfers");
469
+ }
470
+ const [rentPda] = deriveRentPda();
471
+ const [vault] = deriveVault(mint);
472
+ const vaultAta = deriveVaultAta(mint, vault);
473
+ const [queue] = (0, transferQueue_js_1.deriveTransferQueue)(mint);
474
+ const encryptedDestination = encryptEd25519Recipient(destinationOwner.toBytes(), validator);
475
+ const encryptedSuffix = encryptEd25519Recipient(packPrivateTransferSuffix(minDelayMs, maxDelayMs, split, QUEUED_TRANSFER_FLAG_CREATE_IDEMPOTENT_ATA), validator);
476
+ const data = Buffer.concat([
477
+ Buffer.from([25]),
478
+ u32leBuffer(shuttleId),
479
+ u64leBuffer(amount),
480
+ encodeLengthPrefixedBytes(validator.toBytes()),
481
+ encodeLengthPrefixedBytes(encryptedDestination),
482
+ encodeLengthPrefixedBytes(encryptedSuffix),
483
+ ]);
484
+ return new web3_js_1.TransactionInstruction({
485
+ programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
486
+ keys: [
487
+ { pubkey: payer, isSigner: true, isWritable: true },
488
+ { pubkey: rentPda, isSigner: false, isWritable: true },
489
+ { pubkey: shuttleEphemeralAta, isSigner: false, isWritable: true },
490
+ { pubkey: shuttleAta, isSigner: false, isWritable: true },
491
+ { pubkey: shuttleWalletAta, isSigner: false, isWritable: true },
492
+ { pubkey: owner, isSigner: true, isWritable: false },
493
+ {
494
+ pubkey: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
495
+ isSigner: false,
496
+ isWritable: false,
497
+ },
498
+ {
499
+ pubkey: (0, pda_js_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID),
500
+ isSigner: false,
501
+ isWritable: true,
502
+ },
503
+ {
504
+ pubkey: (0, pda_js_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta),
505
+ isSigner: false,
506
+ isWritable: true,
507
+ },
508
+ {
509
+ pubkey: (0, pda_js_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta),
510
+ isSigner: false,
511
+ isWritable: true,
512
+ },
513
+ { pubkey: constants_js_1.DELEGATION_PROGRAM_ID, isSigner: false, isWritable: false },
514
+ {
515
+ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
516
+ isSigner: false,
517
+ isWritable: false,
518
+ },
519
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
520
+ { pubkey: mint, isSigner: false, isWritable: false },
521
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
522
+ { pubkey: vault, isSigner: false, isWritable: false },
523
+ { pubkey: sourceAta, isSigner: false, isWritable: true },
524
+ { pubkey: vaultAta, isSigner: false, isWritable: true },
525
+ { pubkey: queue, isSigner: false, isWritable: true },
526
+ ],
527
+ data,
528
+ });
529
+ }
530
+ function withdrawThroughDelegatedShuttleWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator) {
531
+ if (!Number.isInteger(shuttleId) ||
532
+ shuttleId < 0 ||
533
+ shuttleId > 4294967295) {
534
+ throw new Error("shuttleId must fit in u32");
535
+ }
536
+ if (amount < 0n) {
537
+ throw new Error("amount must be non-negative");
538
+ }
539
+ const [rentPda] = deriveRentPda();
540
+ const data = validator ? Buffer.alloc(45) : Buffer.alloc(13);
541
+ data[0] = 26;
542
+ data.writeUInt32LE(shuttleId, 1);
543
+ data.writeBigUInt64LE(amount, 5);
544
+ if (validator) {
545
+ validator.toBuffer().copy(data, 13);
546
+ }
547
+ return new web3_js_1.TransactionInstruction({
548
+ programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
549
+ keys: [
550
+ { pubkey: payer, isSigner: true, isWritable: true },
551
+ { pubkey: rentPda, isSigner: false, isWritable: true },
552
+ { pubkey: shuttleEphemeralAta, isSigner: false, isWritable: true },
553
+ { pubkey: shuttleAta, isSigner: false, isWritable: true },
554
+ { pubkey: shuttleWalletAta, isSigner: false, isWritable: true },
555
+ { pubkey: owner, isSigner: true, isWritable: false },
556
+ {
557
+ pubkey: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
558
+ isSigner: false,
559
+ isWritable: false,
560
+ },
561
+ {
562
+ pubkey: (0, pda_js_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID),
563
+ isSigner: false,
564
+ isWritable: true,
565
+ },
566
+ {
567
+ pubkey: (0, pda_js_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta),
568
+ isSigner: false,
569
+ isWritable: true,
570
+ },
571
+ {
572
+ pubkey: (0, pda_js_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta),
573
+ isSigner: false,
574
+ isWritable: true,
575
+ },
576
+ { pubkey: constants_js_1.DELEGATION_PROGRAM_ID, isSigner: false, isWritable: false },
577
+ {
578
+ pubkey: ASSOCIATED_TOKEN_PROGRAM_ID,
579
+ isSigner: false,
580
+ isWritable: false,
581
+ },
582
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
583
+ { pubkey: ownerAta, isSigner: false, isWritable: true },
584
+ { pubkey: mint, isSigner: false, isWritable: false },
585
+ { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
586
+ ],
587
+ data,
588
+ });
589
+ }
272
590
  function mergeShuttleIntoAtaIx(owner, destinationAta, shuttleEphemeralAta, shuttleWalletAta, mint) {
273
591
  return new web3_js_1.TransactionInstruction({
274
592
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
@@ -283,7 +601,10 @@ function mergeShuttleIntoAtaIx(owner, destinationAta, shuttleEphemeralAta, shutt
283
601
  data: Buffer.from([15]),
284
602
  });
285
603
  }
286
- function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta) {
604
+ function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, escrowIndex) {
605
+ const data = escrowIndex === undefined
606
+ ? Buffer.from([14])
607
+ : Buffer.from([14, escrowIndex]);
287
608
  return new web3_js_1.TransactionInstruction({
288
609
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
289
610
  keys: [
@@ -295,12 +616,12 @@ function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shu
295
616
  { pubkey: constants_js_1.MAGIC_CONTEXT_ID, isSigner: false, isWritable: true },
296
617
  { pubkey: constants_js_1.MAGIC_PROGRAM_ID, isSigner: false, isWritable: false },
297
618
  ],
298
- data: Buffer.from([14]),
619
+ data,
299
620
  });
300
621
  }
301
622
  function withdrawSplIx(owner, mint, amount) {
302
623
  const [ephemeralAta] = deriveEphemeralAta(owner, mint);
303
- const [vault, vaultBump] = deriveVault(mint);
624
+ const [vault] = deriveVault(mint);
304
625
  const vaultAta = deriveVaultAta(mint, vault);
305
626
  const userDestAta = getAssociatedTokenAddressSync(mint, owner);
306
627
  return new web3_js_1.TransactionInstruction({
@@ -314,7 +635,7 @@ function withdrawSplIx(owner, mint, amount) {
314
635
  { pubkey: userDestAta, isSigner: false, isWritable: true },
315
636
  { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
316
637
  ],
317
- data: Buffer.from([3, ...u64le(amount), vaultBump]),
638
+ data: encodeAmountInstructionData(3, amount),
318
639
  });
319
640
  }
320
641
  function undelegateIx(owner, mint) {
@@ -352,7 +673,7 @@ function undelegateIx(owner, mint) {
352
673
  data: Buffer.from([5]),
353
674
  });
354
675
  }
355
- function createEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
676
+ function createEataPermissionIx(ephemeralAta, payer, flags = 0) {
356
677
  const permission = (0, pda_js_1.permissionPdaFromAccount)(ephemeralAta);
357
678
  return new web3_js_1.TransactionInstruction({
358
679
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
@@ -363,10 +684,10 @@ function createEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
363
684
  { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
364
685
  { pubkey: constants_js_1.PERMISSION_PROGRAM_ID, isSigner: false, isWritable: false },
365
686
  ],
366
- data: Buffer.from([6, bump, flags]),
687
+ data: Buffer.from([6, flags]),
367
688
  });
368
689
  }
369
- function resetEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
690
+ function resetEataPermissionIx(ephemeralAta, payer, flags = 0) {
370
691
  const permission = (0, pda_js_1.permissionPdaFromAccount)(ephemeralAta);
371
692
  return new web3_js_1.TransactionInstruction({
372
693
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
@@ -376,10 +697,10 @@ function resetEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
376
697
  { pubkey: payer, isSigner: true, isWritable: false },
377
698
  { pubkey: constants_js_1.PERMISSION_PROGRAM_ID, isSigner: false, isWritable: false },
378
699
  ],
379
- data: Buffer.from([9, bump, flags]),
700
+ data: Buffer.from([9, flags]),
380
701
  });
381
702
  }
382
- function delegateEataPermissionIx(payer, ephemeralAta, bump, validator) {
703
+ function delegateEataPermissionIx(payer, ephemeralAta, validator) {
383
704
  const permission = (0, pda_js_1.permissionPdaFromAccount)(ephemeralAta);
384
705
  return new web3_js_1.TransactionInstruction({
385
706
  programId: constants_js_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
@@ -407,7 +728,7 @@ function delegateEataPermissionIx(payer, ephemeralAta, bump, validator) {
407
728
  { pubkey: constants_js_1.DELEGATION_PROGRAM_ID, isSigner: false, isWritable: false },
408
729
  { pubkey: validator, isSigner: false, isWritable: false },
409
730
  ],
410
- data: Buffer.from([7, bump]),
731
+ data: Buffer.from([7]),
411
732
  });
412
733
  }
413
734
  function undelegateEataPermissionIx(owner, ephemeralAta) {
@@ -425,99 +746,241 @@ function undelegateEataPermissionIx(owner, ephemeralAta) {
425
746
  data: Buffer.from([8]),
426
747
  });
427
748
  }
428
- async function delegateSpl(owner, mint, amount, opts) {
749
+ function randomShuttleId() {
750
+ const cryptoObj = globalThis?.crypto;
751
+ if (cryptoObj?.getRandomValues !== undefined) {
752
+ const buf = new Uint32Array(1);
753
+ cryptoObj.getRandomValues(buf);
754
+ return buf[0];
755
+ }
756
+ return Math.floor(Math.random() * 4294967296);
757
+ }
758
+ async function buildDelegateSplInstructions(owner, mint, amount, opts) {
429
759
  const payer = opts?.payer ?? owner;
430
760
  const validator = opts?.validator;
431
761
  const initIfMissing = opts?.initIfMissing ?? true;
432
762
  const initVaultIfMissing = opts?.initVaultIfMissing ?? initIfMissing;
763
+ const isPrivate = opts?.private ?? false;
433
764
  const instructions = [];
434
- const [ephemeralAta, eataBump] = deriveEphemeralAta(owner, mint);
435
- const [vault, vaultBump] = deriveVault(mint);
765
+ const [ephemeralAta] = deriveEphemeralAta(owner, mint);
766
+ const [vault] = deriveVault(mint);
767
+ const [vaultEphemeralAta] = deriveEphemeralAta(vault, mint);
436
768
  const vaultAta = deriveVaultAta(mint, vault);
437
769
  const ownerAta = getAssociatedTokenAddressSync(mint, owner);
438
770
  if (initIfMissing) {
439
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump));
771
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
440
772
  }
441
773
  if (initVaultIfMissing) {
442
- instructions.push(initVaultIx(vault, mint, payer, vaultBump), initVaultAtaIx(payer, vaultAta, vault, mint));
774
+ instructions.push(initVaultIx(vault, mint, payer), initVaultAtaIx(payer, vaultAta, vault, mint), delegateEphemeralAtaIx(payer, vaultEphemeralAta, validator));
443
775
  }
444
776
  instructions.push(transferToVaultIx(ephemeralAta, vault, mint, ownerAta, vaultAta, owner, amount));
445
- instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, eataBump, validator));
777
+ if (isPrivate) {
778
+ instructions.push(createEataPermissionIx(ephemeralAta, payer));
779
+ }
780
+ instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, validator));
446
781
  return instructions;
447
782
  }
448
- async function delegateSplIdempotent(owner, mint, amount, opts) {
783
+ async function buildIdempotentDelegateSplInstructions(owner, mint, amount, opts) {
449
784
  const payer = opts?.payer ?? owner;
450
785
  const validator = opts?.validator;
786
+ const initIfMissing = opts?.initIfMissing ?? true;
451
787
  const initVaultIfMissing = opts?.initVaultIfMissing ?? false;
452
788
  const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
453
- const randomShuttleId = () => {
454
- const cryptoObj = globalThis?.crypto;
455
- if (cryptoObj?.getRandomValues !== undefined) {
456
- const buf = new Uint32Array(1);
457
- cryptoObj.getRandomValues(buf);
458
- return buf[0];
459
- }
460
- return Math.floor(Math.random() * 4294967296);
461
- };
789
+ const isPrivate = opts?.private ?? false;
462
790
  const shuttleId = opts?.shuttleId ?? randomShuttleId();
463
791
  const instructions = [];
464
- const [ephemeralAta, eataBump] = deriveEphemeralAta(owner, mint);
465
- const [vault, vaultBump] = deriveVault(mint);
792
+ const [ephemeralAta] = deriveEphemeralAta(owner, mint);
793
+ const [vault] = deriveVault(mint);
794
+ const [vaultEphemeralAta] = deriveEphemeralAta(vault, mint);
466
795
  const vaultAta = deriveVaultAta(mint, vault);
467
796
  const ownerAta = getAssociatedTokenAddressSync(mint, owner);
468
- const [shuttleEphemeralAta, shuttleBump] = deriveShuttleEphemeralAta(owner, mint, shuttleId);
469
- const [shuttleAta, shuttleAtaBump] = deriveShuttleAta(shuttleEphemeralAta, mint);
797
+ const [shuttleEphemeralAta] = deriveShuttleEphemeralAta(owner, mint, shuttleId);
798
+ const [shuttleAta] = deriveShuttleAta(shuttleEphemeralAta, mint);
470
799
  const shuttleWalletAta = deriveShuttleWalletAta(mint, shuttleEphemeralAta);
471
800
  if (initVaultIfMissing) {
472
- instructions.push(initVaultIx(vault, mint, payer, vaultBump), initVaultAtaIx(payer, vaultAta, vault, mint));
801
+ instructions.push(initVaultIx(vault, mint, payer), initVaultAtaIx(payer, vaultAta, vault, mint), delegateEphemeralAtaIx(payer, vaultEphemeralAta, validator));
473
802
  }
474
803
  if (initAtasIfMissing) {
475
- instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, ownerAta, owner, mint), createAssociatedTokenAccountIdempotentInstruction(payer, shuttleWalletAta, shuttleEphemeralAta, mint));
804
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, ownerAta, owner, mint));
476
805
  }
477
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump), createEataPermissionIx(ephemeralAta, payer, eataBump), delegateEphemeralAtaIx(payer, ephemeralAta, eataBump, validator), initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId, shuttleBump));
806
+ if (initIfMissing) {
807
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
808
+ }
809
+ if (isPrivate) {
810
+ instructions.push(createEataPermissionIx(ephemeralAta, payer));
811
+ }
812
+ instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, validator));
478
813
  if (amount > 0n) {
479
- instructions.push(depositSplTokensIx(shuttleAta, vault, mint, ownerAta, vaultAta, owner, amount));
814
+ instructions.push(setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator));
815
+ }
816
+ else {
817
+ instructions.push(initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId), delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, validator));
480
818
  }
481
- instructions.push(delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleAtaBump, validator));
482
819
  return instructions;
483
820
  }
484
- async function delegatePrivateSpl(owner, mint, amount, opts) {
821
+ async function delegateSpl(owner, mint, amount, opts) {
822
+ if (opts?.idempotent === false) {
823
+ return buildDelegateSplInstructions(owner, mint, amount, opts);
824
+ }
825
+ return buildIdempotentDelegateSplInstructions(owner, mint, amount, opts);
826
+ }
827
+ async function delegateSplWithPrivateTransfer(owner, mint, amount, opts) {
485
828
  const payer = opts?.payer ?? owner;
486
- const validator = opts?.validator ?? DEFAULT_PRIVATE_VALIDATOR;
829
+ const validator = opts?.validator;
487
830
  const initIfMissing = opts?.initIfMissing ?? true;
488
831
  const initVaultIfMissing = opts?.initVaultIfMissing ?? false;
489
- const permissionFlags = opts?.permissionFlags ?? 0;
490
- const delegatePermission = opts?.delegatePermission ?? false;
832
+ const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
833
+ const initTransferQueueIfMissing = opts?.initTransferQueueIfMissing ?? false;
834
+ const shuttleId = opts?.shuttleId ?? randomShuttleId();
835
+ const minDelayMs = opts?.minDelayMs ?? 0n;
836
+ const maxDelayMs = opts?.maxDelayMs ?? minDelayMs;
837
+ const split = opts?.split ?? 1;
491
838
  const instructions = [];
492
- const [ephemeralAta, eataBump] = deriveEphemeralAta(owner, mint);
493
- const [vault, vaultBump] = deriveVault(mint);
839
+ const [ephemeralAta] = deriveEphemeralAta(owner, mint);
840
+ const [vault] = deriveVault(mint);
841
+ const [vaultEphemeralAta] = deriveEphemeralAta(vault, mint);
494
842
  const vaultAta = deriveVaultAta(mint, vault);
843
+ const [queue] = (0, transferQueue_js_1.deriveTransferQueue)(mint);
495
844
  const ownerAta = getAssociatedTokenAddressSync(mint, owner);
845
+ const [shuttleEphemeralAta] = deriveShuttleEphemeralAta(owner, mint, shuttleId);
846
+ const [shuttleAta] = deriveShuttleAta(shuttleEphemeralAta, mint);
847
+ const shuttleWalletAta = deriveShuttleWalletAta(mint, shuttleEphemeralAta);
848
+ if (initVaultIfMissing) {
849
+ instructions.push(initVaultIx(vault, mint, payer), initVaultAtaIx(payer, vaultAta, vault, mint), delegateEphemeralAtaIx(payer, vaultEphemeralAta, validator));
850
+ }
851
+ if (initTransferQueueIfMissing) {
852
+ instructions.push((0, transferQueue_js_1.initTransferQueueIx)(payer, queue, mint));
853
+ }
854
+ if (initAtasIfMissing) {
855
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, ownerAta, owner, mint));
856
+ }
496
857
  if (initIfMissing) {
497
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump));
858
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
859
+ }
860
+ instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, validator), depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, owner, shuttleWalletAta, mint, shuttleId, amount, minDelayMs, maxDelayMs, split, validator));
861
+ return instructions;
862
+ }
863
+ async function transferSpl(from, to, mint, amount, opts) {
864
+ const payer = opts.payer ?? from;
865
+ const validator = opts.validator;
866
+ const initIfMissing = opts.initIfMissing ?? false;
867
+ const initAtasIfMissing = opts.initAtasIfMissing ?? false;
868
+ const initVaultIfMissing = opts.initVaultIfMissing ?? false;
869
+ const shuttleId = opts.shuttleId ?? randomShuttleId();
870
+ const minDelayMs = opts.privateTransfer?.minDelayMs ?? 0n;
871
+ const maxDelayMs = opts.privateTransfer?.maxDelayMs ?? minDelayMs;
872
+ const split = opts.privateTransfer?.split ?? 1;
873
+ const fromAta = getAssociatedTokenAddressSync(mint, from);
874
+ const toAta = getAssociatedTokenAddressSync(mint, to);
875
+ if (opts.fromBalance === "ephemeral") {
876
+ switch (opts.visibility) {
877
+ case "private":
878
+ if (opts.toBalance === "base") {
879
+ const [queue] = (0, transferQueue_js_1.deriveTransferQueue)(mint);
880
+ const [vault] = deriveVault(mint);
881
+ const vaultAta = deriveVaultAta(mint, vault);
882
+ return [
883
+ (0, transferQueue_js_1.depositAndQueueTransferIx)(queue, vault, mint, fromAta, vaultAta, toAta, from, amount, minDelayMs, maxDelayMs, split),
884
+ ];
885
+ }
886
+ if (opts.toBalance === "ephemeral") {
887
+ return [createTransferInstruction(fromAta, toAta, from, amount)];
888
+ }
889
+ break;
890
+ case "public":
891
+ if (opts.toBalance === "ephemeral") {
892
+ return [createTransferInstruction(fromAta, toAta, from, amount)];
893
+ }
894
+ break;
895
+ }
498
896
  }
897
+ const instructions = [];
499
898
  if (initVaultIfMissing) {
500
- instructions.push(initVaultIx(vault, mint, payer, vaultBump));
501
- instructions.push(initVaultAtaIx(payer, vaultAta, vault, mint));
899
+ const [vault] = deriveVault(mint);
900
+ const [vaultEphemeralAta] = deriveEphemeralAta(vault, mint);
901
+ const vaultAta = deriveVaultAta(mint, vault);
902
+ instructions.push(initVaultIx(vault, mint, payer), initVaultAtaIx(payer, vaultAta, vault, mint), delegateEphemeralAtaIx(payer, vaultEphemeralAta, validator));
502
903
  }
503
- instructions.push(transferToVaultIx(ephemeralAta, vault, mint, ownerAta, vaultAta, owner, amount));
504
- instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, eataBump, validator));
505
- instructions.push(createEataPermissionIx(ephemeralAta, payer, eataBump, permissionFlags));
506
- if (delegatePermission) {
507
- instructions.push(delegateEataPermissionIx(payer, ephemeralAta, eataBump, validator));
904
+ if (opts.fromBalance === "base" && initAtasIfMissing) {
905
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, fromAta, from, mint));
906
+ }
907
+ switch (opts.visibility) {
908
+ case "private":
909
+ if (opts.fromBalance === "base" && opts.toBalance === "base") {
910
+ const [shuttleEphemeralAta] = deriveShuttleEphemeralAta(from, mint, shuttleId);
911
+ const [shuttleAta] = deriveShuttleAta(shuttleEphemeralAta, mint);
912
+ const shuttleWalletAta = deriveShuttleWalletAta(mint, shuttleEphemeralAta);
913
+ return [
914
+ ...instructions,
915
+ depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx(payer, shuttleEphemeralAta, shuttleAta, from, fromAta, to, shuttleWalletAta, mint, shuttleId, amount, minDelayMs, maxDelayMs, split, validator),
916
+ ];
917
+ }
918
+ if (opts.fromBalance === "base" && opts.toBalance === "ephemeral") {
919
+ if (initIfMissing) {
920
+ const [toEphemeralAta] = deriveEphemeralAta(to, mint);
921
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, toAta, to, mint), initEphemeralAtaIx(toEphemeralAta, to, mint, payer), delegateEphemeralAtaIx(payer, toEphemeralAta, validator));
922
+ }
923
+ const [shuttleEphemeralAta] = deriveShuttleEphemeralAta(from, mint, shuttleId);
924
+ const [shuttleAta] = deriveShuttleAta(shuttleEphemeralAta, mint);
925
+ const shuttleWalletAta = deriveShuttleWalletAta(mint, shuttleEphemeralAta);
926
+ return [
927
+ ...instructions,
928
+ setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, from, fromAta, toAta, shuttleWalletAta, mint, shuttleId, amount, validator),
929
+ ];
930
+ }
931
+ break;
932
+ case "public":
933
+ if (opts.fromBalance === "base" && opts.toBalance === "base") {
934
+ return [
935
+ ...instructions,
936
+ createTransferInstruction(fromAta, toAta, from, amount),
937
+ ];
938
+ }
939
+ break;
940
+ }
941
+ throw new Error(`transferSpl route not implemented: visibility=${opts.visibility}, fromBalance=${opts.fromBalance}, toBalance=${opts.toBalance}`);
942
+ }
943
+ async function buildIdempotentWithdrawSplInstructions(owner, mint, amount, opts) {
944
+ const payer = opts?.payer ?? owner;
945
+ const validator = opts?.validator;
946
+ const initIfMissing = opts?.initIfMissing ?? true;
947
+ const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
948
+ const shuttleId = opts?.shuttleId ?? randomShuttleId();
949
+ const instructions = [];
950
+ const [ephemeralAta] = deriveEphemeralAta(owner, mint);
951
+ const ownerAta = getAssociatedTokenAddressSync(mint, owner);
952
+ const [shuttleEphemeralAta] = deriveShuttleEphemeralAta(owner, mint, shuttleId);
953
+ const [shuttleAta] = deriveShuttleAta(shuttleEphemeralAta, mint);
954
+ const shuttleWalletAta = deriveShuttleWalletAta(mint, shuttleEphemeralAta);
955
+ if (initAtasIfMissing) {
956
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, ownerAta, owner, mint));
508
957
  }
958
+ if (initIfMissing) {
959
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
960
+ }
961
+ instructions.push(delegateEphemeralAtaIx(payer, ephemeralAta, validator), withdrawThroughDelegatedShuttleWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator));
509
962
  return instructions;
510
963
  }
511
- function u64le(n) {
512
- if (n < 0n || n > 0xffffffffffffffffn) {
513
- throw new Error("amount out of range for u64");
964
+ async function withdrawSpl(owner, mint, amount, opts) {
965
+ if (opts?.idempotent === false) {
966
+ const instructions = [];
967
+ if (opts?.initAtasIfMissing === true) {
968
+ const payer = opts.payer ?? owner;
969
+ const ownerAta = getAssociatedTokenAddressSync(mint, owner);
970
+ instructions.push(createAssociatedTokenAccountIdempotentInstruction(payer, ownerAta, owner, mint));
971
+ }
972
+ instructions.push(withdrawSplIx(owner, mint, amount));
973
+ return instructions;
514
974
  }
515
- const bytes = new Array(8).fill(0);
516
- let x = n;
517
- for (let i = 0; i < 8; i++) {
518
- bytes[i] = Number(x & 0xffn);
519
- x >>= 8n;
975
+ return buildIdempotentWithdrawSplInstructions(owner, mint, amount, opts);
976
+ }
977
+ function encodeAmountInstructionData(discriminator, amount, ...suffix) {
978
+ const data = Buffer.alloc(1 + 8 + suffix.length);
979
+ data[0] = discriminator;
980
+ data.writeBigUInt64LE(amount, 1);
981
+ if (suffix.length > 0) {
982
+ data.set(suffix, 9);
520
983
  }
521
- return bytes;
984
+ return data;
522
985
  }
523
986
  //# sourceMappingURL=ephemeralAta.js.map