|
8 | 8 | import software.sava.core.programs.Discriminator; |
9 | 9 | import software.sava.core.tx.Instruction; |
10 | 10 |
|
| 11 | +import java.nio.ByteBuffer; |
| 12 | +import java.nio.ByteOrder; |
| 13 | +import java.nio.charset.StandardCharsets; |
11 | 14 | import java.util.Arrays; |
12 | 15 | import java.util.Collection; |
13 | 16 | import java.util.List; |
@@ -1377,7 +1380,175 @@ public static Instruction withdrawExcessLamports(final SolanaAccounts solanaAcco |
1377 | 1380 | signerAccounts |
1378 | 1381 | ); |
1379 | 1382 | } |
| 1383 | + public static Instruction initializeMetadataPointer(final SolanaAccounts solanaAccounts, |
| 1384 | + final PublicKey mintAccount, |
| 1385 | + final PublicKey authority, |
| 1386 | + final PublicKey metadataAccount) { |
| 1387 | + return initializeMetadataPointer(solanaAccounts.invokedToken2022Program(), mintAccount,authority, metadataAccount); |
| 1388 | + } |
| 1389 | + public static Instruction initializeMetadataPointer(final AccountMeta invokedTokenProgram, |
| 1390 | + final PublicKey mintAccount, |
| 1391 | + final PublicKey authority, |
| 1392 | + final PublicKey metadataAccount) { |
| 1393 | + final var keys = List.of(createWrite(mintAccount)); |
| 1394 | + byte[] data = new byte[1+1+32+32]; |
| 1395 | + data[0] = (byte)TokenInstruction.MetadataPointerExtension.ordinal(); |
| 1396 | + data[1] = (byte)0; |
| 1397 | + |
| 1398 | + authority.write(data, 2); |
| 1399 | + |
| 1400 | + metadataAccount.write(data, 34); |
| 1401 | + |
| 1402 | + return createInstruction(invokedTokenProgram, keys, data); |
| 1403 | + } |
| 1404 | + |
| 1405 | + public static Instruction updateMetadataPointer(final SolanaAccounts solanaAccounts, |
| 1406 | + final PublicKey mintAccount, |
| 1407 | + final PublicKey authority, |
| 1408 | + final PublicKey metadataAccount){ |
| 1409 | + return updateMetadataPointer(solanaAccounts.invokedToken2022Program(),mintAccount,authority,metadataAccount); |
| 1410 | + } |
| 1411 | + public static Instruction updateMetadataPointer(final AccountMeta invokedTokenProgram, |
| 1412 | + final PublicKey mintAccount, |
| 1413 | + final PublicKey authority, |
| 1414 | + final PublicKey metadataAccount) { |
| 1415 | + |
| 1416 | + final var keys = List.of( |
| 1417 | + AccountMeta.createWrite(mintAccount), |
| 1418 | + AccountMeta.createReadOnlySigner(authority) |
| 1419 | + ); |
| 1420 | + |
| 1421 | + byte[] data = new byte[1+1+32]; |
| 1422 | + data[0] = (byte)TokenInstruction.MetadataPointerExtension.ordinal(); |
| 1423 | + data[1] = (byte)1; |
| 1424 | + |
| 1425 | + metadataAccount.write(data, 2); |
| 1426 | + |
| 1427 | + return createInstruction( |
| 1428 | + invokedTokenProgram, |
| 1429 | + keys, |
| 1430 | + data |
| 1431 | + ); |
| 1432 | + } |
| 1433 | + |
| 1434 | + public static Instruction initializeTokenMetadataInstruction( |
| 1435 | + final SolanaAccounts solanaAccounts, |
| 1436 | + final PublicKey metadataAccount, |
| 1437 | + final PublicKey updateAuthority, |
| 1438 | + final PublicKey mintAuthority, |
| 1439 | + final PublicKey mintAccount, |
| 1440 | + final String name, |
| 1441 | + final String symbol, |
| 1442 | + final String uri |
| 1443 | + ) { |
| 1444 | + final var keys = List.of( |
| 1445 | + AccountMeta.createWrite(metadataAccount), |
| 1446 | + AccountMeta.createMeta(updateAuthority, false, false), |
| 1447 | + AccountMeta.createMeta(mintAccount, false, false), |
| 1448 | + AccountMeta.createMeta(mintAuthority, false, true) |
| 1449 | + ); |
| 1450 | + |
| 1451 | + byte[] data = buildInitializeTokenMetadataData(name, symbol, uri); |
| 1452 | + |
| 1453 | + return createInstruction( |
| 1454 | + solanaAccounts.invokedToken2022Program(), |
| 1455 | + keys, |
| 1456 | + data |
| 1457 | + ); |
| 1458 | + } |
| 1459 | + |
| 1460 | + private static byte[] buildInitializeTokenMetadataData( |
| 1461 | + String name, |
| 1462 | + String symbol, |
| 1463 | + String uri) { |
1380 | 1464 |
|
| 1465 | + byte[] nameBytes = name.getBytes(StandardCharsets.UTF_8); |
| 1466 | + byte[] symbolBytes = symbol.getBytes(StandardCharsets.UTF_8); |
| 1467 | + byte[] uriBytes = uri.getBytes(StandardCharsets.UTF_8); |
| 1468 | + |
| 1469 | + byte[] discriminator = new byte[]{ |
| 1470 | + (byte) 0xD2, (byte) 0xE1, (byte) 0x1E, (byte) 0xA2, |
| 1471 | + (byte) 0x58, (byte) 0xB8, (byte) 0x4D, (byte) 0x8D |
| 1472 | + }; |
| 1473 | + |
| 1474 | + int dataSize = discriminator.length |
| 1475 | + + Integer.BYTES + nameBytes.length |
| 1476 | + + Integer.BYTES + symbolBytes.length |
| 1477 | + + Integer.BYTES + uriBytes.length; |
| 1478 | + |
| 1479 | + byte[] data = new byte[dataSize]; |
| 1480 | + int offset = 0; |
| 1481 | + |
| 1482 | + System.arraycopy(discriminator, 0, data, offset, discriminator.length); |
| 1483 | + offset += discriminator.length; |
| 1484 | + |
| 1485 | + ByteUtil.putInt32LE(data, offset, nameBytes.length); |
| 1486 | + offset += Integer.BYTES; |
| 1487 | + System.arraycopy(nameBytes, 0, data, offset, nameBytes.length); |
| 1488 | + offset += nameBytes.length; |
| 1489 | + |
| 1490 | + ByteUtil.putInt32LE(data, offset, symbolBytes.length); |
| 1491 | + offset += Integer.BYTES; |
| 1492 | + System.arraycopy(symbolBytes, 0, data, offset, symbolBytes.length); |
| 1493 | + offset += symbolBytes.length; |
| 1494 | + |
| 1495 | + ByteUtil.putInt32LE(data, offset, uriBytes.length); |
| 1496 | + offset += Integer.BYTES; |
| 1497 | + System.arraycopy(uriBytes, 0, data, offset, uriBytes.length); |
| 1498 | + |
| 1499 | + return data; |
| 1500 | + } |
| 1501 | + |
| 1502 | + public static Instruction initializeTransferHook(final SolanaAccounts solanaAccounts, |
| 1503 | + final PublicKey mintAccount, |
| 1504 | + final PublicKey authority, |
| 1505 | + final PublicKey programAccount) { |
| 1506 | + return initializeTransferHook(solanaAccounts.invokedToken2022Program(), mintAccount,authority, programAccount); |
| 1507 | + } |
| 1508 | + public static Instruction initializeTransferHook(final AccountMeta invokedTokenProgram, |
| 1509 | + final PublicKey mintAccount, |
| 1510 | + final PublicKey authority, |
| 1511 | + final PublicKey programAccount) { |
| 1512 | + final var keys = List.of(AccountMeta.createWrite(mintAccount)); |
| 1513 | + byte[] data = new byte[1+1+32+32]; |
| 1514 | + data[0] = (byte)TokenInstruction.TransferHookExtension.ordinal(); |
| 1515 | + data[1] = (byte)0; |
| 1516 | + |
| 1517 | + authority.write(data, 2); |
| 1518 | + programAccount.write(data,34); |
| 1519 | + return createInstruction(invokedTokenProgram, keys, data); |
| 1520 | + } |
| 1521 | + |
| 1522 | + public static Instruction updateTransferHook(final SolanaAccounts solanaAccounts, |
| 1523 | + final PublicKey mintAccount, |
| 1524 | + final PublicKey authority, |
| 1525 | + final PublicKey programAccount){ |
| 1526 | + return updateTransferHook(solanaAccounts.invokedToken2022Program(),mintAccount,authority,programAccount); |
| 1527 | + } |
| 1528 | + public static Instruction updateTransferHook( |
| 1529 | + final AccountMeta invokedTokenProgram, |
| 1530 | + final PublicKey mintAccount, |
| 1531 | + final PublicKey authority, |
| 1532 | + final PublicKey programAccount) { |
| 1533 | + |
| 1534 | + |
| 1535 | + final var keys = List.of( |
| 1536 | + AccountMeta.createWrite(mintAccount), |
| 1537 | + AccountMeta.createReadOnlySigner(authority) |
| 1538 | + ); |
| 1539 | + |
| 1540 | + byte[] data = new byte[1+1+32]; |
| 1541 | + data[0] = (byte)TokenInstruction.TransferHookExtension.ordinal(); |
| 1542 | + data[1] = (byte)1; |
| 1543 | + |
| 1544 | + programAccount.write(data, 2); |
| 1545 | + |
| 1546 | + return createInstruction( |
| 1547 | + invokedTokenProgram, |
| 1548 | + keys, |
| 1549 | + data |
| 1550 | + ); |
| 1551 | + } |
1381 | 1552 | private Token2022Program() { |
1382 | 1553 | } |
1383 | 1554 | } |
0 commit comments