TypeScript ile Tüm Program Hesaplarını Al
Bir program tarafından sahip olunan tüm hesapları döndüren bir RPC yöntemi. Şu anda sayfalama desteklenmemektedir.
getProgramAccounts
talepleri, yanıt süresini iyileştirmek ve yalnızca istenen sonuçları döndürmek için dataSlice
ve/veya filters
parametrelerini içermelidir.
getProgramAccounts RPC Yöntemi
getProgramAccounts
RPC yönteminin aşağıdaki sözdizimi vardır:
programId
:string
- Sorgulamak için programın pubkey'i, base58 kodlu dize olarak sağlanır- (isteğe bağlı)
configOrCommitment
:object
- Aşağıdaki isteğe bağlı alanları içeren yapılandırma parametreleri:- (isteğe bağlı)
commitment
:string
-Durum taahhüdü
- (isteğe bağlı)
encoding
:string
- Hesap verileri için kodlama, ya:base58
,base64
veyajsonParsed
. Not: web3js kullanıcıları bunun yerinegetParsedProgramAccounts
kullanmalıdır - (isteğe bağlı)
dataSlice
:object
- Döndürülen hesap verilerini sınırlamak için:offset
:number
- Hesap verilerine geri dönmeye başlamak için bayt sayısılength
:number
- Döndürülecek hesap veri baytı sayısı
- (isteğe bağlı)
filters
:array
- Aşağıdaki filtre nesnelerini kullanarak sonuçları filtreleyin:memcmp
:object
- Hesap verileri ile bir dizi baytı eşleştirin:offset
:number
- Hesap verilerine karşılaştırmaya başlamak için bayt sayısıbytes
:string
- Eşleşmesi gereken veri, base58 kodlu dize olarak 129 bayt ile sınırlıdır
dataSize
:number
- Hesap verileri uzunluğunu sağlanan veri boyutuyla karşılaştırır
- (isteğe bağlı)
withContext
:boolean
- Sonucu birRpcResponse JSON nesnesi
ile sarmalayın
- (isteğe bağlı)
Yanıt
Varsayılan olarak getProgramAccounts
, aşağıdaki yapıya sahip JSON nesneleri dizisini döndürecektir:
pubkey
:string
- Hesapın pubkey'i, base58 kodlu dize olarakaccount
:object
- Aşağıdaki alt alanlarla bir JSON nesnesi:lamports
:number
, Hesaba atanan lamport sayısıowner
:string
, Hesabın atandığı programın base58 kodlu pubkey'idata
:string
|object
- Hesap ile ilişkili veri, sağlanan kodlama parametresine bağlı olarak ya kodlanmış ikili veri ya da JSON formatındaexecutable
:boolean
, Hesabın bir program içerip içermediği bilgisini gösterirrentEpoch
:number
, Bu hesabın bir sonraki kira borcunu ödeyeceği dönem
Derinlemesine İnceleme
getProgramAccounts
, bir program tarafından sahip olunan tüm hesapları döndüren çok yönlü bir RPC metodudur. getProgramAccounts
'ı birçok yararlı sorgular için kullanabiliriz, örneğin:
- Belirli bir cüzdan için tüm token hesapları
- Belirli bir minta ait tüm token hesapları (yani tüm JUP sahipleri)
- Belirli bir program için tüm özel hesaplar (yani tüm Mango kullanıcıları)
Yararlı olmasına rağmen, getProgramAccounts
mevcut kısıtlamaları nedeniyle sıkça yanlış anlaşılmaktadır.
getProgramAccounts
tarafından desteklenen birçok sorgunun büyük veri setlerini taramak için RPC düğümlerine ihtiyaç duymasıdır. Bu tarama işlemleri hem bellek hem de kaynak açısından yoğun olacaktır.
Sonuç olarak, fazla sık veya çok geniş kapsamlı çağrılar bağlantı zaman aşımına neden olabilir.
Dahası, bu yazının yazıldığı sırada getProgramAccounts
son noktası sayfalama desteklememektedir.
Bir sorgunun sonuçları çok büyükse yanıt kesilecektir.
Bu mevcut kısıtlamaların üstesinden gelmek için getProgramAccounts
, dataSlice
ve filters
seçenekleri olan memcmp
ve dataSize
gibi birkaç yararlı parametre sunmaktadır. Bu parametrelerin kombinasyonlarını sağlayarak sorgularımızın kapsamını yönetilebilir ve öngörülebilir boyutlara düşürebiliriz.
getProgramAccounts
'ın yaygın bir örneği,
SPL-Token Programı ile etkileşimde bulunmayı içerir. Token Programı tarafından sahip olunan tüm hesapları
basic call ile toplamak büyük miktarda veri gerektirecektir. Ancak, parametreler sağlayarak yalnızca kullanmak istediğimiz verileri etkili bir şekilde talep edebiliriz.
filters
getProgramAccounts
ile kullanılacak en yaygın parametre filters
dizisidir. Bu dizi, dataSize
ve memcmp
olmak üzere iki tür filtrenin kabul edilmesini sağlar.
Her iki filtreyi kullanmadan önce, talep ettiğimiz verilerin nasıl düzenlendiği ve seri hale getirildiği konusunda aşina olmalıyız.
dataSize
Token Programı durumunda, token hesaplarının 165 bayt uzunluğunda olduğunu görebiliriz. Özellikle, bir token hesabı sekiz farklı alana sahiptir ve her bir alan belirli sayıda bayt gerektirir. Bu verilerin nasıl düzenlendiğini aşağıdaki illüstrasyonu kullanarak görselleştirebiliriz.
Cüzdan adresimize sahip olan tüm token hesaplarını bulmak istersek, sorgumuzun kapsamını yalnızca 165 bayt uzunluğundaki hesaplarla sınırlamak için filters
dizimize { dataSize: 165 }
ekleyebiliriz. Ancak tek başına bu yeterli olmayacaktır. Ayrıca, cüzdan adresimize sahip hesapları arayan bir filtre eklememiz gerekecektir. Bunu memcmp
filtresi ile başarabiliriz.
memcmp
memcmp
filtresi, ya da "bellek karşılaştırma" filtresi, herhangi bir alanda saklanan verileri karşılaştırmamıza olanak tanır. Özellikle, belirli bir pozisyonda belirli bir dizi bayt ile eşleşen hesaplar için sorgu yapabiliriz. memcmp
iki argüman gerektirir:
offset
: Verileri karşılaştırmaya başlayacağımız pozisyon. Bu pozisyon bayt cinsinden ölçülmekte ve bir tam sayı olarak ifade edilmektedir.bytes
: Hesabın verileri ile eşleşmesi gereken veri. Bu, base-58 kodlu bir dize olarak belirtilmeli ve 129 bayttan daha az olmalıdır.
Önemli Not:
memcmp
'in yalnızcabytes
üzerinde tam eşleşme sağlayan sonuçlar döndüreceğini unutmamak önemlidir.
Şu an itibarıyla, sağladığımız bytes
değerinden daha az veya daha fazla olan değerler için karşılaştırmalar desteklenmemektedir.
Token Programı örneğimizde, sorgumuzu yalnızca cüzdan adresimize sahip token hesaplarını döndürecek şekilde değiştiriyoruz. Bir token hesabına baktığımızda, bir token hesabında saklanan ilk iki alanın her birinin pubkey olduğunu ve her pubkey'in 32 bayt uzunluğunda olduğunu görebiliriz. owner
alanı ikinci alan olduğuna göre, memcmp
'imize 32 baytlık bir offset
ile başlamalıyız. Buradan sonra, owner
alanının cüzdan adresimizle eşleşen hesapları arayacağız.
Bu sorguyu aşağıdaki örnekle başlatabiliriz:
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { clusterApiUrl, Connection } from "@solana/web3.js";
(async () => {
const MY_WALLET_ADDRESS = "FriELggez2Dy3phZeHHAdpcoEXkKQVkv6tx3zDtCVP8T";
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const accounts = await connection.getParsedProgramAccounts(
TOKEN_PROGRAM_ID, // new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
{
filters: [
{
dataSize: 165, // bayt sayısı
},
{
memcmp: {
offset: 32, // bayt sayısı
bytes: MY_WALLET_ADDRESS, // base58 kodlu dize
},
},
],
},
);
console.log(
`Cüzdan ${MY_WALLET_ADDRESS} için ${accounts.length} token hesabı bulundu: `,
);
accounts.forEach((account, i) => {
console.log(
`-- Token Hesap Adresi ${i + 1}: ${account.pubkey.toString()} --`,
);
console.log(`Mint: ${account.account.data["parsed"]["info"]["mint"]}`);
console.log(
`Miktar: ${account.account.data["parsed"]["info"]["tokenAmount"]["uiAmount"]}`,
);
});
})();
Çıktı şu şekilde olmalıdır:
Cüzdan FriELggez2Dy3phZeHHAdpcoEXkKQVkv6tx3zDtCVP8T için 2 token hesabı bulundu:
-- Token Hesap Adresi 0: H12yCcKLHFJFfohkeKiN8v3zgaLnUMwRcnJTyB4igAsy --
Mint: CKKDsBT6KiT4GDKs3e39Ue9tDkhuGUKM3cC2a7pmV9YK
Miktar: 1
-- Token Hesap Adresi 1: Et3bNDxe2wP1yE5ao6mMvUByQUHg8nZTndpJNvfKLdCb --
Mint: BUGuuhPsHpk8YZrL2GctsCtXGneL1gmT5zYb7eMHZDWf
Miktar: 3
dataSlice
İki filtre parametresinin yanı sıra, getProgramAccounts
için en yaygın üçüncü parametre dataSlice
dir. filters
parametresinin aksine, dataSlice
, bir sorgu tarafından döndürülen hesap sayısını azaltmayacaktır. Bunun yerine, dataSlice
, her bir hesap için döndürülecek veri miktarını sınırlayacaktır.
dataSlice
, büyük bir veri kümesi üzerinde sorgular çalıştırdığımızda ancak hesap verilerinin kendisi ile gerçekten ilgilenmediğimiz durumlarda özellikle kullanışlıdır. Bunun bir örneği, belirli bir token mint'i için token hesaplarının sayısını bulmak istememizdir.
import { TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { clusterApiUrl, Connection } from "@solana/web3.js";
(async () => {
const MY_TOKEN_MINT_ADDRESS = "BUGuuhPsHpk8YZrL2GctsCtXGneL1gmT5zYb7eMHZDWf";
const connection = new Connection(clusterApiUrl("devnet"), "confirmed");
const accounts = await connection.getProgramAccounts(
TOKEN_PROGRAM_ID, // new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA")
{
dataSlice: {
offset: 0, // bayt sayısı
length: 0, // bayt sayısı
},
filters: [
{
dataSize: 165, // bayt sayısı
},
{
memcmp: {
offset: 0, // bayt sayısı
bytes: MY_TOKEN_MINT_ADDRESS, // base58 kodlu dize
},
},
],
},
);
console.log(
`Mint ${MY_TOKEN_MINT_ADDRESS} için ${accounts.length} token hesabı bulundu`,
);
console.log(accounts);
})();
Çıktı şu şekilde olmalıdır (dikkat ederseniz, account.data
bölümünde boş `` var):
Mint BUGuuhPsHpk8YZrL2GctsCtXGneL1gmT5zYb7eMHZDWf için 3 token hesabı bulundu
[
{
account: {
data: <Buffer >,
executable: false,
lamports: 2039280,
owner: [PublicKey],
rentEpoch: 228
},
pubkey: PublicKey {
_bn: <BN: a8aca7a3132e74db2ca37bfcd66f4450f4631a5464b62fffbd83c48ef814d8d7>
}
},
{
account: {
data: <Buffer >,
executable: false,
lamports: 2039280,
owner: [PublicKey],
rentEpoch: 228
},
pubkey: PublicKey {
_bn: <BN: ce3b7b906c2ff6c6b62dc4798136ec017611078443918b2fad1cadff3c2e0448>
}
},
{
account: {
data: <Buffer >,
executable: false,
lamports: 2039280,
owner: [PublicKey],
rentEpoch: 228
},
pubkey: PublicKey {
_bn: <BN: d4560e42cb24472b0e1203ff4b0079d6452b19367b701643fa4ac33e0501cb1>
}
}
]
Tüm üç parametreyi (dataSlice
, dataSize
ve memcmp
) birleştirerek sorgumuzun kapsamını sınırlayabilir ve yalnızca ilgilendiğimiz verileri verimli bir şekilde döndürebiliriz.