Temporarily host Solana module

This commit is contained in:
2026-06-09 15:15:04 +02:00
parent 9716864f2e
commit b33b35ba1e
11 changed files with 449 additions and 0 deletions
@@ -0,0 +1,52 @@
package com.r35157.libs.solana.valuetypes;
import com.r35157.libs.valuetypes.basic.CurrencyType;
import java.util.UUID;
/**
* Defines well-known currency types used by the Solana integration.
*
* <p>Each enum value wraps a {@link CurrencyType} with a stable identifier and a
* human-readable currency name. These predefined values are intended for common
* currencies that the Solana-related modules need to reference consistently.</p>
*/
public enum WellKnownCurrencyTypes {
/**
* Native Solana currency.
*/
SOLANA(new CurrencyType(
UUID.fromString("019e0116-fce5-792f-a647-fa6da4dffec5"),
"Solana",
"SOL")
),
/**
* Syrup USDC token currency.
*/
SYRUPUSDC(new CurrencyType(
UUID.fromString("019e1d51-0600-7956-8231-f3b7058a91c2"),
"SyrupUSDC",
"SyrupUSDC")
);
/**
* Creates a well-known currency type entry.
*
* @param currencyType the currency type represented by this enum value
*/
WellKnownCurrencyTypes(CurrencyType currencyType) {
this.currencyType = currencyType;
}
/**
* Returns the currency type represented by this enum value.
*
* @return the represented currency type
*/
public CurrencyType getCurrencyType() {
return currencyType;
}
private final CurrencyType currencyType;
}
@@ -0,0 +1,30 @@
package com.r35157.libs.solana;
import java.math.BigDecimal;
/**
* Represents an SPL token holding owned by a Solana address.
*
* <p>The holding describes one SPL token account and the token mint it belongs to.
* The amount is represented both as a UI amount and as the raw on-chain amount,
* together with the number of decimals used by the token mint.</p>
*
* <p>The program id identifies which SPL token program owns the token account,
* for example the original SPL Token Program or the Token-2022 Program.</p>
*
* @param tokenAccount the SPL token account holding the token balance
* @param mintAddress the SPL mint address of the token
* @param uiAmount the human-readable token amount
* @param rawAmount the raw on-chain token amount before decimal conversion
* @param decimals the number of decimals used by the token mint
* @param programId the SPL token program id that owns the token account
*/
public record SPLTokenHolding(
ΩSPLTokenAccountΩ tokenAccount,
ΩSPLMintAddressΩ mintAddress,
ΩAmountΩ uiAmount,
ΩRawAmountΩ rawAmount,
ΩamountDecimalsΩ decimals,
ΩSPLProgramIdΩ programId
) {
}
@@ -0,0 +1,24 @@
package com.r35157.libs.solana;
import java.math.BigDecimal;
/**
* Represents the total supply of an SPL token mint.
*
* <p>The supply is represented both as a UI amount and as the raw on-chain amount,
* together with the number of decimals used by the token mint.</p>
*
* @param mintAddress the SPL mint address whose supply was fetched
* @param uiAmount the human-readable token supply
* @param rawAmount the raw on-chain token supply before decimal conversion
* @param decimals the number of decimals used by the token mint
* @param programId the SPL token program id for the mint
*/
public record SPLTokenSupply(
ΩSPLMintAddressΩ mintAddress,
ΩAmountΩ uiAmount,
ΩRawAmountΩ rawAmount,
ΩamountDecimalsΩ decimals,
ΩSPLProgramIdΩ programId
) {
}
@@ -0,0 +1,24 @@
package com.r35157.libs.solana;
/**
* Represents basic information about a Solana account.
*
* <p>The address identifies the account that was queried. The owner identifies
* the Solana program that owns the account. The account data is represented as
* a Base64 encoded string, matching the encoding returned by the Solana RPC
* account-info response.</p>
*
* <p>For normal wallet/system accounts, the data may be empty. Program-owned
* accounts, token accounts, mint accounts and application-specific state
* accounts may contain encoded account data.</p>
*
* @param address the Solana account address
* @param owner the Solana program id that owns the account
* @param dataBase64 the account data encoded as Base64, or an empty string if the account has no data
*/
public record SolanaAccountInfo(
ΩSolanaAddressΩ address,
ΩSolanaProgramIdΩ owner,
String dataBase64
) {
}
@@ -0,0 +1,146 @@
package com.r35157.libs.solana;
import com.r35157.libs.solana.valuetypes.SolanaProgramDerivedAddress;
import com.r35157.libs.solana.valuetypes.economic.SolanaSPLTokenProgram;
import com.r35157.libs.valuetypes.basic.MoneyAmount;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Provides read-oriented access to the Solana blockchain.
*
* <p>This interface exposes the Solana operations needed by higher-level
* integrations. It can fetch native SOL balances, SPL token holdings, NFT-like
* token holding candidates, account information and program derived addresses.</p>
*
* <p>The interface is intentionally generic and does not contain Raydium-specific
* logic. Higher-level integrations are expected to interpret Solana accounts,
* token holdings and derived addresses according to their own domain rules.</p>
*/
public interface SolanaBlockChain {
/**
* Fetches the native SOL balance for a Solana address.
*
* @param address the Solana address to inspect
* @return the native SOL balance for the address
* @throws IOException if the balance could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching the balance
*/
ΩSolanaAmountΩ getBalanceInSolana(ΩSolanaAddressΩ address) throws IOException, InterruptedException;
/**
* Fetches the native SOL balance for a Solana address in lamports.
*
* <p>Lamports are the smallest unit of native SOL.</p>
*
* @param address the Solana address to inspect
* @return the native SOL balance for the address in lamports
* @throws IOException if the balance could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching the balance
*/
ΩlamportsΩ getBalanceInLamport(ΩSolanaAddressΩ address) throws IOException, InterruptedException;
/**
* Fetches SPL token holdings owned by a Solana address for a specific token program.
*
* <p>The supplied token program decides which token accounts are inspected. For example,
* callers may query the original SPL Token Program or the Token-2022 Program depending
* on which token accounts they need to discover.</p>
*
* @param ownerAddress the Solana owner address whose token holdings should be inspected
* @param splProgramId the SPL token program to query
* @return a map of SPL mint addresses to token holding information
* @throws IOException if the token holdings could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching token holdings
*/
Map<ΩSPLMintAddressΩ, SPLTokenHolding> getSPLTokenHoldings(
ΩSolanaAddressΩ ownerAddress,
SolanaSPLTokenProgram splProgramId
) throws IOException, InterruptedException;
/**
* Fetches NFT-like token mint address candidates owned by a Solana address for a specific token program.
*
* <p>This method identifies token holdings that look like NFTs within the supplied token
* program. A returned address is only a candidate. Higher-level integrations are responsible
* for deciding whether the returned address has domain-specific meaning.</p>
*
* // TODO This method currently identifies candidates from the owner's token holdings only.
* // A token with zero decimals and an owner balance of one is not guaranteed to be a real NFT,
* // because the mint's total supply may still be greater than one. A future implementation
* // should verify the mint supply, for example by using Solana getTokenSupply, before treating
* // the result as a confirmed NFT.
*
* @param ownerAddress the Solana owner address whose NFT-like holdings should be inspected
* @param splProgram the SPL token program to query
* @return the NFT-like Solana mint address candidates owned by the address
* @throws IOException if the NFT candidate addresses could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching NFT candidate addresses
*/
Set<ΩSolanaNFTAddressΩ> getSolanaNFTCandidateAddresses(
ΩSolanaAddressΩ ownerAddress,
SolanaSPLTokenProgram splProgram
) throws IOException, InterruptedException;
/**
* Finds a Solana program derived address for a program id and a set of seeds.
*
* <p>The seeds describe the logical inputs used to derive the address. The implementation
* is responsible for converting each seed into the byte representation required by Solana.</p>
*
* @param programId the Solana program id used to derive the address
* @param seeds the seeds used when deriving the program address
* @return the derived Solana address together with its bump value
*/
SolanaProgramDerivedAddress findProgramAddress(
ΩSolanaProgramIdΩ programId,
List<SolanaProgramAddressSeed> seeds
);
/**
* Fetches account information for a Solana account address.
*
* <p>If the account does not exist, this method returns {@code null}. If the account exists,
* the returned value contains the account address, the owning Solana program id and the
* account data encoded as Base64.</p>
*
* @param accountAddress the Solana account address to inspect
* @return account information, or {@code null} if the account does not exist
* @throws IOException if the account information could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching account information
*/
SolanaAccountInfo getAccountInfo(ΩSolanaAddressΩ accountAddress)
throws IOException, InterruptedException;
/**
* Encodes a raw 32-byte Solana address into its textual Solana address representation.
*
* <p>This method is intended for callers that have obtained raw Solana address bytes from
* account data and need the normal string representation used elsewhere in the API.</p>
*
* @param addressBytes the raw 32-byte Solana address
* @return the encoded Solana address
* @throws IllegalArgumentException if the supplied byte array is not a valid Solana address length
*/
ΩSolanaAddressΩ encodeSolanaAddress(byte[] addressBytes);
/**
* Fetches the total supply of an SPL token mint for a specific token program.
*
* <p>The supplied token program identifies which SPL token program owns the mint,
* for example the original SPL Token Program or the Token-2022 Program.</p>
*
* @param mintAddress the SPL mint address whose supply should be fetched
* @param splProgram the SPL token program to query
* @return the SPL token supply for the mint
* @throws IOException if the token supply could not be fetched or parsed
* @throws InterruptedException if the calling thread is interrupted while fetching token supply
*/
SPLTokenSupply getSPLTokenSupply(
ΩSPLMintAddressΩ mintAddress,
SolanaSPLTokenProgram splProgram
) throws IOException, InterruptedException;
}
@@ -0,0 +1,19 @@
package com.r35157.libs.solana;
/**
* Contains Solana-related constants used by the Solana integration.
*
* <p>This class is intended for shared constants that are part of the public
* Solana API surface or are useful across Solana-related modules.</p>
*/
public class SolanaConstants {
/**
* The default Solana JSON-RPC endpoint used by the integration.
*/
public static final String RPC_URL = "https://api.mainnet.solana.com";
/**
* The SPL mint address for Syrup USDC on Solana.
*/
public static final String SPL_TOKEN_SYRUPUSDC = "AvZZF1YaZDziPY2RCK4oJrRVrbN3mTD9NL24hPeaZeUj";
}
@@ -0,0 +1,51 @@
package com.r35157.libs.solana;
/**
* Represents a seed used when deriving a Solana program derived address.
*
* <p>A seed has a kind and a textual value. The kind tells the Solana
* implementation how the value should be converted to bytes before it is used
* in program address derivation.</p>
*
* <p>This keeps callers from having to perform encoding or decoding themselves.
* For example, a caller can provide a UTF-8 seed or a Solana address seed, and
* the implementation decides how each seed is converted to the byte format
* required by Solana.</p>
*
* @param kind the kind of seed
* @param value the textual seed value
*/
public record SolanaProgramAddressSeed(
SolanaProgramAddressSeedKind kind,
String value
) {
/**
* Creates a UTF-8 seed.
*
* @param value the text value to encode as UTF-8
* @return a program address seed representing the supplied UTF-8 text
*/
public static SolanaProgramAddressSeed utf8(String value) {
return new SolanaProgramAddressSeed(
SolanaProgramAddressSeedKind.UTF8,
value
);
}
/**
* Creates a Solana address seed.
*
* <p>The supplied address is represented textually here. The implementation
* deriving the program address is responsible for decoding the address into
* its raw Solana address bytes.</p>
*
* @param address the Solana address to use as a seed
* @return a program address seed representing the supplied Solana address
*/
public static SolanaProgramAddressSeed solanaAddress(ΩSolanaAddressΩ address) {
return new SolanaProgramAddressSeed(
SolanaProgramAddressSeedKind.SOLANA_ADDRESS,
address
);
}
}
@@ -0,0 +1,21 @@
package com.r35157.libs.solana;
/**
* Defines how a Solana program address seed should be converted to bytes.
*
* <p>Program derived addresses are calculated from byte seeds. This enum allows
* callers to describe the meaning of a seed without doing the byte conversion
* themselves.</p>
*/
public enum SolanaProgramAddressSeedKind {
/**
* A seed that should be encoded as UTF-8 text.
*/
UTF8,
/**
* A seed that represents a Solana address and should be decoded from its
* textual Solana address representation to raw address bytes.
*/
SOLANA_ADDRESS
}
@@ -0,0 +1,17 @@
package com.r35157.libs.solana.valuetypes;
/**
* Represents a Solana program derived address and its bump value.
*
* <p>A program derived address is a Solana address generated deterministically
* from a program id and a set of seeds. The bump value is the extra seed value
* used to find a valid program derived address for those inputs.</p>
*
* @param address the derived Solana address
* @param bump the bump value used when deriving the address
*/
public record SolanaProgramDerivedAddress(
ΩSolanaAddressΩ address,
int bump
) {
}
@@ -0,0 +1,21 @@
package com.r35157.libs.solana.valuetypes.economic;
import com.r35157.libs.valuetypes.basic.CurrencyType;
/**
* Represents an SPL token known to the Solana integration.
*
* <p>The currency type describes the economic identity of the token, while the
* mint address identifies the SPL token mint on Solana. The token address is the
* Solana address associated with the token in this model.</p>
*
* @param currencyType the currency type represented by this SPL token
* @param mintAddress the SPL mint address of the token
* @param tokenAddress the Solana address associated with the token
*/
public record SolanaSPLToken (
CurrencyType currencyType,
ΩSPLMintAddressΩ mintAddress,
ΩSolanaAddressΩ tokenAddress
) {
}
@@ -0,0 +1,44 @@
package com.r35157.libs.solana.valuetypes.economic;
/**
* Represents a Solana SPL token program supported by this integration.
*
* <p>Solana has more than one token program. The original SPL Token Program is
* used by many existing tokens, while the Token-2022 Program supports newer token
* functionality and extensions.</p>
*
* <p>The program address is used when querying token accounts owned by a wallet,
* for example when discovering SPL token holdings or NFT-like token holdings
* under a specific token program.</p>
*/
public enum SolanaSPLTokenProgram {
/**
* The original Solana SPL Token Program.
*/
SPL_TOKEN_PROGRAM("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"),
/**
* The Solana Token-2022 Program.
*/
TOKEN_2022_PROGRAM("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
/**
* Creates a Solana SPL token program entry.
*
* @param address the Solana program address for the token program
*/
SolanaSPLTokenProgram(ΩSPLProgramIdΩ address) {
this.address = address;
}
/**
* Returns the Solana program address for this token program.
*
* @return the SPL token program address
*/
public ΩSPLProgramIdΩ getAddress() {
return address;
}
private final ΩSPLProgramIdΩ address;
}