9 dakika
AssemblyScript Geçiş Rehberi
Up until now, Subgraphs have been using one of the first versions of AssemblyScript (v0.6). Finally we’ve added support for the newest one available (v0.19.10)! 🎉
That will enable Subgraph developers to use newer features of the AS language and standard library.
Bu rehber, graph-cli
/graph-ts
araçlarının 0.22.0
ve öncesi versiyonlarını kullanan herkes için geçerlidir. Eğer halihazırda bu versiyonun üstünde (veya ona eşit) bir versiyon kullanıyorsanız, zaten AssemblyScript’in 0.19.10
versiyonunu kullanıyorsunuz demektir 🙂
Note: As of 0.24.0
, graph-node
can support both versions, depending on the apiVersion
specified in the Subgraph manifest.
Özellikler
Yeni işlevsellik
TypedArray
’ler artıkwrap
isimli yeni statik metot (v0.8.1) kullanılarakArrayBuffer
’lardan oluşturulabilir- Yeni standart kütüphane fonksiyonları:
String#toUpperCase
,String#toLowerCase
,String#localeCompare
veTypedArray#set
(v0.9.0) - GenericClass’in bir örneğini doğrulamak için x instanceof GenericClass desteği eklendi (v0.9.2)
- Daha verimli bir dizi çeşidi olan
StaticArray<T>
eklendi, (v0.9.3) Array<T>#flat
eklendi (v0.10.0)Number#toString
fonksiyonundaradix
argümanı desteklenmeye başlandı (v0.10.1)- Kayan nokta literallerinde ayırıcılar için destek eklendi (v0.13.7)
- İlk sınıf fonksiyonlar için destek eklendi (v0.14.0)
- Yerleşikler eklendi:
i32/i64/f32/f64.add/sub/mul
(v0.14.13) Array/TypedArray/String#at
’ fonksiyonu geliştirildi (v0.18.2)- Şablon literal dizeleri için destek eklendi (v0.18.17)
encodeURI(Component)
vedecodeURI(Component)
eklendi (v0.18.27)toString
,toDateString
vetoTimeString
metodlarıDate
’e eklendi (v0.18.29)Date
içintoUTCString
eklendi (v0.18.30)nonnull/NonNullable
yerleşik türü eklendi (v0.19.2)
Optimizasyonlar
Math
fonksiyonları olanexp
,exp2
,log
,log2
vepow
, daha hızlı varyantlarla değiştirildi (v0.9.0)Math.mod
’ fonksiyonu biraz optimize edildi (v0.17.1)- std Map ve Set’te daha fazla alan erişiminin önbelleğe alınması sağlandı (v0.17.8)
- İkinin katları için
ipow32/64
optimizasyonu (v0.18.2)
Diğer
- Bir dizi literalinin türü artık içeriğinden çıkarsanabilir (v0.9.0)
- stdlib Unicode 13.0.0’a güncellendi (v0.10.0)
Nasıl yükseltilir?
- Change your mappings
apiVersion
insubgraph.yaml
to0.0.9
:
1...2dataSources:3 ...4 mapping:5 ...6 apiVersion: 0.0.97 ...
- Kullanmakta olduğunuz
graph-cli
yilatest
(en son) sürüme güncellemek için şu komutu çalıştırın:
1# Eğer `graph-cli` global olarak yüklüyse2npm install --global @graphprotocol/graph-cli@latest34# veya `subgraph` içinde bir geliştirme gereksinimi olarak yüklüyse5npm install --save-dev @graphprotocol/graph-cli@latest
- Aynısını
graph-ts
için de yapın, ancak global olarak kurmak yerine ana gereksinimlerinizde kaydedin:
1npm install --save @graphprotocol/graph-ts@latest
- Dildeki uyumsuzluk sorunlarını düzeltmek için rehberin geri kalanını takip edin.
codegen
vedeploy
komutlarını tekrar çalıştırın.
Uyumsuz değişiklikler
Null olabilme durumu
AssemblyScript’in eski bir sürümünde şu şekilde kod oluşturabilirdiniz:
1function load(): Value | null { ... }23let maybeValue = load();4maybeValue.aMethod();
Ancak, daha yeni sürümde değer null olabildiği için bunu kontrol etmenizi gerektirir, aşağıdaki gibi:
1let maybeValue = load()23if (maybeValue) {4 maybeValue.aMethod() // `maybeValue` artık null değil5}
Veya bunu şu şekilde zorlayın:
1let maybeValue = load()! // Değer null ise çalıştırma esnasında hata verir23maybeValue.aMethod()
If you are unsure which to choose, we recommend always using the safe version. If the value doesn’t exist you might want to just do an early if statement with a return in you Subgraph handler.
Değişken Gölgeleme
Daha önce değişken gölgeleme yapabiliyordunuz ve aşağıdaki gibi bir kod çalışıyordu:
1let a = 102let b = 203let a = a + b
Ancak bu artık mümkün değil ve bu kodu derlemeye çalışırsanız derleyici şu hatayı verir:
1ERROR TS2451: Cannot redeclare block-scoped variable 'a'23 let a = a + b;4 ~~~~~~~~~~~~~5in assembly/index.ts(4,3)
Eğer değişken gölgeleme yapıyorsanız, yinelenen değişkenlerinizi yeniden adlandırmanız gerekecek.
Null Karşılaştırmaları
By doing the upgrade on your Subgraph, sometimes you might get errors like these:
1ERROR TS2322: Type '~lib/@graphprotocol/graph-ts/common/numbers/BigInt | null' is not assignable to type '~lib/@graphprotocol/graph-ts/common/numbers/BigInt'.2 if (decimals == null) {3 ~~~~4 in src/mappings/file.ts(41,21)
Bu hatayı çözmek için if
ifadesini şu şekilde değiştirebilirsiniz:
1if (!decimals) {23 // veya45 if (decimals === null) {
Aynısı == yerine != kullandığınızda da geçerlidir.
Dönüştürme
Önceden dönüştürme yapmanın yaygın yolu, as
kelimesini şöyle kullanmaktı:
1let byteArray = new ByteArray(10)2let uint8Array = byteArray as Uint8Array // equivalent to: <Uint8Array>byteArray
Ancak bu sadece iki senaryoda çalışır:
- Temel tür dönüşümü (
u8
,i32
,bool
gibi veri türleri arasında; örneğin:let b: isize = 10; b as usize
); - Sınıf kalıtımında yukarı doğru dönüşüm (alt sınıf → üst sınıf)
Örnekler:
1// temel tür dönüşümü2let a: usize = 103let b: isize = 54let c: usize = a + (b as usize)
1// sınıf kalıtımında yukarı doğru dönüşüm2class Bytes extends Uint8Array {}34let bytes = new Bytes(2)5// <Uint8Array>bytes // // aynı şöyle: bytes as Uint8Array
as
/<T>var
kullanmanın güvenli olmadığı iki dönüşüm senaryosu vardır:
- Sınıf kalıtımında aşağı doğru dönüşüm (üst sınıf → alt sınıf)
- Ortak bir üst sınıfa sahip iki tür arasında dönüşüm
1// sınıf kalıtımında aşağı doğru dönüşüm2class Bytes extends Uint8Array {}34let uint8Array = new Uint8Array(2)5// <Bytes>uint8Array // çalıştırma esnasında kırılır :(
1// aynı üst sınıfı paylaşan iki tür arasında2class Bytes extends Uint8Array {}3class ByteArray extends Uint8Array {}45let bytes = new Bytes(2)6// <ByteArray>bytes // çalıştırma esnasında kırılır :(
Bu durumlar için changetype<T>
fonksiyonunu kullanabilirsiniz:
1// sınıf kalıtımında aşağı doğru dönüşüm2class Bytes extends Uint8Array {}34let uint8Array = new Uint8Array(2)5changetype<Bytes>(uint8Array) // çalışır :)
1// Aynı üst sınıfı paylaşan iki tür arasında2class Bytes extends Uint8Array {}3class ByteArray extends Uint8Array {}45let bytes = new Bytes(2)6changetype<ByteArray>(bytes) // çalışır :)
Sadece null olabilmeyi kaldırmak istiyorsanız, as
operatörünü (veya <T>variable
) kullanmaya devam edebilirsiniz. Ancak değerin null olamayacağını bilmeniz gerekir. Aksi halde bu sorun yaratır.
1// null olabilmeyi kaldırma2let previousBalance = AccountBalance.load(balanceId) // AccountBalance | null34if (previousBalance != null) {5 return previousBalance as AccountBalance // güvenli null kaldırma6}78let newBalance = new AccountBalance(balanceId)
Null olabilme durumu için null olabilme kontrolü özelliğine göz atmanızı öneririz. Bu özellikleri uygulamak, kodunuzu daha temiz hale getirecektir 🙂
Ayrıca, dönüştürme işlemlerini kolaylaştırmak için bazı türlere birkaç statik metot daha ekledik, bunlar:
- Bytes.fromByteArray
- Bytes.fromUint8Array
- BigInt.fromByteArray
- ByteArray.fromBigInt
Özellik erişimi ile null olabilme kontrolü
Null kontrolü özelliğini kullanmak için, if
ifadelerini veya üçlü operatörünü (?
ve :
) şu şekilde kullanabilirsiniz:
1let something: string | null = 'data'23let somethingOrElse = something ? something : 'else'45// veya67let somethingOrElse89if (something) {10 somethingOrElse = something11} else {12 somethingOrElse = 'else'13}
Ancak bu yalnızca bir değişken üzerinde if
/ üçlü operatör kullandığınızda çalışır, bir özellik erişiminde değil:
1class Container {2 data: string | null3}45let container = new Container()6container.data = 'data'78let somethingOrElse: string = container.data ? container.data : 'else' // derlemede hata verir
Bu hata çıktısını verir:
1ERROR TS2322: Type '~lib/string/String | null' is not assignable to type '~lib/string/String'.23 let somethingOrElse: string = container.data ? container.data : "else";4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Bu hatayı çözmek için, özellik erişimini bir değişkene atayarak derleyicinin null kontrolünü yapabilmesini sağlayabilirsiniz:
1class Container {2 data: string | null3}45let container = new Container()6container.data = 'data'78let data = container.data910let somethingOrElse: string = data ? data : 'else' // sorunsuz bir şekilde derlenir :)
Özellik erişimi ile operatör aşırı yükleme
Bir özelliğe erişimden gelen bir null değere izin veren bir türü, null olmayan bir türle toplamaya çalışırsanız AssemblyScript derleyicisi, bu değerlerden birinin null değere izin verdiği konusunda derleme zamanı uyarısı vermez. Bunun yerine, sadece sessiz bir şekilde derlemeye devam eder ve çalışma sırasında kodun kırılmasına yol açar.
1class BigInt extends Uint8Array {2 @operator('+')3 plus(other: BigInt): BigInt {4 // ...5 }6}78class Wrapper {9 public constructor(public n: BigInt | null) {}10}1112let x = BigInt.fromI32(2)13let y: BigInt | null = null1415x + y // null değer alabilme hakkında derleme hatası verir1617let wrapper = new Wrapper(y)1819wrapper.n = wrapper.n + x // olması gerektiği gibi derleme hatası vermez
We’ve opened a issue on the AssemblyScript compiler for this, but for now if you do these kind of operations in your Subgraph mappings, you should change them to do a null check before it.
1let wrapper = new Wrapper(y)23if (!wrapper.n) {4 wrapper.n = BigInt.fromI32(0)5}67wrapper.n = wrapper.n + x // şimdi `n`'nin bir BigInt olduğu garanti edilmiştir
Değer ilklendirme
Bunun gibi bir koda sahipseniz:
1var value: Type // null2value.x = 103value.y = 'content'
It will compile but break at runtime, that happens because the value hasn’t been initialized, so make sure your Subgraph has initialized their values, like this:
1var value = new Type() // ilklendirme2value.x = 103value.y = 'content'
Ayrıca, bir GraphQL varlığında şunun gibi null olabilen özellikleriniz varsa:
1type Total @entity {2 id: Bytes!3 amount: BigInt4}
Ve bu koda benzer bir koda sahipseniz:
1let total = Total.load('latest')23if (total === null) {4 total = new Total('latest')5}67total.amount = total.amount + BigInt.fromI32(1)
total.amount
değerini ilklendirdiğinizden emin olmanız gerekecek, çünkü toplama işlemi için son satırda erişmeye çalışırsanız, uygulama çöker. Bu yüzden ya önce ilklendirin:
1let total = Total.load('latest')23if (total === null) {4 total = new Total('latest')5 total.amount = BigInt.fromI32(0)6}78total.tokens = total.tokens + BigInt.fromI32(1)
Ya da GraphQL şemanızı bu özellik için null olabilen bir tür kullanmayacak şekilde değiştirin. Böylece codegen
adımında bu değer sıfır olarak ilklendirilir 😉
1type Total @entity {2 id: Bytes!3 amount: BigInt!4}
1let total = Total.load('latest')23if (total === null) {4 total = new Total('latest') // null olamayan özellikleri ilklendirir5}67total.amount = total.amount + BigInt.fromI32(1)
Sınıf özelliği ilklendirme
Eğer (kendi tarafınızdan veya standart kütüphane tarafından bildirilen) başka sınıfları içeren özelliklere sahip sınıfları şu şekilde dışa aktarırsanız:
1class Thing {}23export class Something {4 value: Thing5}
Derleyici hata verecektir çünkü sınıf olan özellikler için ya bir ilklendirici eklemeniz ya da !
operatörünü eklemeniz gerekmektedir:
1export class Something {2 constructor(public value: Thing) {}3}45// veya67export class Something {8 value: Thing910 constructor(value: Thing) {11 this.value = value12 }13}1415// veya1617export class Something {18 value!: Thing19}
Dizi ilklendirmesi
Array
sınıfı, listenin uzunluğunu ilklendirmek için bir sayı kabul etmeye devam eder. Ancak .push
gibi işlemler başlangıca eklemek yerine boyutu gerçekten artıracağı için dikkatli olmalısınız, örneğin:
1let arr = new Array<string>(5) // ["", "", "", "", ""]23arr.push('something') // ["", "", "", "", "", "something"] // uzunluk 6 :(
Kullandığınız tiplere bağlı olarak -mesela null olabilen değerler kullanıyorsunuz- ve bu tiplere erişim şeklinize göre, aşağıdaki gibi bir çalıştırma hatasıyla karşılaşabilirsiniz:
1ERRO Handler skipped due to execution failure, error: Mapping aborted at ~lib/array.ts, line 110, column 40, with message: Element type must be nullable if array is holey wasm backtrace: 0: 0x19c4 - <unknown>!~lib/@graphprotocol/graph-ts/index/format 1: 0x1e75 - <unknown>!~lib/@graphprotocol/graph-ts/common/collections/Entity#constructor 2: 0x30b9 - <unknown>!node_modules/@graphprotocol/graph-ts/global/global/id_of_type
Listenin başına “push” yapabilmek için, Array
’i ya şu şekilde sıfır boyutla ilklendirmelisiniz:
1let arr = new Array<string>(0) // []23arr.push('something') // ["something"]
Ya da dizin kullanarak değiştirmelisiniz:
1let arr = new Array<string>(5) // ["", "", "", "", ""]23arr[0] = 'something' // ["something", "", "", "", ""]
GraphQL şeması
Bu doğrudan bir AssemblyScript değişikliği değildir. Ancak schema.graphql
dosyanızı güncellemeniz gerekebilir.
Artık türlerinizde Non-Nullable Lists (Boş Olamayan Listeler) olarak alanlar tanımlayamazsınız. Eğer böyle bir şemanız varsa:
1type Something @entity {2 id: Bytes!3}45type MyEntity @entity {6 id: Bytes!7 invalidField: [Something]! # artık geçerli değil8}
Listenin tür üyesine şu şekilde !
eklemeniz gerekecek:
1type Something @entity {2 id: Bytes!3}45type MyEntity @entity {6 id: Bytes!7 invalidField: [Something!]! # geçerli8}
Bu değişiklik, AssemblyScript sürümleri arasındaki null olabilme farklılıklarından dolayı oldu. Ve bu değişiklik src/generated/schema.ts
dosyasıyla ilgilidir (varsayılan yol, bunu değiştirmiş olabilirsiniz).
Diğer
Map#set
veSet#add
ögelerini,this
döndürecek şekilde spesifikasyonla uyumlu hale getirdik (v0.9.2)- Diziler artık ArrayBufferView’den gelmek yerine artık farklı (v0.10.0) sürümünden geliyorlar
- Nesne literalinden başlatılan sınıflar artık yapıcı bir metot tanımlayamaz (v0.10.0)
- Bir
**
ikili işleminin sonucu artık her iki işlenen de tamsayı ise ortak payda tamsayısıdır. Önceden, sonuçMath/f.pow
çağrılmış gibi bir float’tı (v0.11.0) bool
dönüşümündeNaN
’ değerifalse
değerine zorla dönüştürülür (v0.14.9)i8
/u8
ya dai16
/u16
tipindeki küçük tamsayı değerlerini kaydırırken, RHS değerinin yalnızca sırasıyla en düşük 3 ve 4 anlamlı biti sonucu etkiler. Bu, biri32.shl
sonucu yalnızca RHS değerinin 5 en düşük anlamlı bitinden etkilenmesine benzer. Örnek:someI8 << 8
önceden0
değerini üretirken, şimdi RHS’ın8 & 7 = 0
(3 bit) olarak maskelenmesinden dolayısomeI8
değerini üretir (v0.17.0)- Boyutlar farklı olduğunda ilişkisel dize karşılaştırmalarında olan hatanın düzeltmesi (v0.17.8)