AssemblyScript API'si
Reading time: 17 min
Not: Eğer graph-cli
/graph-ts
sürüm 0.22.0
'den önce bir subgraph oluşturduysanız, eski bir AssemblyScript sürümünü kullanıyorsunuz demektir. gözden geçirmeniz önerilir.
Subgraph eşlemeleri yazarken kullanılabilecek yerleşik API'leri öğrenin. Hazır olarak sunulan iki tür API mevcuttur:
ile uyumlu olduğu sürece diğer kütüphaneleri de bağımlılık olarak ekleyebilirsiniz.
Dil eşlemeleri AssemblyScript ile yazıldığından, dil ve standart kütüphane özelliklerini gözden geçirmek faydalı olacaktır.
@graphprotocol/graph-ts
kütüphanesi aşağıdaki API'leri sağlar:
- Ethereum akıllı sözleşmeleri, olaylar, bloklar, işlemler ve Ethereum değerleriyle çalışmak için bir
ethereum
API'si. - Varlıkları Graph Düğümü deposundan yüklemek ve depoya kaydetmek için bir
store
API'si. - Graph Düğümü çıktısına ve Graph Gezgini'ne mesaj kaydetmek için bir
log
API'si. - IPFS'ten dosyaları yüklemek için bir
ipfs
API'si. - JSON verilerini ayrıştırmak için bir
json
API'si. - Kriptografik fonksiyonları kullanmak için bir
crypto
API'si. - Ethereum, JSON, GraphQL ve AssemblyScript gibi farklı tip sistemler arası çeviri yapmak için düşük seviyeli yazılımlar.
Subgraph manifestosundaki apiVersion
, bir subgraph için Graph Düğümü tarafından çalıştırılan eşleme (mapping) API'sinin sürümünü belirtir.
AssemblyScript'e yerleşik olan temel türler hakkında dökümantasyona ulaşabilirsiniz.
Aşağıdaki ek türler @graphprotocol/graph-ts
tarafından sağlanmaktadır.
import { ByteArray } from '@graphprotocol/graph-ts'
ByteArray
, bir u8
dizisini temsil eder.
Oluşturma
fromI32(x: i32): ByteArray
-x
değerini baytlara ayrıştırır.fromHexString(hex: string): ByteArray
- Girdi uzunluğu çift sayı olmalıdır.0x
ile başlatmak isteğe bağlıdır.
Tür Dönüşümleri
toHexString(): string
- On altılık tabanda bir dizeye (hex string) dönüştürür ve0x
öneki ekler.toString(): string
- Baytları UTF-8 dizesi olarak yorumlar.toBase58(): string
- Baytları base58 dizesine kodlar.toU32(): u32
- Baytları little-endian biru32
olarak yorumlar. Aşım durumunda hata verir.toI32(): i32
- Bayt dizisini little-endian biri32
olarak yorumlar. Aşım durumunda hata verir.
Operatörler
equals(y: ByteArray): bool
–x == y
olarak yazılabilir.concat(other: ByteArray): ByteArray
-this
dizisinin sonunaother
dizisini ekleyerek yeni birByteArray
döner.concatI32(other: i32): ByteArray
-this
dizisinin sonunaother
'ın bayt temsili ekleyerek yeni birByteArray
döner.
import { BigDecimal } from '@graphprotocol/graph-ts'
BigDecimal
, ondalık sayıları istenildiği kadar doğrulukta temsil etmek için kullanılır.
Not: BigDecimal
, saklanır ve bu format 34 ondalık basamağa kadar destek sunar. Bu durum, BigDecimal
'i, 34 basamağı aşabilen sabit noktalı türleri temsil etmek için (örneğin Solidity'deki gibi) uygun olmaktan çıkarır.
Oluşturma
constructor(bigInt: BigInt)
– BirBigInt
'ten birBigDecimal
oluşturur.static fromString(s: string): BigDecimal
– Ondalık bir dizeyi ayrıştırır.
Tür Dönüşümleri
toString(): string
– Ondalık bir dize olarak yazdırır.
Math
plus(y: BigDecimal): BigDecimal
–x + y
şeklinde yazılabilir.minus(y: BigDecimal): BigDecimal
–x - y
şeklinde yazılabilir.times(y: BigDecimal): BigDecimal
–x * y
şeklinde yazılabilir.div(y: BigDecimal): BigDecimal
–x / y
şeklinde yazılabilir.equals(y: BigDecimal): bool
–x == y
şeklinde yazılabilir.notEqual(y: BigDecimal): bool
–x != y
şeklinde yazılabilir.lt(y: BigDecimal): bool
–x < y
şeklinde yazılabilir.le(y: BigDecimal): bool
–x <= y
şeklinde yazılabilir.gt(y: BigDecimal): bool
–x > y
şeklinde yazılabilir.ge(y: BigDecimal): bool
–x >= y
şeklinde yazılabilir.neg(): BigDecimal
--x
şeklinde yazılabilir.
import { BigInt } from '@graphprotocol/graph-ts'
BigInt
, büyük tam sayıları temsil etmek için kullanılır. Buna, Ethereum'daki uint32
ile uint256
ve int64
ile int256
türlerindeki değerler dahildir. uint32
'nin altındaki her şey, örneğin int32
, uint24
veya int8
, i32
olarak temsil edilir.
BigInt
sınıfı aşağıdaki API'ye sahiptir:
Oluşturma
-
BigInt.fromI32(x: i32): BigInt
– Biri32
'den birBigInt
oluşturur. -
BigInt.fromString(s: string): BigInt
– Bir dizeden birBigInt
oluşturur. -
BigInt.fromUnsignedBytes(x: Bytes): BigInt
–bytes
'i işaretsiz, little-endian bir tamsayı olarak yorumlar. Girdiniz big-endian ise önce.reverse()
metodunu kullanın. -
BigInt.fromSignedBytes(x: Bytes): BigInt
–bytes
'i işaretli, little-endian bir tamsayı olarak yorumlar. Girdiniz big-endian ise önce.reverse()
metodunu kullanın.Tür Dönüşümleri
-
x.toHex(): dize
–BigInt
'i on altılık tabanda bir karakter dizesine dönüştürür. -
x.toString(): dize
–BigInt
'i ondalık tabanda bir dizeye dönüştürür. -
x.toI32(): i32
–BigInt
'i biri32
olarak döndürür, değeri32
'ye sığmazsa hata verir. İlk olarakx.isI32()
kontrolünü yapmanız önerilir. -
x.toBigDecimal(): BigDecimal
– Kesirli kısmı olmayan bir ondalık sayıya dönüştürür.
Math
x.plus(y: BigInt): BigInt
–x + y
şeklinde yazılabilir.x.minus(y: BigInt): BigInt
–x - y
şeklinde yazılabilir.x.times(y: BigInt): BigInt
–x * y
şeklinde yazılabilir.x.div(y: BigInt): BigInt
–x / y
şeklinde yazılabilir.x.mod(y: BigInt): BigInt
–x % y
şeklinde yazılabilir.x.equals(y: BigInt): bool
–x == y
şeklinde yazılabilir.x.notEqual(y: BigInt): bool
–x != y
şeklinde yazılabilir.x.lt(y: BigInt): bool
–x < y
şeklinde yazılabilir.x.le(y: BigInt): bool
–x <= y
şeklinde yazılabilir.x.gt(y: BigInt): bool
–x > y
şeklinde yazılabilir.x.ge(y: BigInt): bool
–x >= y
şeklinde yazılabilir.x.neg(): BigInt
–-x
şeklinde yazılabilir.x.divDecimal(y: BigDecimal): BigDecimal
– Ondalık bir sayı ile böler ve ondalık bir sonuç döndürür.x.isZero(): bool
– Sayının sıfır olup olmadığını kontrol etmek için kullanışlı bir metot.x.isI32(): bool
– Sayının biri32
'ye sığıp sığmadığını kontrol eder.x.abs(): BigInt
– Mutlak değer.x.pow(exp: u8): BigInt
– Üs alma işlemi.bitOr(x: BigInt, y: BigInt): BigInt
–x | y
olarak yazılabilir.bitAnd(x: BigInt, y: BigInt): BigInt
–x & y
şeklinde yazılabilir.leftShift(x: BigInt, bits: u8): BigInt
–x << y
şeklinde yazılabilir.rightShift(x: BigInt, bits: u8): BigInt
–x >> y
şeklinde yazılabilir.
import { TypedMap } from '@graphprotocol/graph-ts'
TypedMap
, anahtar-değer çiftlerini saklamak için kullanılabilir. inceleyebilirsiniz.
TypedMap
sınıfının API'si aşağıdaki gibidir:
new TypedMap<K, V>()
–K
türünde anahtarlar veV
türünde değerler içeren boş bir eşlem oluştururmap.set(key: K, value: V): void
–key
anahtarının değerinivalue
olarak ayarlarmap.getEntry(key: K): TypedMapEntry<K, V> | null
–key
için anahtar-değer çiftini döndürür, eğerkey
eşlemde mevcut değilsenull
dönermap.get(key: K): V | null
–key
için değeri döndürür, eğerkey
eşlemde mevcut değilsenull
dönermap.isSet(key: K): bool
– Eğerkey
eşlemde mevcutsatrue
, değilsefalse
döner
import { Bytes } from '@graphprotocol/graph-ts'
Bytes
, keyfi uzunluktaki bayt dizilerini temsil etmek için kullanılır. Buna Ethereum'daki bytes
, bytes32
gibi türler dahildir.
Bytes
sınıfı, AssemblyScript'in sınıfını genişletir ve Uint8Array
'in tüm işlevselliğini destekler. Buna ek olarak, aşağıdaki yeni metotlara sahiptir:
Oluşturma
fromHexString(hex: string): Bytes
–hex
dizesini, on altı tabanında çift sayıda basamaktan oluşması koşuluyla birByteArray
'e dönüştürür.hex
dizesi isteğe bağlı olarak0x
ile başlayabilirfromI32(i: i32): Bytes
–i
değerini bir bayt dizisine dönüştürür
Tür Dönüşümleri
b.toHex()
– dizideki baytları temsil eden on altı tabanında bir dize döndürürb.toString()
– dizideki baytları Unicode karakterlerinden oluşan bir dizeye dönüştürürb.toBase58()
– bir Ethereum Bytes değerini base58 kodlamasına (IPFS hash'leri için kullanılır) dönüştürür
Operatörler
b.concat(other: Bytes): Bytes
–this
dizisinin sonunaother
dizisini ekleyerek yeni birBytes
döndürürb.concatI32(other: i32): ByteArray
–this
dizisinin sonrasınaother
'ın bayt temsilini eklenerek yeni birBytes
döndürür
import { Address } from '@graphprotocol/graph-ts'
Address
, Ethereum address
değerlerini temsil etmek için Bytes
sınıfını genişletir.
Bytes
API'sine ek olarak aşağıdaki metotları sağlar:
Address.fromString(s: dize): Address
– On altılık tabanda bir dizeden birAddress
oluştururAddress.fromBytes(b: Bytes): Address
– Tam olarak 20 bayt uzunluğunda olması gerekenb
dizisinden birAddress
oluşturur. Daha az veya daha fazla bayt içeren bir değer geçildiğinde hata verir
import { store } from '@graphprotocol/graph-ts'
store
API'si, varlıkları Graph Düğümü deposundan yüklemeye, depoya kaydetmeye ve depodan kaldırmaya olanak tanır.
Depoya yazılan varlıklar, subgraph'in GraphQL şemasında tanımlanan @entity
türleriyle bire bir eşleşir. Bu varlıklarla çalışmayı kolaylaştırmak için tarafından sağlanan graph codegen
komutu varlık sınıfları oluşturur. Varlık sınıfları, şemadaki alanlar için özellik alıcıları ve ayarlayıcılarının yanı sıra bu varlıkları yüklemek ve kaydetmek için metotlar içeren, yerleşik Entity
türünün alt sınıflarıdır.
Aşağıdaki, Ethereum olaylarından varlıklar oluşturmak için yaygın bir modeldir.
// ERC20 ABI'dan oluşturulan Transfer olay sınıfını içe aktarınimport { Transfer as TransferEvent } from '../generated/ERC20/ERC20'// GraphQL şemasından oluşturulan Transfer varlık türünü içe aktarınimport { Transfer } from '../generated/schema'// Transfer olayı işleyicisiexport function handleTransfer(event: TransferEvent): void {// İşlem hash'ını olay kimliği olarak kullanarak bir Transfer varlığı oluşturunlet id = event.transaction.hashlet transfer = new Transfer(id)// Olay parametrelerini kullanarak varlığın özelliklerini ayarlayıntransfer.from = event.params.fromtransfer.to = event.params.totransfer.amount = event.params.amount// Varlığı depoya kaydedintransfer.save()}
Zincir işlenirken bir Transfer
olayıyla karşılaşıldığında, oluşturulan Transfer
türü (burada varlık türüyle adlandırma çakışmasını önlemek için TransferEvent
olarak adlandırılmıştır) kullanılarak handleTransfer
olay işleyicisine aktarılır. Bu tür, olayın ana işlemi ve parametreleri gibi verilere erişim sağlar.
Her varlık, diğer varlıklarla çakışmayı önlemek için benzersiz bir ID'ye sahip olmalıdır. Genellikle olay parametrelerinin içinde bu iş için kullanılabilecek benzersiz bir tanımlayıcı bulunur.
Not: ID olarak işlem hash'ini kullanmak, aynı işlemdeki diğer olayların bu hash'i ID olarak kullanarak varlık oluşturmadığını varsayar.
Bir varlık mevcutsa aiağıdaki kod kullanılarak depodan yüklenebilir:
let id = event.transaction.hash // veya kimlik(ID) nasıl oluşturulmuşsalet transfer = Transfer.load(id)if (transfer == null) {transfer = new Transfer(id)}// Transfer varlığı önceki gibi kullanılır
Varlık henüz depoda mevcut olmayabileceğinden, load
yöntemi Transfer | null
türünde bir değer döndürür. Değeri kullanmadan önce null
olup olmadığını kontrol etmek gerekebilir.
Not: Varlıkları yüklemek, yalnızca, eşlemede yapılan değişikliklerin bir varlığın önceki verilerine bağlı olması durumunda gereklidir. Mevcut varlıkları güncellemenin iki yolunu görmek için bir sonraki bölüme bakın.
graph-node
v0.31.0, @graphprotocol/graph-ts
v0.30.0 ve @graphprotocol/graph-cli
v0.49.0 itibarıyla loadInBlock
metodu tüm varlık türlerinde kullanılabilir hale gelmiştir.
Store API'si mevcut blokta oluşturulan veya güncellenen varlıkların alınmasına olanak tanır. Bunun tipik bir örneği, bir işleyicinin zincir-üzeri bir olaydan bir işlem oluşturması ve sonraki bir işleyicinin, bu işlem mevcutsa ona erişmek istemesidir.
- Eğer işlem mevcut değilse subgraph sırf varlığın mevcut olmadığını öğrenmek için veritabanına başvurmak zorunda kalacaktır. Ancak, subgraph yazarı varlığın aynı blokta oluşturulmuş olması gerektiğini zaten biliyorsa,
loadInBlock
kullanmak bu veritabanı sorgusunu ortadan kaldırır. - Bazı subgraph'lerde bu başarısız aramalar endeksleme süresine önemli ölçüde etki edebilir.
let id = event.transaction.hash // veya ID nasıl oluşturulurmuşsalet transfer = Transfer.loadInBlock(id)if (transfer == null) {transfer = new Transfer(id)}// Transfer varlığını daha önce olduğu gibi kullanın
Not: Belirtilen blokta bir varlık oluşturulmadıysa, depoda verilen ID'ye sahip bir varlık olsa bile loadInBlock
yöntemi null
döndürecektir.
graph-node
v0.31.0, @graphprotocol/graph-ts
v0.31.0 ve @graphprotocol/graph-cli
v0.51.0 itibarıyla, loadRelated
metodu kullanılabilir hale gelmiştir.
Bu, türetilmiş varlık alanlarının bir olay işleyicisi içinden yüklenmesini sağlar. Örneğin, aşağıdaki şema göz önüne alındığında:
type Token @entity {id: ID!holder: Holder!color: String}type Holder @entity {id: ID!tokens: [Token!]! @derivedFrom(field: "holder")}
Aşağıdaki kod, Holder
varlığının türetildiği Token
varlığını yükleyecektir:
let holder = Holder.load('test-id')// Belirli bir sahiple ilişkili Token unsurlarını yükleyinlet tokens = holder.tokens.load()
Mevcut bir varlığı güncellemenin iki yolu vardır:
Transfer.load(id)
ya da benzeri bir metotla varlığı yükleyin, varlık üzerindeki özellikleri ayarlayın ve ardından.save()
ile tekrar depoya kaydedin.new Transfer(id)
ya da benzeri bir metotla varlığı oluşturun, varlık üzerindeki özellikleri ayarlayın ve ardından.save()
ile depoya kaydedin. Eğer varlık zaten mevcutsa, yapılan değişiklikler mevcut varlıkla birleştirilir.
Oluşturulan özellik ayarlayıcılar sayesinde çoğu durumda özellikerin değiştirilmesi kolaydır:
let transfer = new Transfer(id)transfer.from = ...transfer.to = ...transfer.amount = ...
Ayrıca aşağıdaki iki talimattan biriyle özellikleri kaldırmakta mümkündür:
transfer.from.unset()transfer.from = null
Bu yalnızca isteğe bağlı özelliklerle çalışır, yani GraphQL'de !
olmadan tanımlanan özelliklerle. Örnek olarak, owner: Bytes
veya amount: BigInt
verilebilir.
Dizi özelliklerini güncellemek biraz daha karmaşıktır, çünkü bir varlıktan bir dizi almak, o dizinin bir kopyasını oluşturur. Bu sebeple diziyi değiştirdikten sonra dizi özelliklerinin tekrar doğrudan ayarlanması gerekmektedir. Aşağıdaki örnek, entity
nin bir numbers: [BigInt!]!
alanına sahip olduğunu varsayar.
// Bu işe yaramazentity.numbers.push(BigInt.fromI32(1))entity.save()// Bu çalışırlet numbers = entity.numbersnumbers.push(BigInt.fromI32(1))entity.numbers = numbersentity.save()
Şu andabir varlığı oluşturulan türler aracılığıyla kaldırmanın bir yolu yoktur. Bunun yerine, bir varlığı kaldırmak için varlık türünün adını ve varlık ID'sini store.remove
yöntemine iletmek gerekir:
import { store } from '@graphprotocol/graph-ts'...let id = event.transaction.hashstore.remove('Transfer', id)
Ethereum API'si, akıllı sözleşmelere, genel durum değişkenlerine, sözleşme fonksiyonlarına, olaylara, işlemlere, bloklara ve Ethereum verilerinin kodlama/çözme işlemlerine erişim sağlar.
Varlıklarda olduğu gibi graph codegen
, bir subgraph'te kullanılan tüm akıllı sözleşmeler ve olaylar için sınıflar oluşturur. Bunun için, sözleşme ABI'lerinin subgraph manifestosundaki veri kaynağının bir parçası olması gerekir. ABI dosyaları genelde abis/
klasöründe saklanır.
Oluşturulan sınıflarla sayesinde Ethereum türleri ile arasındaki dönüşümler arka planda gerçekleşir, böylece subgraph yazarlarının bu dönüşümlerle ilgilenmesine gerek kalmaz.
Aşağıdaki örnek bunu açıklar. Aşağıdaki gibi bir subgraph şeması verildiğinde
type Transfer @entity {id: Bytes!from: Bytes!to: Bytes!amount: BigInt!}
ve Ethereum üzerindeki Transfer(address,address,uint256)
olay imzası için, sırasıyla address
, address
ve uint256
türlerine sahipfrom
, to
ve amount
değerleri, Address
ve BigInt
türlerine dönüştürülür. Bu sayede, bu değerler Transfer
varlığındaki Bytes!
ve BigInt!
özelliklerine aktarılabilir:
let id = event.transaction.hashlet transfer = new Transfer(id)transfer.from = event.params.fromtransfer.to = event.params.totransfer.amount = event.params.amounttransfer.save()
Önceki örneklerdeki Transfer
olayı gibi olay işleyicilere iletilen Ethereum olayları, sadece olay parametrelerine değil, aynı zamanda bu olayların ait olduğu işlem ve blok bilgilerine de erişim sağlar. event
örneklerinden aşağıdaki veriler elde edilebilir (bu sınıflar graph-ts
içindeki ethereum
modülünün bir parçasıdır):
class Event {address: AddresslogIndex: BigInttransactionLogIndex: BigIntlogType: string | nullblock: Blocktransaction: Transactionparameters: Array<EventParam>receipt: TransactionReceipt | null}class Block {hash: BytesparentHash: BytesunclesHash: Bytesauthor: AddressstateRoot: BytestransactionsRoot: BytesreceiptsRoot: Bytesnumber: BigIntgasUsed: BigIntgasLimit: BigInttimestamp: BigIntdifficulty: BigInttotalDifficulty: BigIntsize: BigInt | nullbaseFeePerGas: BigInt | null}class Transaction {hash: Bytesindex: BigIntfrom: Addressto: Address | nullvalue: BigIntgasLimit: BigIntgasPrice: BigIntinput: Bytesnonce: BigInt}class TransactionReceipt {transactionHash: BytestransactionIndex: BigIntblockHash: BytesblockNumber: BigIntcumulativeGasUsed: BigIntgasUsed: BigIntcontractAddress: Addresslogs: Array<Log>status: BigIntroot: ByteslogsBloom: Bytes}class Log {address: Addresstopics: Array<Bytes>data: BytesblockHash: BytesblockNumber: BytestransactionHash: BytestransactionIndex: BigIntlogIndex: BigInttransactionLogIndex: BigIntlogType: stringremoved: bool | null}
graph codegen
tarafından oluşturulan kod, subgraph'te kullanılan akıllı sözleşmeler için sınıflar da içerir. Bu sınıflar, mevcut blokta sözleşmenin genel durum değişkenlerine erişmek ve sözleşme fonksiyonlarını çağırmak için kullanılabilir.
Yaygın bir model, bir olayın kaynaklandığı sözleşmeye erişmektir. Bu, aşağıdaki kodla elde edilir:
// Oluşturulan sözleşme sınıfı ve Transfer olayı sınıfını içe aktarınimport { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'// Oluşturulan varlık sınıfını içe aktarınimport { Transfer } from '../generated/schema'export function handleTransfer(event: TransferEvent) {// Sözleşmeyi olayı yayınlayan adresle bağlayınlet contract = ERC20Contract.bind(event.address)// Durum değişkenlerine ve işlevlere erişmek için çağrı yapınlet erc20Symbol = contract.symbol()}
Burada Transfer
, varlık türüyle adlandırma çakışmasını önlemek için TransferEvent
olarak yeniden adlandırılmıştır
Ethereum üzerindeki ERC20Contract
sözleşmesi symbol
adında herkese açık ve salt okunur bir fonksiyona sahip olduğu sürece, .symbol()
ile çağrılabilir. Genel durum değişkenleri için otomatik olarak aynı ada sahip bir metot oluşturulur.
Subgraph parçası olan diğer tüm sözleşmelerde oluşturulan koddan içe aktarılabilir ve geçerli bir adrese bağlanabilir.
Eğer sözleşmenizin salt okunur metotlarıının başarısız olması (revert) mümkünse, kodunuzu try_
öneki ile oluşturulmuş sözleşme metodunu çağırarak çözümleyebilirsiniz (handle).
- Örneğin, Gravity sözleşmesi
gravatarToOwner
metodunu dışa açar. Bu kod, metodun başarısızlıkla sonuçlanmasını (revert) çözümleyebilir:
let gravity = Gravity.bind(event.address)let callResult = gravity.try_gravatarToOwner(gravatar)if (callResult.reverted) {log.info('getGravatar reverted', [])} else {let owner = callResult.value}
Not: Geth veya Infura istemcisine bağlı bir Graph Düğümü tüm başarısızlıkları (revert) algılamayabilir. Buna bel bağlıyorsanız Parity istemcisine bağlı bir Graph Düğümü kullanmanızı öneririz.
Veriler, ethereum
modülündeki encode
ve decode
fonksiyonları kullanılarak Ethereum'un ABI kodlama formatına göre kodlanabilir ve kodu çözülebilir.
import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'let tupleArray: Array<ethereum.Value> = [ethereum.Value.fromAddress(Address.fromString('0x0000000000000000000000000000000000000420')),ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(62)),]let tuple = tupleArray as ethereum.Tuplelet encoded = ethereum.encode(ethereum.Value.fromTuple(tuple))!let decoded = ethereum.decode('(address,uint256)', encoded)
Daha fazla bilgi için:
Bir adresin yerel token bakiyesi ethereum
modülü kullanılarak elde edilebilir. Bu özellik, subgraph.yaml
dosyasında tanımlanan apiVersion: 0.0.9
itibarıyla kullanılabilir. getBalance()
fonksiyonu, belirtilen adresin olayın tetiklendiği blok sonundaki bakiyesini alır.
import { ethereum } from '@graphprotocol/graph-ts'let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')let balance = ethereum.getBalance(address) // bakiyeyi BigInt olarak döndürür
Bir adresin akıllı sözleşme adresi mi yoksa harici sahipli bir adres (EOA) mi olduğunu kontrol etmek için, ethereum
modülündeki hasCode()
fonksiyonu kullanılabilir. Bu fonksiyon boolean
döner. Bu özellik subgraph.yaml
dosyasında tanımlanan apiVersion: 0.0.9
itibarıyla kullanılabilir.
import { ethereum } from '@graphprotocol/graph-ts'let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')let isContract = ethereum.hasCode(contractAddr).inner // true döndürürlet eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')let isContract = ethereum.hasCode(eoa).inner // false döndürür
import { log } from '@graphprotocol/graph-ts'
log
API'si, subgraph'lerin bilgileri Graph Düğümü standart çıktısına ve Graph Gezgini'ne kaydetmesine olanak tanır. Mesajlar farklı günlük seviyeleri kullanılarak kaydedilebilir. Verilen argümanlardan günlük mesajlarını oluşturmak için temel bir biçimlendirme dizesi sentaksı sunulmaktadır.
log
API'si aşağıdaki fonksiyonları içerir:
log.debug(fmt: string, args: Array<string>): void
– bir hata ayıklama mesajı kaydeder.log.info(fmt: string, args: Array<string>): void
– bir bilgilendirme mesajı kaydeder.log.warning(fmt: string, args: Array<string>): void
– bir uyarı mesajı kaydeder.log.error(fmt: string, args: Array<string>): void
– bir hata mesajı kaydeder.log.critical(fmt: string, args: Array<string>): void
– kritik bir mesaj kaydeder ve subgraph'i sonlandırır.
log
API'si bir format dizesi ve bir dize değerleri dizisini alır. Daha sonra, dizideki dize değerlerini format dizesindeki yer tutucuların yerine koyar. İlk {}
yer tutucusu dizideki ilk değerle, ikinci {}
yer tutucusu ikinci değerle ve bu şekilde devam ederek değiştirilir.
log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string'])
Aşağıdaki örnekte, "A" dize değeri, kaydedilmeden önce bir diziye dönüştürülerek ['A']
haline getirilir:
let myValue = 'A'export function handleSomeEvent(event: SomeEvent): void {// Görüntüler : "My value is: A"log.info('My value is: {}', [myValue])}
Aşağıdaki örnekte, bağımsız değişken dizisi üç değer içermesine rağmen dizinin yalnızca ilk değeri loglanır.
let myArray = ['A', 'B', 'C']export function handleSomeEvent(event: SomeEvent): void {// Görüntüler: "My value is: A" ('log.info'ya üç değer iletilmiş olsa da)log.info('My value is: {}', myArray)}
Argüman dizisindeki her girişin günlük mesajındaki bir yer tutucu {}
ile eşleşmesi gerekir. Aşağıdaki örnek, günlük mesajında üç yer tutucu {}
içerir. Bu nedenle, myArray
'deki üç değerin üçü de loglanır.
let myArray = ['A', 'B', 'C']export function handleSomeEvent(event: SomeEvent): void {// Görüntüler: "My first value is: A, second value is: B, third value is: C"log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)}
Dizide belirli bir değeri görüntülemek için dizinlenmiş değer bulunmalıdır.
export function handleSomeEvent(event: SomeEvent): void {// Görüntüler : "My third value is C"log.info('My third value is: {}', [myArray[2]])}
Aşağıdaki örnek, bir olaydan blok numarasını, blok hash'ını ve işlem hash'ını loglar:
import { log } from '@graphprotocol/graph-ts'export function handleSomeEvent(event: SomeEvent): void {log.debug('Block number: {}, block hash: {}, transaction hash: {}', [event.block.number.toString(), // "47596000"event.block.hash.toHexString(), // "0x..."event.transaction.hash.toHexString(), // "0x..."])}
import { ipfs } from '@graphprotocol/graph-ts'
Akıllı sözleşmeler bazen IPFS dosyalarını zincire sabitler. Bu, eşlemelerin sözleşmeden IPFS hash'lerini almasını ve ilgili dosyaları IPFS'ten okumasını sağlar. Dosya verileri Bytes
olarak döndürülür ve genellikle daha fazla işleme tabi tutulması gerekir; örneğin, bu sayfada daha sonra belgelenen json
API'si ile.
IPFS hash'ı veya yolu verildiğinde, bir dosyayı IPFS'den okuma şu şekilde yapılır:
// Bunu eşleştirmedeki bir olay işleyicinin içine koyunlet hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'let data = ipfs.cat(hash)// `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`gibi yollar// bu dizinlerdeki dosyaları içerenler de desteklenirlet path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'let data = ipfs.cat(path)
Not: Şu anda ipfs.cat
deterministik değildir. Eğer dosya, IPFS ağı üzerinden, talebin zaman aşımından önce getirilemezse, fonksiyon null
döndürür. Bu nedenle, sonucunnull
olup olmadığını kontrol etmek her zaman önemlidir.
Ayrıca, daha büyük dosyaları akış halinde işlemek için ipfs.map
kullanmak da mümkündür. Bu fonksiyon, bir IPFS dosyasının hash'ini veya yolunu, bir geri çağırma işlevinin adını ve davranışını değiştirmek için bayraklar alır:
import { JSONValue, Value } from '@graphprotocol/graph-ts'export function processItem(value: JSONValue, userData: Value): void {// İşlem yapmayla ilgili ayrıntılar için JSONValue belgelerine bakın// JSON değerleri ilelet obj = value.toObject()let id = obj.get('id')let title = obj.get('title')if (!id || !title) {return}// Geri çağırmalar da varlık oluşturabilirlet newItem = new Item(id)newItem.title = title.toString()newitem.parent = userData.toString() // Set parent to "parentId"newitem.save()}// Bunu eşleştirmedeki bir olay işleyicisinin içine koyunipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])// Alternatif olarak `ipfs.mapJSON` kullanınipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))
Şu anda desteklenen tek bayrak ipfs.map
'e iletilmesi gereken json
bayrağıdır. json
bayrağı ile IPFS dosyası, her satırda bir JSON değeri olacak şekilde bir dizi JSON değerinden oluşmalıdır. ipfs.map
çağrısı, dosyadaki her satırı okur, bir JSONValue
olarak ayrıştırır (deserialize eder) ve her biri için geri çağırma (callback) fonksiyonunu çağırır. Geri çağırma fonksiyonu daha sonra JSONValue
dan gelen verileri depolamak için varlık operasyonlarını kullanabilir. Varlık değişiklikleri yalnızca ipfs.map
'i çağıran işleyici başarıyla tamamlandığında depolanır; bu sırada değişiklikler bellekte tutulur ve bu nedenle ipfs.map
'in işleyebileceği dosya boyutu sınırlıdır.
Başarılı olduğunda ipfs.map
, void
döndürür. Geri çağırma fonksiyonunun herhangi bir çağrısı bir hataya neden olursa, ipfs.map
'i çağıran işleyici durdurulur ve subgraph başarısız olarak işaretlenir.
import { crypto } from '@graphprotocol/graph-ts'
crypto
API'si, eşlemelerde kullanılan kriptografik fonksiyonları sağlar. Şu anda yalnızca bir fonksiyon mevcuttur:
crypto.keccak256(input: ByteArray): ByteArray
import { json, JSONValueKind } from '@graphprotocol/graph-ts'
JSON verileri, json
API'si kullanılarak ayrıştırılabilir:
json.fromBytes(data: Bytes): JSONValue
– Geçerli bir UTF-8 sekansı olarak yorumlanan birBytes
dizisinden JSON verisini ayrıştırırjson.try_fromBytes(data: Bytes): Result<JSONValue, boolean>
–json.fromBytes
'in güvenli versiyonu. Ayrıştırma başarısız olursa bir hata döndürürjson.fromString(data: string): JSONValue
– Geçerli bir UTF-8String
den JSON verilerini ayrıştırırjson.try_fromString(data: string): Result<JSONValue, boolean>
–json.fromString
'in güvenli versiyonu. Ayrıştırma başarısız olursa bir hata döndürür
JSONValue
sınıfı, rastgele bir JSON belgesinden değerleri çekmek için bir yol sağlar. JSON değerleri boolean, sayı, dizi gibi türlerde olabileceği için, JSONValue
sınıfı bir değerin türünü kontrol etmek için kind
özelliği ile birlikte gelir:
let value = json.fromBytes(...)if (value.kind == JSONValueKind.BOOL) {...}
Ayrıca, değerin null
olup olmadığını kontrol etmek için bir metot da vardır:
value.isNull(): boolean
Bir değerin türü kesin olduğunda, aşağıdaki yöntemlerden biri kullanılarak birine dönüştürülebilir:
value.toBool(): boolean
value.toI64(): i64
value.toF64(): f64
value.toBigInt(): BigInt
value.toString(): string
value.toArray(): Array<JSONValue>
– (ve ardındanJSONValue
değerini yukarıdaki 5 metottan biriyle dönüştürün)
Kaynak(lar) | Hedef | Dönüşüm fonksiyonu |
---|---|---|
Address | Bytes | yok |
Address | String | s.toHexString() |
BigDecimal | String | s.toString() |
BigInt | BigDecimal | s.toBigDecimal() |
BigInt | Dizgi (onaltılık) | s.toHexString() or s.toHex() |
BigInt | String (unicode) | s.toString() |
BigInt | i32 | s.toI32() |
Boolean | Boolean | yok |
Bytes (işaretli) | BigInt | BigInt.fromSignedBytes(s) |
Bytes (işaretsiz) | BigInt | BigInt.fromUnsignedBytes(s) |
Bytes | Dizgi (onaltılık) | s.toHexString() or s.toHex() |
Bytes | String (unicode) | s.toString() |
Bytes | String (base58) | s.toBase58() |
Bytes | i32 | s.toI32() |
Bytes | u32 | s.toU32() |
Bytes | JSON | json.fromBytes(s) |
int8 | i32 | yok |
int32 | i32 | yok |
int32 | BigInt | BigInt.fromI32(s) |
uint24 | i32 | yok |
int64 - int256 | BigInt | yok |
uint32 - uint256 | BigInt | yok |
JSON | boolean | s.toBool() |
JSON | i64 | s.toI64() |
JSON | u64 | s.toU64() |
JSON | f64 | s.toF64() |
JSON | BigInt | s.toBigInt() |
JSON | string | s.toString() |
JSON | Array | s.toArray() |
JSON | Object | s.toObject() |
String | Address | Address.fromString(s) |
Bytes | Address | Address.fromBytes(s) |
String | BigInt | BigInt.fromString(s) |
String | BigDecimal | BigDecimal.fromString(s) |
Dizgi (onaltılık) | Bytes | ByteArray.fromHexString(s) |
String (UTF-8) | Bytes | ByteArray.fromUTF8(s) |
dataSource
ad alanı üzerinden işleyiciyi çağıran veri kaynağının sözleşme adresini, ağını ve bağlamını inceleyebilirsiniz:
dataSource.address(): Address
dataSource.network(): string
dataSource.context(): DataSourceContext
Temel Entity
sınıfı ve alt sınıf olan DataSourceContext
sınıfı, alanları dinamik olarak ayarlamak ve almak için yardımcı programlara sahiptir:
setString(key: string, value: string): void
setI32(key: string, value: i32): void
setBigInt(key: string, value: BigInt): void
setBytes(key: string, value: Bytes): void
setBoolean(key: string, value: bool): void
setBigDecimal(key, value: BigDecimal): void
getString(key: string): string
getI32(key: string): i32
getBigInt(key: string): BigInt
getBytes(key: string): Bytes
getBoolean(key: string): boolean
getBigDecimal(key: string): BigDecimal
dataSources
içindeki context
bölümü, subgraph eşlemeleriniz içinde erişilebilen anahtar-değer çiftlerini tanımlamanıza olanak tanır. Kullanılabilir türler şunlardır: Bool
, String
, Int
, Int8
, BigDecimal
, Bytes
, List
ve BigInt
.
İşte context
bölümünde çeşitli türlerin kullanımını gösteren bir YAML örneği:
dataSources:- kind: ethereum/contractname: ContractNamenetwork: mainnetcontext:bool_example:type: Booldata: truestring_example:type: Stringdata: 'hello'int_example:type: Intdata: 42int8_example:type: Int8data: 127big_decimal_example:type: BigDecimaldata: '10.99'bytes_example:type: Bytesdata: '0x68656c6c6f'list_example:type: Listdata:- type: Intdata: 1- type: Intdata: 2- type: Intdata: 3big_int_example:type: BigIntdata: '1000000000000000000000000'
Bool
: Boolean bir değer (true
veyafalse
) belirtir.String
: Bir String (dize) değeri belirtir.Int
: 32-bit bir tamsayı belirtir.Int8
: 8-bit bir tamsayı belirtir.BigDecimal
: Ondalık bir sayı belirtir. Tırnak içinde yazılması gerekir.Bytes
: On altılık tabanda (hexadecimal) bir dizeyi belirtir.List
: Elemanlardan oluşan bir liste belirtir. Her elemanın türü ve verisi belirtilmelidir.BigInt
: Büyük bir tamsayı değeri belirtir. Büyük boyutu nedeniyle tırnak içinde yazılması gerekir.
Bu bağlama daha sonra subgraph eşleştirme dosyalarınızdan erişilebilir ve böylece daha dinamik ve yapılandırılabilir subgraphlar elde edebilirsiniz.