@magicblock-labs/ephemeral-rollups-kit 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.getEphemeralAtaEncoder = getEphemeralAtaEncoder;
4
37
  exports.getEphemeralAtaDecoder = getEphemeralAtaDecoder;
@@ -10,6 +43,7 @@ exports.getGlobalVaultCodec = getGlobalVaultCodec;
10
43
  exports.decodeGlobalVault = decodeGlobalVault;
11
44
  exports.deriveEphemeralAta = deriveEphemeralAta;
12
45
  exports.deriveVault = deriveVault;
46
+ exports.deriveRentPda = deriveRentPda;
13
47
  exports.deriveVaultAta = deriveVaultAta;
14
48
  exports.deriveShuttleEphemeralAta = deriveShuttleEphemeralAta;
15
49
  exports.deriveShuttleAta = deriveShuttleAta;
@@ -17,10 +51,14 @@ exports.deriveShuttleWalletAta = deriveShuttleWalletAta;
17
51
  exports.initEphemeralAtaIx = initEphemeralAtaIx;
18
52
  exports.initVaultAtaIx = initVaultAtaIx;
19
53
  exports.initVaultIx = initVaultIx;
54
+ exports.initRentPdaIx = initRentPdaIx;
20
55
  exports.transferToVaultIx = transferToVaultIx;
21
56
  exports.delegateIx = delegateIx;
22
57
  exports.initShuttleEphemeralAtaIx = initShuttleEphemeralAtaIx;
23
58
  exports.delegateShuttleEphemeralAtaIx = delegateShuttleEphemeralAtaIx;
59
+ exports.setupAndDelegateShuttleEphemeralAtaWithMergeIx = setupAndDelegateShuttleEphemeralAtaWithMergeIx;
60
+ exports.depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx = depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx;
61
+ exports.withdrawThroughDelegatedShuttleWithMergeIx = withdrawThroughDelegatedShuttleWithMergeIx;
24
62
  exports.mergeShuttleIntoAtaIx = mergeShuttleIntoAtaIx;
25
63
  exports.undelegateAndCloseShuttleEphemeralAtaIx = undelegateAndCloseShuttleEphemeralAtaIx;
26
64
  exports.withdrawSplIx = withdrawSplIx;
@@ -30,15 +68,21 @@ exports.resetEataPermissionIx = resetEataPermissionIx;
30
68
  exports.delegateEataPermissionIx = delegateEataPermissionIx;
31
69
  exports.undelegateEataPermissionIx = undelegateEataPermissionIx;
32
70
  exports.delegateSpl = delegateSpl;
33
- exports.delegateSplIdempotent = delegateSplIdempotent;
34
- exports.delegatePrivateSpl = delegatePrivateSpl;
71
+ exports.delegateSplWithPrivateTransfer = delegateSplWithPrivateTransfer;
72
+ exports.transferSpl = transferSpl;
73
+ exports.withdrawSpl = withdrawSpl;
35
74
  const kit_1 = require("@solana/kit");
36
75
  const system_1 = require("@solana-program/system");
76
+ const blake2b_1 = require("@noble/hashes/blake2b");
77
+ const ed25519_1 = require("@noble/curves/ed25519");
78
+ const nacl = __importStar(require("tweetnacl"));
37
79
  const constants_1 = require("../../constants");
38
80
  const pda_1 = require("../../pda");
39
- const DEFAULT_PRIVATE_VALIDATOR = (0, kit_1.address)("FnE6VJT5QNZdedZPnCoLsARgBwoE6DeJNjBs2H1gySXA");
81
+ const transferQueue_1 = require("./transferQueue");
82
+ const U64_ENCODER = (0, kit_1.getU64Encoder)();
40
83
  const TOKEN_PROGRAM_ADDRESS = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA";
41
84
  const ASSOCIATED_TOKEN_PROGRAM_ADDRESS = "ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL";
85
+ const QUEUED_TRANSFER_FLAG_CREATE_IDEMPOTENT_ATA = 1 << 0;
42
86
  async function getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve = false) {
43
87
  const addressEncoder = (0, kit_1.getAddressEncoder)();
44
88
  const [ata] = await (0, kit_1.getProgramDerivedAddress)({
@@ -51,6 +95,55 @@ async function getAssociatedTokenAddressSync(mint, owner, allowOwnerOffCurve = f
51
95
  });
52
96
  return ata;
53
97
  }
98
+ function createTransferInstruction(source, destination, owner, amount) {
99
+ return {
100
+ accounts: [
101
+ { address: source, role: kit_1.AccountRole.WRITABLE },
102
+ { address: destination, role: kit_1.AccountRole.WRITABLE },
103
+ { address: owner, role: kit_1.AccountRole.READONLY_SIGNER },
104
+ ],
105
+ data: encodeAmountInstructionData(3, amount),
106
+ programAddress: TOKEN_PROGRAM_ADDRESS,
107
+ };
108
+ }
109
+ function encryptEd25519Recipient(plaintext, recipient) {
110
+ const recipientBytes = (0, kit_1.getAddressEncoder)().encode(recipient);
111
+ const recipientX25519 = (0, ed25519_1.edwardsToMontgomeryPub)(new Uint8Array(recipientBytes));
112
+ const ephemeral = nacl.box.keyPair();
113
+ const nonce = (0, blake2b_1.blake2b)(Buffer.concat([
114
+ Buffer.from(ephemeral.publicKey),
115
+ Buffer.from(recipientX25519),
116
+ ]), { dkLen: nacl.box.nonceLength });
117
+ const ciphertext = nacl.box(plaintext, nonce, recipientX25519, ephemeral.secretKey);
118
+ return Buffer.concat([
119
+ Buffer.from(ephemeral.publicKey),
120
+ Buffer.from(ciphertext),
121
+ ]);
122
+ }
123
+ function encodeLengthPrefixedBytes(bytes) {
124
+ if (bytes.length > 0xff) {
125
+ throw new Error("encrypted private transfer payload exceeds u8 length");
126
+ }
127
+ return Buffer.concat([Buffer.from([bytes.length]), Buffer.from(bytes)]);
128
+ }
129
+ function packPrivateTransferSuffix(minDelayMs, maxDelayMs, split, flags = 0) {
130
+ const suffix = Buffer.alloc(8 + 8 + 4 + 1);
131
+ suffix.writeBigUInt64LE(minDelayMs, 0);
132
+ suffix.writeBigUInt64LE(maxDelayMs, 8);
133
+ suffix.writeUInt32LE(split, 16);
134
+ suffix.writeUInt8(flags, 20);
135
+ return suffix;
136
+ }
137
+ function u32leBuffer(value) {
138
+ const out = Buffer.alloc(4);
139
+ out.writeUInt32LE(value, 0);
140
+ return out;
141
+ }
142
+ function u64leBuffer(value) {
143
+ const out = Buffer.alloc(8);
144
+ out.writeBigUInt64LE(value, 0);
145
+ return out;
146
+ }
54
147
  function getEphemeralAtaEncoder() {
55
148
  return (0, kit_1.getStructEncoder)([
56
149
  ["owner", (0, kit_1.getAddressEncoder)()],
@@ -101,6 +194,13 @@ async function deriveVault(mint) {
101
194
  });
102
195
  return [vault, bump];
103
196
  }
197
+ async function deriveRentPda() {
198
+ const [rentPda, bump] = await (0, kit_1.getProgramDerivedAddress)({
199
+ programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
200
+ seeds: [new Uint8Array([114, 101, 110, 116])],
201
+ });
202
+ return [rentPda, bump];
203
+ }
104
204
  async function deriveVaultAta(mint, vault) {
105
205
  return getAssociatedTokenAddressSync(mint, vault, true);
106
206
  }
@@ -137,7 +237,7 @@ async function deriveShuttleAta(shuttleEphemeralAta, mint) {
137
237
  async function deriveShuttleWalletAta(mint, shuttleEphemeralAta) {
138
238
  return getAssociatedTokenAddressSync(mint, shuttleEphemeralAta, true);
139
239
  }
140
- function initEphemeralAtaIx(ephemeralAta, owner, mint, payer, bump) {
240
+ function initEphemeralAtaIx(ephemeralAta, owner, mint, payer) {
141
241
  return {
142
242
  accounts: [
143
243
  { address: ephemeralAta, role: kit_1.AccountRole.WRITABLE },
@@ -146,7 +246,7 @@ function initEphemeralAtaIx(ephemeralAta, owner, mint, payer, bump) {
146
246
  { address: mint, role: kit_1.AccountRole.READONLY },
147
247
  { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
148
248
  ],
149
- data: new Uint8Array([0, bump]),
249
+ data: new Uint8Array([0]),
150
250
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
151
251
  };
152
252
  }
@@ -164,12 +264,13 @@ function initVaultAtaIx(payer, vaultAta, vault, mint) {
164
264
  programAddress: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
165
265
  };
166
266
  }
167
- function initVaultIx(vault, mint, payer, bump, vaultAta) {
267
+ function initVaultIx(vault, mint, payer, vaultEphemeralAta, vaultAta) {
168
268
  return {
169
269
  accounts: [
170
270
  { address: vault, role: kit_1.AccountRole.WRITABLE },
171
271
  { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
172
272
  { address: mint, role: kit_1.AccountRole.READONLY },
273
+ { address: vaultEphemeralAta, role: kit_1.AccountRole.WRITABLE },
173
274
  { address: vaultAta, role: kit_1.AccountRole.WRITABLE },
174
275
  { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
175
276
  {
@@ -178,7 +279,18 @@ function initVaultIx(vault, mint, payer, bump, vaultAta) {
178
279
  },
179
280
  { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
180
281
  ],
181
- data: new Uint8Array([1, bump]),
282
+ data: new Uint8Array([1]),
283
+ programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
284
+ };
285
+ }
286
+ function initRentPdaIx(payer, rentPda) {
287
+ return {
288
+ accounts: [
289
+ { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
290
+ { address: rentPda, role: kit_1.AccountRole.WRITABLE },
291
+ { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
292
+ ],
293
+ data: new Uint8Array([23]),
182
294
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
183
295
  };
184
296
  }
@@ -193,27 +305,25 @@ function transferToVaultIx(ephemeralAta, vault, mint, sourceAta, vaultAta, owner
193
305
  { address: owner, role: kit_1.AccountRole.READONLY_SIGNER },
194
306
  { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
195
307
  ],
196
- data: new Uint8Array([2, ...u64le(amount)]),
308
+ data: encodeAmountInstructionData(2, amount),
197
309
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
198
310
  };
199
311
  }
200
- async function delegateIx(payer, ephemeralAta, bump, validator) {
312
+ async function delegateIx(payer, ephemeralAta, validator) {
201
313
  const delegateBuffer = await (0, pda_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(ephemeralAta, constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
202
314
  const delegationRecord = await (0, pda_1.delegationRecordPdaFromDelegatedAccount)(ephemeralAta);
203
315
  const delegationMetadata = await (0, pda_1.delegationMetadataPdaFromDelegatedAccount)(ephemeralAta);
204
316
  const encoder = (0, kit_1.getAddressEncoder)();
205
317
  let data;
206
318
  if (validator) {
207
- data = new Uint8Array(34);
319
+ data = new Uint8Array(33);
208
320
  data[0] = 4;
209
- data[1] = bump;
210
321
  const validatorBytes = encoder.encode(validator);
211
- data.set(validatorBytes, 2);
322
+ data.set(validatorBytes, 1);
212
323
  }
213
324
  else {
214
- data = new Uint8Array(2);
325
+ data = new Uint8Array(1);
215
326
  data[0] = 4;
216
- data[1] = bump;
217
327
  }
218
328
  return {
219
329
  accounts: [
@@ -230,16 +340,15 @@ async function delegateIx(payer, ephemeralAta, bump, validator) {
230
340
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
231
341
  };
232
342
  }
233
- function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId, bump) {
343
+ function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId) {
234
344
  if (!Number.isInteger(shuttleId) ||
235
345
  shuttleId < 0 ||
236
346
  shuttleId > 4294967295) {
237
347
  throw new Error("shuttleId must fit in u32");
238
348
  }
239
- const data = new Uint8Array(6);
349
+ const data = new Uint8Array(5);
240
350
  data[0] = 11;
241
351
  new DataView(data.buffer).setUint32(1, shuttleId, true);
242
- data[5] = bump;
243
352
  return {
244
353
  accounts: [
245
354
  { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
@@ -259,22 +368,20 @@ function initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shutt
259
368
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
260
369
  };
261
370
  }
262
- async function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, bump, validator) {
371
+ async function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, validator) {
263
372
  const delegateBuffer = await (0, pda_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
264
373
  const delegationRecord = await (0, pda_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta);
265
374
  const delegationMetadata = await (0, pda_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta);
266
375
  const addressEncoder = (0, kit_1.getAddressEncoder)();
267
376
  let data;
268
377
  if (validator) {
269
- data = new Uint8Array(34);
378
+ data = new Uint8Array(33);
270
379
  data[0] = 13;
271
- data[1] = bump;
272
- data.set(addressEncoder.encode(validator), 2);
380
+ data.set(addressEncoder.encode(validator), 1);
273
381
  }
274
382
  else {
275
- data = new Uint8Array(2);
383
+ data = new Uint8Array(1);
276
384
  data[0] = 13;
277
- data[1] = bump;
278
385
  }
279
386
  return {
280
387
  accounts: [
@@ -292,6 +399,172 @@ async function delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttle
292
399
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
293
400
  };
294
401
  }
402
+ async function setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, sourceAta, destinationAta, shuttleWalletAta, mint, shuttleId, amount, validator) {
403
+ if (!Number.isInteger(shuttleId) ||
404
+ shuttleId < 0 ||
405
+ shuttleId > 4294967295) {
406
+ throw new Error("shuttleId must fit in u32");
407
+ }
408
+ const [rentPda] = await deriveRentPda();
409
+ const [vault] = await deriveVault(mint);
410
+ const vaultAta = await deriveVaultAta(mint, vault);
411
+ const delegateBuffer = await (0, pda_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
412
+ const delegationRecord = await (0, pda_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta);
413
+ const delegationMetadata = await (0, pda_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta);
414
+ const addressEncoder = (0, kit_1.getAddressEncoder)();
415
+ const data = new Uint8Array(validator ? 45 : 13);
416
+ const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
417
+ data[0] = 24;
418
+ dataView.setUint32(1, shuttleId, true);
419
+ dataView.setBigUint64(5, amount, true);
420
+ if (validator) {
421
+ data.set(addressEncoder.encode(validator), 13);
422
+ }
423
+ return {
424
+ accounts: [
425
+ { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
426
+ { address: rentPda, role: kit_1.AccountRole.WRITABLE },
427
+ { address: shuttleEphemeralAta, role: kit_1.AccountRole.WRITABLE },
428
+ { address: shuttleAta, role: kit_1.AccountRole.WRITABLE },
429
+ { address: shuttleWalletAta, role: kit_1.AccountRole.WRITABLE },
430
+ { address: owner, role: kit_1.AccountRole.READONLY_SIGNER },
431
+ { address: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
432
+ { address: delegateBuffer, role: kit_1.AccountRole.WRITABLE },
433
+ { address: delegationRecord, role: kit_1.AccountRole.WRITABLE },
434
+ { address: delegationMetadata, role: kit_1.AccountRole.WRITABLE },
435
+ { address: constants_1.DELEGATION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
436
+ {
437
+ address: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
438
+ role: kit_1.AccountRole.READONLY,
439
+ },
440
+ { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
441
+ { address: destinationAta, role: kit_1.AccountRole.WRITABLE },
442
+ { address: mint, role: kit_1.AccountRole.READONLY },
443
+ { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
444
+ { address: vault, role: kit_1.AccountRole.READONLY },
445
+ { address: sourceAta, role: kit_1.AccountRole.WRITABLE },
446
+ { address: vaultAta, role: kit_1.AccountRole.WRITABLE },
447
+ ],
448
+ data,
449
+ programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
450
+ };
451
+ }
452
+ async 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 (amount < 0n) {
459
+ throw new Error("amount must be non-negative");
460
+ }
461
+ if (minDelayMs < 0n || maxDelayMs < 0n) {
462
+ throw new Error("delay values 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
+ if (!Number.isInteger(split) || split <= 0 || split > 4294967295) {
471
+ throw new Error("split must fit in u32 and be positive");
472
+ }
473
+ const [rentPda] = await deriveRentPda();
474
+ const [vault] = await deriveVault(mint);
475
+ const vaultAta = await deriveVaultAta(mint, vault);
476
+ const [queue] = await (0, transferQueue_1.deriveTransferQueue)(mint);
477
+ const delegateBuffer = await (0, pda_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
478
+ const delegationRecord = await (0, pda_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta);
479
+ const delegationMetadata = await (0, pda_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta);
480
+ const addressEncoder = (0, kit_1.getAddressEncoder)();
481
+ const encryptedDestination = encryptEd25519Recipient(new Uint8Array(addressEncoder.encode(destinationOwner)), validator);
482
+ const encryptedSuffix = encryptEd25519Recipient(packPrivateTransferSuffix(minDelayMs, maxDelayMs, split, QUEUED_TRANSFER_FLAG_CREATE_IDEMPOTENT_ATA), validator);
483
+ const data = Buffer.concat([
484
+ Buffer.from([25]),
485
+ u32leBuffer(shuttleId),
486
+ u64leBuffer(amount),
487
+ encodeLengthPrefixedBytes(new Uint8Array(addressEncoder.encode(validator))),
488
+ encodeLengthPrefixedBytes(encryptedDestination),
489
+ encodeLengthPrefixedBytes(encryptedSuffix),
490
+ ]);
491
+ return {
492
+ accounts: [
493
+ { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
494
+ { address: rentPda, role: kit_1.AccountRole.WRITABLE },
495
+ { address: shuttleEphemeralAta, role: kit_1.AccountRole.WRITABLE },
496
+ { address: shuttleAta, role: kit_1.AccountRole.WRITABLE },
497
+ { address: shuttleWalletAta, role: kit_1.AccountRole.WRITABLE },
498
+ { address: owner, role: kit_1.AccountRole.READONLY_SIGNER },
499
+ { address: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
500
+ { address: delegateBuffer, role: kit_1.AccountRole.WRITABLE },
501
+ { address: delegationRecord, role: kit_1.AccountRole.WRITABLE },
502
+ { address: delegationMetadata, role: kit_1.AccountRole.WRITABLE },
503
+ { address: constants_1.DELEGATION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
504
+ {
505
+ address: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
506
+ role: kit_1.AccountRole.READONLY,
507
+ },
508
+ { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
509
+ { address: mint, role: kit_1.AccountRole.READONLY },
510
+ { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
511
+ { address: vault, role: kit_1.AccountRole.READONLY },
512
+ { address: sourceAta, role: kit_1.AccountRole.WRITABLE },
513
+ { address: vaultAta, role: kit_1.AccountRole.WRITABLE },
514
+ { address: queue, role: kit_1.AccountRole.WRITABLE },
515
+ ],
516
+ data,
517
+ programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
518
+ };
519
+ }
520
+ async function withdrawThroughDelegatedShuttleWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator) {
521
+ if (!Number.isInteger(shuttleId) ||
522
+ shuttleId < 0 ||
523
+ shuttleId > 4294967295) {
524
+ throw new Error("shuttleId must fit in u32");
525
+ }
526
+ if (amount < 0n) {
527
+ throw new Error("amount must be non-negative");
528
+ }
529
+ const [rentPda] = await deriveRentPda();
530
+ const delegateBuffer = await (0, pda_1.delegateBufferPdaFromDelegatedAccountAndOwnerProgram)(shuttleAta, constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID);
531
+ const delegationRecord = await (0, pda_1.delegationRecordPdaFromDelegatedAccount)(shuttleAta);
532
+ const delegationMetadata = await (0, pda_1.delegationMetadataPdaFromDelegatedAccount)(shuttleAta);
533
+ const addressEncoder = (0, kit_1.getAddressEncoder)();
534
+ const data = new Uint8Array(validator ? 45 : 13);
535
+ const dataView = new DataView(data.buffer, data.byteOffset, data.byteLength);
536
+ data[0] = 26;
537
+ dataView.setUint32(1, shuttleId, true);
538
+ dataView.setBigUint64(5, amount, true);
539
+ if (validator) {
540
+ data.set(addressEncoder.encode(validator), 13);
541
+ }
542
+ return {
543
+ accounts: [
544
+ { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
545
+ { address: rentPda, role: kit_1.AccountRole.WRITABLE },
546
+ { address: shuttleEphemeralAta, role: kit_1.AccountRole.WRITABLE },
547
+ { address: shuttleAta, role: kit_1.AccountRole.WRITABLE },
548
+ { address: shuttleWalletAta, role: kit_1.AccountRole.WRITABLE },
549
+ { address: owner, role: kit_1.AccountRole.READONLY_SIGNER },
550
+ { address: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
551
+ { address: delegateBuffer, role: kit_1.AccountRole.WRITABLE },
552
+ { address: delegationRecord, role: kit_1.AccountRole.WRITABLE },
553
+ { address: delegationMetadata, role: kit_1.AccountRole.WRITABLE },
554
+ { address: constants_1.DELEGATION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
555
+ {
556
+ address: ASSOCIATED_TOKEN_PROGRAM_ADDRESS,
557
+ role: kit_1.AccountRole.READONLY,
558
+ },
559
+ { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
560
+ { address: ownerAta, role: kit_1.AccountRole.WRITABLE },
561
+ { address: mint, role: kit_1.AccountRole.READONLY },
562
+ { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
563
+ ],
564
+ data,
565
+ programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
566
+ };
567
+ }
295
568
  function mergeShuttleIntoAtaIx(owner, ownerAta, shuttleEphemeralAta, shuttleWalletAta, mint) {
296
569
  return {
297
570
  accounts: [
@@ -306,7 +579,14 @@ function mergeShuttleIntoAtaIx(owner, ownerAta, shuttleEphemeralAta, shuttleWall
306
579
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
307
580
  };
308
581
  }
309
- function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta) {
582
+ function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, escrowIndex) {
583
+ if (escrowIndex !== undefined &&
584
+ (!Number.isInteger(escrowIndex) || escrowIndex < 0 || escrowIndex > 0xff)) {
585
+ throw new Error("escrowIndex must fit in u8");
586
+ }
587
+ const data = escrowIndex === undefined
588
+ ? new Uint8Array([14])
589
+ : new Uint8Array([14, escrowIndex]);
310
590
  return {
311
591
  accounts: [
312
592
  { address: payer, role: kit_1.AccountRole.WRITABLE_SIGNER },
@@ -317,13 +597,13 @@ function undelegateAndCloseShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shu
317
597
  { address: constants_1.MAGIC_CONTEXT_ID, role: kit_1.AccountRole.WRITABLE },
318
598
  { address: constants_1.MAGIC_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
319
599
  ],
320
- data: new Uint8Array([14]),
600
+ data,
321
601
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
322
602
  };
323
603
  }
324
604
  async function withdrawSplIx(owner, mint, amount) {
325
605
  const [ephemeralAta] = await deriveEphemeralAta(owner, mint);
326
- const [vault, vaultBump] = await deriveVault(mint);
606
+ const [vault] = await deriveVault(mint);
327
607
  const vaultAta = await deriveVaultAta(mint, vault);
328
608
  const userDestAta = await getAssociatedTokenAddressSync(mint, owner);
329
609
  return {
@@ -336,7 +616,7 @@ async function withdrawSplIx(owner, mint, amount) {
336
616
  { address: userDestAta, role: kit_1.AccountRole.WRITABLE },
337
617
  { address: TOKEN_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
338
618
  ],
339
- data: new Uint8Array([3, ...u64le(amount), vaultBump]),
619
+ data: encodeAmountInstructionData(3, amount),
340
620
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
341
621
  };
342
622
  }
@@ -370,7 +650,7 @@ async function undelegateIx(owner, mint) {
370
650
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
371
651
  };
372
652
  }
373
- async function createEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
653
+ async function createEataPermissionIx(ephemeralAta, payer, flags = 0) {
374
654
  const permission = await (0, pda_1.permissionPdaFromAccount)(ephemeralAta);
375
655
  return {
376
656
  accounts: [
@@ -380,11 +660,11 @@ async function createEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
380
660
  { address: system_1.SYSTEM_PROGRAM_ADDRESS, role: kit_1.AccountRole.READONLY },
381
661
  { address: constants_1.PERMISSION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
382
662
  ],
383
- data: new Uint8Array([6, bump, flags]),
663
+ data: new Uint8Array([6, flags]),
384
664
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
385
665
  };
386
666
  }
387
- async function resetEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
667
+ async function resetEataPermissionIx(ephemeralAta, payer, flags = 0) {
388
668
  const permission = await (0, pda_1.permissionPdaFromAccount)(ephemeralAta);
389
669
  return {
390
670
  accounts: [
@@ -393,11 +673,11 @@ async function resetEataPermissionIx(ephemeralAta, payer, bump, flags = 0) {
393
673
  { address: payer, role: kit_1.AccountRole.READONLY_SIGNER },
394
674
  { address: constants_1.PERMISSION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
395
675
  ],
396
- data: new Uint8Array([9, bump, flags]),
676
+ data: new Uint8Array([9, flags]),
397
677
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
398
678
  };
399
679
  }
400
- async function delegateEataPermissionIx(payer, ephemeralAta, bump, validator) {
680
+ async function delegateEataPermissionIx(payer, ephemeralAta, validator) {
401
681
  const permission = await (0, pda_1.permissionPdaFromAccount)(ephemeralAta);
402
682
  return {
403
683
  accounts: [
@@ -421,7 +701,7 @@ async function delegateEataPermissionIx(payer, ephemeralAta, bump, validator) {
421
701
  { address: constants_1.DELEGATION_PROGRAM_ID, role: kit_1.AccountRole.READONLY },
422
702
  { address: validator, role: kit_1.AccountRole.READONLY },
423
703
  ],
424
- data: new Uint8Array([7, bump]),
704
+ data: new Uint8Array([7]),
425
705
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
426
706
  };
427
707
  }
@@ -440,98 +720,242 @@ async function undelegateEataPermissionIx(owner, ephemeralAta) {
440
720
  programAddress: constants_1.EPHEMERAL_SPL_TOKEN_PROGRAM_ID,
441
721
  };
442
722
  }
443
- async function delegateSpl(owner, mint, amount, opts) {
723
+ function randomShuttleId() {
724
+ const cryptoObj = globalThis?.crypto;
725
+ if (cryptoObj?.getRandomValues !== undefined) {
726
+ const buf = new Uint32Array(1);
727
+ cryptoObj.getRandomValues(buf);
728
+ return buf[0];
729
+ }
730
+ return Math.floor(Math.random() * 4294967296);
731
+ }
732
+ async function buildDelegateSplInstructions(owner, mint, amount, opts) {
444
733
  const payer = opts?.payer ?? owner;
445
734
  const validator = opts?.validator;
446
735
  const initIfMissing = opts?.initIfMissing ?? true;
447
736
  const initVaultIfMissing = opts?.initVaultIfMissing ?? false;
737
+ const isPrivate = opts?.private ?? false;
448
738
  const instructions = [];
449
- const [ephemeralAta, eataBump] = await deriveEphemeralAta(owner, mint);
450
- const [vault, vaultBump] = await deriveVault(mint);
739
+ const [ephemeralAta] = await deriveEphemeralAta(owner, mint);
740
+ const [vault] = await deriveVault(mint);
741
+ const [vaultEphemeralAta] = await deriveEphemeralAta(vault, mint);
451
742
  const vaultAta = await deriveVaultAta(mint, vault);
452
743
  const ownerAta = await getAssociatedTokenAddressSync(mint, owner);
453
744
  if (initIfMissing) {
454
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump));
745
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
455
746
  }
456
747
  if (initVaultIfMissing) {
457
- instructions.push(initVaultIx(vault, mint, payer, vaultBump, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint));
748
+ instructions.push(initVaultIx(vault, mint, payer, vaultEphemeralAta, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint), await delegateIx(payer, vaultEphemeralAta, validator));
458
749
  }
459
750
  instructions.push(transferToVaultIx(ephemeralAta, vault, mint, ownerAta, vaultAta, owner, amount));
460
- instructions.push(await delegateIx(payer, ephemeralAta, eataBump, validator));
751
+ if (isPrivate) {
752
+ instructions.push(await createEataPermissionIx(ephemeralAta, payer));
753
+ }
754
+ instructions.push(await delegateIx(payer, ephemeralAta, validator));
461
755
  return instructions;
462
756
  }
463
- async function delegateSplIdempotent(owner, mint, amount, opts) {
757
+ async function buildIdempotentDelegateSplInstructions(owner, mint, amount, opts) {
464
758
  const payer = opts?.payer ?? owner;
465
759
  const validator = opts?.validator;
760
+ const initIfMissing = opts?.initIfMissing ?? true;
466
761
  const initVaultIfMissing = opts?.initVaultIfMissing ?? false;
467
762
  const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
468
- const randomShuttleId = () => {
469
- const cryptoObj = globalThis?.crypto;
470
- if (cryptoObj?.getRandomValues !== undefined) {
471
- const buf = new Uint32Array(1);
472
- cryptoObj.getRandomValues(buf);
473
- return buf[0];
474
- }
475
- return Math.floor(Math.random() * 4294967296);
476
- };
763
+ const isPrivate = opts?.private ?? false;
477
764
  const shuttleId = opts?.shuttleId ?? randomShuttleId();
478
765
  const instructions = [];
479
- const [ephemeralAta, eataBump] = await deriveEphemeralAta(owner, mint);
480
- const [vault, vaultBump] = await deriveVault(mint);
766
+ const [ephemeralAta] = await deriveEphemeralAta(owner, mint);
767
+ const [vault] = await deriveVault(mint);
768
+ const [vaultEphemeralAta] = await deriveEphemeralAta(vault, mint);
481
769
  const vaultAta = await deriveVaultAta(mint, vault);
482
770
  const ownerAta = await getAssociatedTokenAddressSync(mint, owner);
483
- const [shuttleEphemeralAta, shuttleBump] = await deriveShuttleEphemeralAta(owner, mint, shuttleId);
484
- const [shuttleAta, shuttleAtaBump] = await deriveShuttleAta(shuttleEphemeralAta, mint);
771
+ const [shuttleEphemeralAta] = await deriveShuttleEphemeralAta(owner, mint, shuttleId);
772
+ const [shuttleAta] = await deriveShuttleAta(shuttleEphemeralAta, mint);
485
773
  const shuttleWalletAta = await deriveShuttleWalletAta(mint, shuttleEphemeralAta);
486
774
  if (initVaultIfMissing) {
487
- instructions.push(initVaultIx(vault, mint, payer, vaultBump, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint));
775
+ instructions.push(initVaultIx(vault, mint, payer, vaultEphemeralAta, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint), await delegateIx(payer, vaultEphemeralAta, validator));
488
776
  }
489
777
  if (initAtasIfMissing) {
490
- instructions.push(initVaultAtaIx(payer, ownerAta, owner, mint), initVaultAtaIx(payer, shuttleWalletAta, shuttleEphemeralAta, mint));
778
+ instructions.push(initVaultAtaIx(payer, ownerAta, owner, mint));
779
+ }
780
+ if (initIfMissing) {
781
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
782
+ }
783
+ if (isPrivate) {
784
+ instructions.push(await createEataPermissionIx(ephemeralAta, payer));
491
785
  }
492
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump), await createEataPermissionIx(ephemeralAta, payer, eataBump), await delegateIx(payer, ephemeralAta, eataBump, validator), initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId, shuttleBump));
786
+ instructions.push(await delegateIx(payer, ephemeralAta, validator));
493
787
  if (amount > 0n) {
494
- instructions.push(transferToVaultIx(shuttleAta, vault, mint, ownerAta, vaultAta, owner, amount));
788
+ instructions.push(await setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator));
789
+ }
790
+ else {
791
+ instructions.push(initShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleWalletAta, owner, mint, shuttleId), await delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, validator));
495
792
  }
496
- instructions.push(await delegateShuttleEphemeralAtaIx(payer, shuttleEphemeralAta, shuttleAta, shuttleAtaBump, validator));
497
793
  return instructions;
498
794
  }
499
- async function delegatePrivateSpl(owner, mint, amount, opts) {
795
+ async function delegateSpl(owner, mint, amount, opts) {
796
+ if (opts?.idempotent === false) {
797
+ return buildDelegateSplInstructions(owner, mint, amount, opts);
798
+ }
799
+ return buildIdempotentDelegateSplInstructions(owner, mint, amount, opts);
800
+ }
801
+ async function delegateSplWithPrivateTransfer(owner, mint, amount, opts) {
500
802
  const payer = opts?.payer ?? owner;
501
- const validator = opts?.validator ?? DEFAULT_PRIVATE_VALIDATOR;
803
+ const validator = opts?.validator;
502
804
  const initIfMissing = opts?.initIfMissing ?? true;
503
805
  const initVaultIfMissing = opts?.initVaultIfMissing ?? false;
504
- const permissionFlags = opts?.permissionFlags ?? 0;
505
- const delegatePermission = opts?.delegatePermission ?? false;
806
+ const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
807
+ const initTransferQueueIfMissing = opts?.initTransferQueueIfMissing ?? false;
808
+ const shuttleId = opts?.shuttleId ?? randomShuttleId();
809
+ const minDelayMs = opts?.minDelayMs ?? 0n;
810
+ const maxDelayMs = opts?.maxDelayMs ?? minDelayMs;
811
+ const split = opts?.split ?? 1;
506
812
  const instructions = [];
507
- const [ephemeralAta, eataBump] = await deriveEphemeralAta(owner, mint);
508
- const [vault, vaultBump] = await deriveVault(mint);
813
+ const [ephemeralAta] = await deriveEphemeralAta(owner, mint);
814
+ const [vault] = await deriveVault(mint);
815
+ const [vaultEphemeralAta] = await deriveEphemeralAta(vault, mint);
509
816
  const vaultAta = await deriveVaultAta(mint, vault);
817
+ const [queue] = await (0, transferQueue_1.deriveTransferQueue)(mint);
510
818
  const ownerAta = await getAssociatedTokenAddressSync(mint, owner);
819
+ const [shuttleEphemeralAta] = await deriveShuttleEphemeralAta(owner, mint, shuttleId);
820
+ const [shuttleAta] = await deriveShuttleAta(shuttleEphemeralAta, mint);
821
+ const shuttleWalletAta = await deriveShuttleWalletAta(mint, shuttleEphemeralAta);
822
+ if (initVaultIfMissing) {
823
+ instructions.push(initVaultIx(vault, mint, payer, vaultEphemeralAta, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint), await delegateIx(payer, vaultEphemeralAta, validator));
824
+ }
825
+ if (initTransferQueueIfMissing) {
826
+ instructions.push((0, transferQueue_1.initTransferQueueIx)(payer, queue, mint));
827
+ }
828
+ if (initAtasIfMissing) {
829
+ instructions.push(initVaultAtaIx(payer, ownerAta, owner, mint));
830
+ }
511
831
  if (initIfMissing) {
512
- instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer, eataBump));
832
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
833
+ }
834
+ instructions.push(await delegateIx(payer, ephemeralAta, validator), await depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, owner, shuttleWalletAta, mint, shuttleId, amount, minDelayMs, maxDelayMs, split, validator));
835
+ return instructions;
836
+ }
837
+ async function transferSpl(from, to, mint, amount, opts) {
838
+ const payer = opts.payer ?? from;
839
+ const validator = opts.validator;
840
+ const initIfMissing = opts.initIfMissing ?? false;
841
+ const initAtasIfMissing = opts.initAtasIfMissing ?? false;
842
+ const initVaultIfMissing = opts.initVaultIfMissing ?? false;
843
+ const shuttleId = opts.shuttleId ?? randomShuttleId();
844
+ const minDelayMs = opts.privateTransfer?.minDelayMs ?? 0n;
845
+ const maxDelayMs = opts.privateTransfer?.maxDelayMs ?? minDelayMs;
846
+ const split = opts.privateTransfer?.split ?? 1;
847
+ const fromAta = await getAssociatedTokenAddressSync(mint, from);
848
+ const toAta = await getAssociatedTokenAddressSync(mint, to);
849
+ if (opts.fromBalance === "ephemeral") {
850
+ switch (opts.visibility) {
851
+ case "private":
852
+ if (opts.toBalance === "base") {
853
+ const [queue] = await (0, transferQueue_1.deriveTransferQueue)(mint);
854
+ const [vault] = await deriveVault(mint);
855
+ const vaultAta = await deriveVaultAta(mint, vault);
856
+ return [
857
+ (0, transferQueue_1.depositAndQueueTransferIx)(queue, vault, mint, fromAta, vaultAta, toAta, from, amount, minDelayMs, maxDelayMs, split),
858
+ ];
859
+ }
860
+ if (opts.toBalance === "ephemeral") {
861
+ return [createTransferInstruction(fromAta, toAta, from, amount)];
862
+ }
863
+ break;
864
+ case "public":
865
+ if (opts.toBalance === "ephemeral") {
866
+ return [createTransferInstruction(fromAta, toAta, from, amount)];
867
+ }
868
+ break;
869
+ }
513
870
  }
871
+ const instructions = [];
514
872
  if (initVaultIfMissing) {
515
- instructions.push(initVaultIx(vault, mint, payer, vaultBump, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint));
873
+ const [vault] = await deriveVault(mint);
874
+ const [vaultEphemeralAta] = await deriveEphemeralAta(vault, mint);
875
+ const vaultAta = await deriveVaultAta(mint, vault);
876
+ instructions.push(initVaultIx(vault, mint, payer, vaultEphemeralAta, vaultAta), initVaultAtaIx(payer, vaultAta, vault, mint), await delegateIx(payer, vaultEphemeralAta, validator));
516
877
  }
517
- instructions.push(transferToVaultIx(ephemeralAta, vault, mint, ownerAta, vaultAta, owner, amount));
518
- instructions.push(await delegateIx(payer, ephemeralAta, eataBump, validator));
519
- instructions.push(await createEataPermissionIx(ephemeralAta, payer, eataBump, permissionFlags));
520
- if (delegatePermission) {
521
- instructions.push(await delegateEataPermissionIx(payer, ephemeralAta, eataBump, validator));
878
+ if (opts.fromBalance === "base" && initAtasIfMissing) {
879
+ instructions.push(initVaultAtaIx(payer, fromAta, from, mint));
880
+ }
881
+ switch (opts.visibility) {
882
+ case "private":
883
+ if (opts.fromBalance === "base" && opts.toBalance === "base") {
884
+ const [shuttleEphemeralAta] = await deriveShuttleEphemeralAta(from, mint, shuttleId);
885
+ const [shuttleAta] = await deriveShuttleAta(shuttleEphemeralAta, mint);
886
+ const shuttleWalletAta = await deriveShuttleWalletAta(mint, shuttleEphemeralAta);
887
+ return [
888
+ ...instructions,
889
+ await depositAndDelegateShuttleEphemeralAtaWithMergeAndPrivateTransferIx(payer, shuttleEphemeralAta, shuttleAta, from, fromAta, to, shuttleWalletAta, mint, shuttleId, amount, minDelayMs, maxDelayMs, split, validator),
890
+ ];
891
+ }
892
+ if (opts.fromBalance === "base" && opts.toBalance === "ephemeral") {
893
+ if (initIfMissing) {
894
+ const [toEphemeralAta] = await deriveEphemeralAta(to, mint);
895
+ instructions.push(initVaultAtaIx(payer, toAta, to, mint), initEphemeralAtaIx(toEphemeralAta, to, mint, payer), await delegateIx(payer, toEphemeralAta, validator));
896
+ }
897
+ const [shuttleEphemeralAta] = await deriveShuttleEphemeralAta(from, mint, shuttleId);
898
+ const [shuttleAta] = await deriveShuttleAta(shuttleEphemeralAta, mint);
899
+ const shuttleWalletAta = await deriveShuttleWalletAta(mint, shuttleEphemeralAta);
900
+ return [
901
+ ...instructions,
902
+ await setupAndDelegateShuttleEphemeralAtaWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, from, fromAta, toAta, shuttleWalletAta, mint, shuttleId, amount, validator),
903
+ ];
904
+ }
905
+ break;
906
+ case "public":
907
+ if (opts.fromBalance === "base" && opts.toBalance === "base") {
908
+ return [
909
+ ...instructions,
910
+ createTransferInstruction(fromAta, toAta, from, amount),
911
+ ];
912
+ }
913
+ break;
914
+ }
915
+ throw new Error(`transferSpl route not implemented: visibility=${opts.visibility}, fromBalance=${opts.fromBalance}, toBalance=${opts.toBalance}`);
916
+ }
917
+ async function buildIdempotentWithdrawSplInstructions(owner, mint, amount, opts) {
918
+ const payer = opts?.payer ?? owner;
919
+ const validator = opts?.validator;
920
+ const initIfMissing = opts?.initIfMissing ?? true;
921
+ const initAtasIfMissing = opts?.initAtasIfMissing ?? false;
922
+ const shuttleId = opts?.shuttleId ?? randomShuttleId();
923
+ const instructions = [];
924
+ const [ephemeralAta] = await deriveEphemeralAta(owner, mint);
925
+ const ownerAta = await getAssociatedTokenAddressSync(mint, owner);
926
+ const [shuttleEphemeralAta] = await deriveShuttleEphemeralAta(owner, mint, shuttleId);
927
+ const [shuttleAta] = await deriveShuttleAta(shuttleEphemeralAta, mint);
928
+ const shuttleWalletAta = await deriveShuttleWalletAta(mint, shuttleEphemeralAta);
929
+ if (initAtasIfMissing) {
930
+ instructions.push(initVaultAtaIx(payer, ownerAta, owner, mint));
522
931
  }
932
+ if (initIfMissing) {
933
+ instructions.push(initEphemeralAtaIx(ephemeralAta, owner, mint, payer));
934
+ }
935
+ instructions.push(await delegateIx(payer, ephemeralAta, validator), await withdrawThroughDelegatedShuttleWithMergeIx(payer, shuttleEphemeralAta, shuttleAta, owner, ownerAta, shuttleWalletAta, mint, shuttleId, amount, validator));
523
936
  return instructions;
524
937
  }
525
- function u64le(n) {
526
- if (n < 0n || n > 0xffffffffffffffffn) {
527
- throw new Error("amount out of range for u64");
938
+ async function withdrawSpl(owner, mint, amount, opts) {
939
+ if (opts?.idempotent === false) {
940
+ const instructions = [];
941
+ if (opts?.initAtasIfMissing === true) {
942
+ const payer = opts.payer ?? owner;
943
+ const ownerAta = await getAssociatedTokenAddressSync(mint, owner);
944
+ instructions.push(initVaultAtaIx(payer, ownerAta, owner, mint));
945
+ }
946
+ instructions.push(await withdrawSplIx(owner, mint, amount));
947
+ return instructions;
528
948
  }
529
- const bytes = new Array(8).fill(0);
530
- let x = n;
531
- for (let i = 0; i < 8; i++) {
532
- bytes[i] = Number(x & 0xffn);
533
- x >>= 8n;
949
+ return buildIdempotentWithdrawSplInstructions(owner, mint, amount, opts);
950
+ }
951
+ function encodeAmountInstructionData(discriminator, amount, ...suffix) {
952
+ const amountBytes = U64_ENCODER.encode(amount);
953
+ const data = new Uint8Array(1 + amountBytes.length + suffix.length);
954
+ data[0] = discriminator;
955
+ data.set(amountBytes, 1);
956
+ if (suffix.length > 0) {
957
+ data.set(suffix, 1 + amountBytes.length);
534
958
  }
535
- return bytes;
959
+ return data;
536
960
  }
537
961
  //# sourceMappingURL=ephemeralAta.js.map