18 dakika
AssemblyScript API'si
Note: If you created a Subgraph prior to graph-cli/graph-ts version 0.22.0, then you’re using an older version of AssemblyScript. It is recommended to review the Migration Guide.
Learn what built-in APIs can be used when writing Subgraph mappings. There are two kinds of APIs available out of the box:
- Graph TypeScript kütüphanesi (
graph-ts) - Code generated from Subgraph files by
graph codegen
AssemblyScript 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, AssemblyScript wiki’sindeki dil ve standart kütüphane özelliklerini gözden geçirmek faydalı olacaktır.
API Referansı
@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
ethereumAPI’si. - Varlıkları Graph Düğümü deposundan yüklemek ve depoya kaydetmek için bir
storeAPI’si. - Graph Düğümü çıktısına ve Graph Gezgini’ne mesaj kaydetmek için bir
logAPI’si. - IPFS’ten dosyaları yüklemek için bir
ipfsAPI’si. - JSON verilerini ayrıştırmak için bir
jsonAPI’si. - Kriptografik fonksiyonları kullanmak için bir
cryptoAPI’si. - Ethereum, JSON, GraphQL ve AssemblyScript gibi farklı tip sistemler arası çeviri yapmak için düşük seviyeli yazılımlar.
Sürümler
The apiVersion in the Subgraph manifest specifies the mapping API version which is run by Graph Node for a given Subgraph.
| Sürüm | Sürüm Notları |
|---|---|
| 0.0.9 | Yeni host fonksiyonları ekler: eth_get_balance ve hasCode |
| 0.0.8 | Bir varlığı kaydederken şemadaki alanların varlığını doğrulama mekanizması ekler. |
| 0.0.7 | Ethereum türlerine TransactionReceipt ve Log sınıfları eklendiEthereum Event nesnesine receipt alanı eklendi |
| 0.0.6 | Ethereum Transaction nesnesine nonce alanı eklendiEthereum Block nesnesine baseFeePerGas eklendi |
| 0.0.5 | AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the Migration Guide)ethereum.transaction.gasUsed renamed to ethereum.transaction.gasLimit |
| 0.0.4 | Ethereum SmartContractCall nesnesine functionSignature alanı eklendi |
| 0.0.3 | Ethereum Call nesnesine from alanı eklendiethereum.call.address, ethereum.call.to olarak yeniden adlandırıldı |
| 0.0.2 | Ethereum Transaction nesnesine input alanı eklendi |
Dahili Türler
AssemblyScript’e yerleşik olan temel türler hakkında dökümantasyona AssemblyScript wiki’sinden ulaşabilirsiniz.
Aşağıdaki ek türler @graphprotocol/graph-ts tarafından sağlanmaktadır.
ByteArray
1import { ByteArray } from '@graphprotocol/graph-ts'ByteArray, bir u8 dizisini temsil eder.
Oluşturma
fromI32(x: i32): ByteArray-xdeğerini baytlara ayrıştırır.fromHexString(hex: string): ByteArray- Girdi uzunluğu çift sayı olmalıdır.0xile 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 biru32olarak yorumlar. Aşım durumunda hata verir.toI32(): i32- Bayt dizisini little-endian biri32olarak yorumlar. Aşım durumunda hata verir.
Operatörler
equals(y: ByteArray): bool–x == yolarak yazılabilir.concat(other: ByteArray): ByteArray-thisdizisinin sonunaotherdizisini ekleyerek yeni birByteArraydöner.concatI32(other: i32): ByteArray-thisdizisinin sonunaother’ın bayt temsili ekleyerek yeni birByteArraydöner.
BigDecimal
1import { BigDecimal } from '@graphprotocol/graph-ts'BigDecimal, ondalık sayıları istenildiği kadar doğrulukta temsil etmek için kullanılır.
Not: Dahili olarak BigDecimal, IEEE-754 decimal128 floating-point formatında 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 ufixed256x18 gibi) uygun olmaktan çıkarır.
Oluşturma
constructor(bigInt: BigInt)– BirBigInt’ten birBigDecimaloluş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.
BigInt
1import { 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 birBigIntoluşturur. -
BigInt.fromString(s: string): BigInt– Bir dizeden birBigIntoluş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 biri32olarak 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 | yolarak 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.
TypedMap
1import { TypedMap } from '@graphprotocol/graph-ts'TypedMap, anahtar-değer çiftlerini saklamak için kullanılabilir. Bu örneği inceleyebilirsiniz.
TypedMap sınıfının API’si aşağıdaki gibidir:
new TypedMap<K, V>()–Ktüründe anahtarlar veVtüründe değerler içeren boş bir eşlem oluştururmap.set(key: K, value: V): void–keyanahtarının değerinivalueolarak ayarlarmap.getEntry(key: K): TypedMapEntry<K, V> | null–keyiçin anahtar-değer çiftini döndürür, eğerkeyeşlemde mevcut değilsenulldönermap.get(key: K): V | null–keyiçin değeri döndürür, eğerkeyeşlemde mevcut değilsenulldönermap.isSet(key: K): bool– Eğerkeyeşlemde mevcutsatrue, değilsefalsedöner
Baytlar
1import { 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 Uint8Array 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–hexdizesini, on altı tabanında çift sayıda basamaktan oluşması koşuluyla birByteArray’e dönüştürür.hexdizesi isteğe bağlı olarak0xile başlayabilirfromI32(i: i32): Bytes–ideğ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–thisdizisinin sonunaotherdizisini ekleyerek yeni birBytesdöndürürb.concatI32(other: i32): ByteArray–thisdizisinin sonrasınaother’ın bayt temsilini eklenerek yeni birBytesdöndürür
Adres(Address)
1import { 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 birAddressoluştururAddress.fromBytes(b: Bytes): Address– Tam olarak 20 bayt uzunluğunda olması gerekenbdizisinden birAddressoluşturur. Daha az veya daha fazla bayt içeren bir değer geçildiğinde hata verir
Store API
1import { 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.
Entities written to the store map one-to-one to the @entity types defined in the Subgraph’s GraphQL schema. To make working with these entities convenient, the graph codegen command provided by the Graph CLI generates entity classes, which are subclasses of the built-in Entity type, with property getters and setters for the fields in the schema as well as methods to load and save these entities.
Unsurların Oluşturulması
Aşağıdaki, Ethereum olaylarından varlıklar oluşturmak için yaygın bir modeldir.
1// ERC20 ABI'dan oluşturulan Transfer olay sınıfını içe aktarın2import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'34// GraphQL şemasından oluşturulan Transfer varlık türünü içe aktarın5import { Transfer } from '../generated/schema'67// Transfer olayı işleyicisi8export function handleTransfer(event: TransferEvent): void {9 // İşlem hash'ını olay kimliği olarak kullanarak bir Transfer varlığı oluşturun10 let id = event.transaction.hash11 let transfer = new Transfer(id)1213 // Olay parametrelerini kullanarak varlığın özelliklerini ayarlayın14 transfer.from = event.params.from15 transfer.to = event.params.to16 transfer.amount = event.params.amount1718 // Varlığı depoya kaydedin19 transfer.save()20}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.
Depodan varlık yükleme
Bir varlık mevcutsa aiağıdaki kod kullanılarak depodan yüklenebilir:
1let id = event.transaction.hash // veya kimlik(ID) nasıl oluşturulmuşsa2let transfer = Transfer.load(id)3if (transfer == null) {4 transfer = new Transfer(id)5}67// Transfer varlığı önceki gibi kullanılırVarlı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.
Bir blok içinde oluşturulan varlıkları arama
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.
The store API facilitates the retrieval of entities that were created or updated in the current block. A typical situation for this is that one handler creates a transaction from some onchain event, and a later handler wants to access this transaction if it exists.
- In the case where the transaction does not exist, the Subgraph will have to go to the database simply to find out that the entity does not exist. If the Subgraph author already knows that the entity must have been created in the same block, using
loadInBlockavoids this database roundtrip. - For some Subgraphs, these missed lookups can contribute significantly to the indexing time.
1let id = event.transaction.hash // veya ID nasıl oluşturulurmuşsa2let transfer = Transfer.loadInBlock(id)3if (transfer == null) {4 transfer = new Transfer(id)5}67// Transfer varlığını daha önce olduğu gibi kullanınNot: 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.
Türetilmiş varlıkları arama
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:
1type Token @entity {2 id: ID!3 holder: Holder!4 color: String5}67type Holder @entity {8 id: ID!9 tokens: [Token!]! @derivedFrom(field: "holder")10}Aşağıdaki kod, Holder varlığının türetildiği Token varlığını yükleyecektir:
1let holder = Holder.load('test-id')2// Belirli bir sahiple ilişkili Token unsurlarını yükleyin3let tokens = holder.tokens.load()Mevcut varlıkları güncelleme
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:
1let transfer = new Transfer(id)2transfer.from = ...3transfer.to = ...4transfer.amount = ...Ayrıca aşağıdaki iki talimattan biriyle özellikleri kaldırmakta mümkündür:
1transfer.from.unset()2transfer.from = nullBu 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, entitynin bir numbers: [BigInt!]! alanına sahip olduğunu varsayar.
1// Bu işe yaramaz2entity.numbers.push(BigInt.fromI32(1))3entity.save()45// Bu çalışır6let numbers = entity.numbers7numbers.push(BigInt.fromI32(1))8entity.numbers = numbers9entity.save()Depodan varlık kaldırma
Ş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:
1import { store } from '@graphprotocol/graph-ts'2...3let id = event.transaction.hash4store.remove('Transfer', id)Ethereum API
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.
Ethereum Türleri İçin Destek
As with entities, graph codegen generates classes for all smart contracts and events used in a Subgraph. For this, the contract ABIs need to be part of the data source in the Subgraph manifest. Typically, the ABI files are stored in an abis/ folder.
With the generated classes, conversions between Ethereum types and the built-in types take place behind the scenes so that Subgraph authors do not have to worry about them.
The following example illustrates this. Given a Subgraph schema like
1type Transfer @entity {2 id: Bytes!3 from: Bytes!4 to: Bytes!5 amount: BigInt!6}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:
1let id = event.transaction.hash2let transfer = new Transfer(id)3transfer.from = event.params.from4transfer.to = event.params.to5transfer.amount = event.params.amount6transfer.save()Olaylar ve Blok/İşlem Verileri
Ö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):
1class Event {2 address: Address3 logIndex: BigInt4 transactionLogIndex: BigInt5 logType: string | null6 block: Block7 transaction: Transaction8 parameters: Array<EventParam>9 receipt: TransactionReceipt | null10}1112class Block {13 hash: Bytes14 parentHash: Bytes15 unclesHash: Bytes16 author: Address17 stateRoot: Bytes18 transactionsRoot: Bytes19 receiptsRoot: Bytes20 number: BigInt21 gasUsed: BigInt22 gasLimit: BigInt23 timestamp: BigInt24 difficulty: BigInt25 totalDifficulty: BigInt26 size: BigInt | null27 baseFeePerGas: BigInt | null28}2930class Transaction {31 hash: Bytes32 index: BigInt33 from: Address34 to: Address | null35 value: BigInt36 gasLimit: BigInt37 gasPrice: BigInt38 input: Bytes39 nonce: BigInt40}4142class TransactionReceipt {43 transactionHash: Bytes44 transactionIndex: BigInt45 blockHash: Bytes46 blockNumber: BigInt47 cumulativeGasUsed: BigInt48 gasUsed: BigInt49 contractAddress: Address50 logs: Array<Log>51 status: BigInt52 root: Bytes53 logsBloom: Bytes54}5556class Log {57 address: Address58 topics: Array<Bytes>59 data: Bytes60 blockHash: Bytes61 blockNumber: Bytes62 transactionHash: Bytes63 transactionIndex: BigInt64 logIndex: BigInt65 transactionLogIndex: BigInt66 logType: string67 removed: bool | null68}Akıllı Sözleşme Durumuna Erişim
The code generated by graph codegen also includes classes for the smart contracts used in the Subgraph. These can be used to access public state variables and call functions of the contract at the current block.
Yaygın bir model, bir olayın kaynaklandığı sözleşmeye erişmektir. Bu, aşağıdaki kodla elde edilir:
1// Oluşturulan sözleşme sınıfı ve Transfer olayı sınıfını içe aktarın2import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'3// Oluşturulan varlık sınıfını içe aktarın4import { Transfer } from '../generated/schema'56export function handleTransfer(event: TransferEvent) {7 // Sözleşmeyi olayı yayınlayan adresle bağlayın8 let contract = ERC20Contract.bind(event.address)910 // Durum değişkenlerine ve işlevlere erişmek için çağrı yapın11 let erc20Symbol = contract.symbol()12}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.
Any other contract that is part of the Subgraph can be imported from the generated code and can be bound to a valid address.
Geri Dönen Çağrıları Yönetme
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
gravatarToOwnermetodunu dışa açar. Bu kod, metodun başarısızlıkla sonuçlanmasını (revert) çözümleyebilir:
1let gravity = Gravity.bind(event.address)2let callResult = gravity.try_gravatarToOwner(gravatar)3if (callResult.reverted) {4 log.info('getGravatar reverted', [])5} else {6 let owner = callResult.value7}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.
ABI Kodlama/Çözme
Veriler, ethereum modülündeki encode ve decode fonksiyonları kullanılarak Ethereum’un ABI kodlama formatına göre kodlanabilir ve kodu çözülebilir.
1import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'23let tupleArray: Array<ethereum.Value> = [4 ethereum.Value.fromAddress(Address.fromString('0x0000000000000000000000000000000000000420')),5 ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(62)),6]78let tuple = tupleArray as ethereum.Tuple910let encoded = ethereum.encode(ethereum.Value.fromTuple(tuple))!1112let decoded = ethereum.decode('(address,uint256)', encoded)Daha fazla bilgi için:
- ABI Spec
- Kodlama/kod çözme Rust kütüphanesi/CLI
- Daha karmaşık bir örnek.
Bir Adresin Bakiyesi
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.
1import { ethereum } from '@graphprotocol/graph-ts'23let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')4let balance = ethereum.getBalance(address) // bakiyeyi BigInt olarak döndürürBir Adresin Akıllı Sözleşme veya EOA (Harici Sahipli Hesap) Olup Olmadığını Kontrol Etme
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.
1import { ethereum } from '@graphprotocol/graph-ts'23let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')4let isContract = ethereum.hasCode(contractAddr).inner // true döndürür56let eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')7let isContract = ethereum.hasCode(eoa).inner // false döndürürLogging API
1import { log } from '@graphprotocol/graph-ts'The log API allows Subgraphs to log information to the Graph Node standard output as well as Graph Explorer. Messages can be logged using different log levels. A basic format string syntax is provided to compose log messages from argument.
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– logs a critical message and terminates the Subgraph.
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.
1log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string'])Bir veya daha fazla değerin loglanması
Tek bir değerin loglanması
Aşağıdaki örnekte, “A” dize değeri, kaydedilmeden önce bir diziye dönüştürülerek ['A'] haline getirilir:
1let myValue = 'A'23export function handleSomeEvent(event: SomeEvent): void {4 // Görüntüler : "My value is: A"5 log.info('My value is: {}', [myValue])6}Mevcut bir diziden tek bir girişi loglama
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.
1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4 // Görüntüler: "My value is: A" ('log.info'ya üç değer iletilmiş olsa da)5 log.info('My value is: {}', myArray)6}Mevcut bir diziden birden çok girişi kaydetme
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.
1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4 // Görüntüler: "My first value is: A, second value is: B, third value is: C"5 log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)6}Mevcut bir diziden belirli bir girişi loglama
Dizide belirli bir değeri görüntülemek için dizinlenmiş değer bulunmalıdır.
1export function handleSomeEvent(event: SomeEvent): void {2 // Görüntüler : "My third value is C"3 log.info('My third value is: {}', [myArray[2]])4}Olay bilgilerinin loglanması
Aşağıdaki örnek, bir olaydan blok numarasını, blok hash’ını ve işlem hash’ını loglar:
1import { log } from '@graphprotocol/graph-ts'23export function handleSomeEvent(event: SomeEvent): void {4 log.debug('Block number: {}, block hash: {}, transaction hash: {}', [5 event.block.number.toString(), // "47596000"6 event.block.hash.toHexString(), // "0x..."7 event.transaction.hash.toHexString(), // "0x..."8 ])9}IPFS API
1import { ipfs } from '@graphprotocol/graph-ts'Smart contracts occasionally anchor IPFS files onchain. This allows mappings to obtain the IPFS hashes from the contract and read the corresponding files from IPFS. The file data will be returned as Bytes, which usually requires further processing, e.g. with the json API documented later on this page.
IPFS hash’ı veya yolu verildiğinde, bir dosyayı IPFS’den okuma şu şekilde yapılır:
1// Bunu eşleştirmedeki bir olay işleyicinin içine koyun2let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'3let data = ipfs.cat(hash)45// `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`6gibi yollar7// bu dizinlerdeki dosyaları içerenler de desteklenir8let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'9let 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:
1import { JSONValue, Value } from '@graphprotocol/graph-ts'23export function processItem(value: JSONValue, userData: Value): void {4 // İşlem yapmayla ilgili ayrıntılar için JSONValue belgelerine bakın5 // JSON değerleri ile6 let obj = value.toObject()7 let id = obj.get('id')8 let title = obj.get('title')910 if (!id || !title) {11 return12 }1314 // Geri çağırmalar da varlık oluşturabilir15 let newItem = new Item(id)16 newItem.title = title.toString()17 newitem.parent = userData.toString() // Set parent to "parentId"18 newitem.save()19}2021// Bunu eşleştirmedeki bir olay işleyicisinin içine koyun22ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])2324// Alternatif olarak `ipfs.mapJSON` kullanın25ipfs.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 JSONValuedan 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.
On success, ipfs.map returns void. If any invocation of the callback causes an error, the handler that invoked ipfs.map is aborted, and the Subgraph is marked as failed.
Kripto(Crypto) API’si
1import { 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
JSON API
1import { 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 birBytesdizisinden 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-8Stringden 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:
1let value = json.fromBytes(...)2if (value.kind == JSONValueKind.BOOL) {3 ...4}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 yerleşik türlerden birine dönüştürülebilir:
value.toBool(): booleanvalue.toI64(): i64value.toF64(): f64value.toBigInt(): BigIntvalue.toString(): stringvalue.toArray(): Array<JSONValue>– (ve ardındanJSONValuedeğerini yukarıdaki 5 metottan biriyle dönüştürün)
Tip Dönüşümleri Referansı
| 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) |
Veri Kaynağı Meta Verileri
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(): AddressdataSource.network(): stringdataSource.context(): DataSourceContext
Varlık ve VeriKaynağıBağlamı
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): voidsetI32(key: string, value: i32): voidsetBigInt(key: string, value: BigInt): voidsetBytes(key: string, value: Bytes): voidsetBoolean(key: string, value: bool): voidsetBigDecimal(key, value: BigDecimal): voidgetString(key: string): stringgetI32(key: string): i32getBigInt(key: string): BigIntgetBytes(key: string): BytesgetBoolean(key: string): booleangetBigDecimal(key: string): BigDecimal
Manifest’teki DataSourceContext
The context section within dataSources allows you to define key-value pairs that are accessible within your Subgraph mappings. The available types are Bool, String, Int, Int8, BigDecimal, Bytes, List, and BigInt.
İşte context bölümünde çeşitli türlerin kullanımını gösteren bir YAML örneği:
1dataSources:2 - kind: ethereum/contract3 name: ContractName4 network: mainnet5 context:6 bool_example:7 type: Bool8 data: true9 string_example:10 type: String11 data: 'hello'12 int_example:13 type: Int14 data: 4215 int8_example:16 type: Int817 data: 12718 big_decimal_example:19 type: BigDecimal20 data: '10.99'21 bytes_example:22 type: Bytes23 data: '0x68656c6c6f'24 list_example:25 type: List26 data:27 - type: Int28 data: 129 - type: Int30 data: 231 - type: Int32 data: 333 big_int_example:34 type: BigInt35 data: '1000000000000000000000000'Bool: Boolean bir değer (trueveyafalse) 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.
This context is then accessible in your Subgraph mapping files, enabling more dynamic and configurable Subgraphs.