Docs
Buscar⌘ K
  • Inicio
  • Acerca de The Graph
  • Redes Admitidas
  • Protocol Contracts
  • Subgrafos
    • Corrientes secundarias
      • Token API
        • AI Suite
          • Indexación
            • Recursos
              Recursos > Migration Guides

              10 minutos

              Guía de Migración de AssemblyScript

              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.

              Esta guía es aplicable para cualquiera que use graph-cli/graph-ts bajo la versión 0.22.0. Si ya estás en una versión superior (o igual) a esa, has estado usando la versión 0.19.10 de AssemblyScript 🙂

              Note: As of 0.24.0, graph-node can support both versions, depending on the apiVersion specified in the Subgraph manifest.

              Características

              Nueva Funcionalidad

              • TypedArrays ahora puede construirse desde ArrayBuffers usando el nuevo wrap método estático⁠ (v0.8.1⁠)
              • Nuevas funciones de la biblioteca estándar: String#toUpperCase, String#toLowerCase, String#localeCompareand TypedArray#set (v0.9.0⁠)
              • Se agregó soporte para x instanceof GenericClass (v0.9.2⁠)
              • Se agregó StaticArray<T>, una más eficiente variante de array (v0.9.3⁠)
              • Se agregó Array<T>#flat (v0.10.0⁠)
              • Se implementó el argumento radix en Number#toString (v0.10.1⁠)
              • Se agregó soporte para los separadores en los literales de punto flotante (v0.13.7⁠)
              • Se agregó soporte para las funciones de primera clase (v0.14.0⁠)
              • Se agregaron builtins: i32/i64/f32/f64.add/sub/mul (v0.14.13⁠)
              • Se implementó Array/TypedArray/String#at (v0.18.2⁠)
              • Se agregó soporte para las plantillas de strings literales (v0.18.17⁠)
              • Se agregó encodeURI(Component) y decodeURI(Component) (v0.18.27⁠)
              • Se agregó toString, toDateString and toTimeString to Date (v0.18.29⁠)
              • Se agregó toUTCString para Date (v0.18.30⁠)
              • Se agregó nonnull/NonNullable builtin type (v0.19.2⁠)

              Optimizaciones

              • Funciones Math como exp, exp2, log, log2 y pow fueron reemplazadas por variantes más rápidas (v0.9.0⁠)
              • Optimizar ligeramente Math.mod (v0.17.1⁠)
              • Caché de más accesos a campos en std Map y Set (v0.17.8⁠)
              • Optimizar para potencias de dos en ipow32/64 (v0.18.2⁠)

              Otros

              • El tipo de un de array literal ahora puede inferirse a partir de su contenido (v0.9.0⁠)
              • Actualizado stdlib a Unicode 13.0.0 (v0.10.0⁠)

              ¿Cómo actualizar?

              1. Change your mappings apiVersion in subgraph.yaml to 0.0.9:
              1...2dataSources:3  ...4    mapping:5      ...6      apiVersion: 0.0.97      ...
              1. Actualiza la graph-cli que usas a la última versión:
              1# si lo tiene instalada de forma global2npm install --global @graphprotocol/graph-cli@latest34# o desde su subgrafo si lo tiene como dependencia5npm install --save-dev @graphprotocol/graph-cli@latest
              1. Haz lo mismo con graph-ts, pero en lugar de instalarlo globalmente, guárdalo en tus dependencias principales:
              1npm install --save @graphprotocol/graph-ts@latest
              1. Sigue el resto de la guía para arreglar los cambios que rompen el lenguaje.
              2. Ejecuta codegen y deploy nuevamente.

              Rompiendo los esquemas

              Anulabilidad

              En la versión anterior de AssemblyScript, podías crear un código como el siguiente:

              1function load(): Value | null { ... }23let maybeValue = load();4maybeValue.aMethod();

              Sin embargo, en la versión más reciente, debido a que el valor es anulable, es necesario que lo compruebes, así:

              1let maybeValue = load()23if (maybeValue) {4  maybeValue.aMethod() // `maybeValue` is not null anymore5}

              O forzarlo así:

              1let maybeValue = load()! // rompiendo el runtime si el valor es nulo23maybeValue.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.

              Variable Shadowing

              Antes podías hacer variable shadowing⁠ y un código como este funcionaría:

              1let a = 102let b = 203let a = a + b

              Sin embargo, ahora esto ya no es posible, y el compilador devuelve este error:

              1ERROR TS2451: Cannot redeclare block-scoped variable 'a'23 let a = a + b;4 ~~~~~~~~~~~~~5in assembly/index.ts(4,3)

              Tendrás que cambiar el nombre de las variables duplicadas si tienes una variable shadowing.

              Comparaciones Nulas

              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)

              Para solucionarlo puedes simplemente cambiar la declaración if por algo así:

              1if (!decimals) {23  // or45  if (decimals === null) {

              Lo mismo ocurre si haces != en lugar de ==.

              Casting

              La forma común de hacer el casting antes era simplemente usar la palabra clave as, de la siguiente forma:

              1let byteArray = new ByteArray(10)2let uint8Array = byteArray as Uint8Array // equivalent to: <Uint8Array>byteArray

              Sin embargo, esto solo funciona en dos casos:

              • Casting de primitivas (entre tipos como u8, i32, bool; eg: let b: isize = 10; b as usize);
              • Upcasting en la herencia de clases (subclase → superclase)

              Ejemplos:

              1// primitive casting2let a: usize = 103let b: isize = 54let c: usize = a + (b as usize)
              1// upcasting on class inheritance2class Bytes extends Uint8Array {}34let bytes = new Bytes(2)5// <Uint8Array>bytes // same as: bytes as Uint8Array

              Hay dos escenarios en los que puede querer cast, pero usando as/<T>var no es seguro:

              • Downcasting en la herencia de clases (superclase → subclase)
              • Entre dos tipos que comparten una superclase
              1// downcasting on class inheritance2class Bytes extends Uint8Array {}34let uint8Array = new Uint8Array(2)5// <Bytes>uint8Array // breaks in runtime :(
              1// between two types that share a superclass2class Bytes extends Uint8Array {}3class ByteArray extends Uint8Array {}45let bytes = new Bytes(2)6// <ByteArray>bytes // breaks in runtime :(

              Para esos casos, puedes usar la función changetype<T>:

              1// downcasting on class inheritance2class Bytes extends Uint8Array {}34let uint8Array = new Uint8Array(2)5changetype<Bytes>(uint8Array) // works :)
              1// entre dos tipos que comparten un superclass2class Bytes extends Uint8Array {}3class ByteArray extends Uint8Array {}45let bytes = new Bytes(2)6changetype<ByteArray>(bytes) // works :)

              Si solo quieres eliminar la anulabilidad, puedes seguir usando el as operador (o <T>variable), pero asegúrate de que el valor no puede ser nulo, de lo contrario se romperá.

              1// eliminar anulabilidad2let previousBalance = AccountBalance.load(balanceId) // AccountBalance | null34if (previousBalance != null) {5  return previousBalance as AccountBalance // sabe remove null6}78let newBalance = new AccountBalance(balanceId)

              Para el caso de la anulabilidad se recomienda echar un vistazo al nullability check feature⁠, hará que tu código sea más limpio 🙂

              También hemos añadido algunos métodos estáticos en algunos tipos para facilitar el casting, son:

              • Bytes.fromByteArray
              • Bytes.fromUint8Array
              • BigInt.fromByteArray
              • ByteArray.fromBigInt

              Comprobación de anulabilidad con acceso a la propiedad

              Para usar el nullability check feature⁠ puedes usar la declaración if o el operador ternario (? and :) asi:

              1let something: string | null = 'data'23let somethingOrElse = something ? something : 'else'45// o67let somethingOrElse89if (something) {10  somethingOrElse = something11} else {12  somethingOrElse = 'else'13}

              Sin embargo eso solo funciona cuando estás haciendo el if / ternario en una variable, no en un acceso a una propiedad, como este:

              1class Container {2  data: string | null3}45let container = new Container()6container.data = 'data'78let somethingOrElse: string = container.data ? container.data : 'else' // doesn't compile

              Lo que produce este error:

              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                                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

              Para solucionar este problema, puedes crear una variable para ese acceso a la propiedad de manera que el compilador pueda hacer la magia de la comprobación de nulidad:

              1class Container {2  data: string | null3}45let container = new Container()6container.data = 'data'78let data = container.data910let somethingOrElse: string = data ? data : 'else' // compiles just fine :)

              Sobrecarga de operadores con acceso a propiedades

              Si intentas sumar (por ejemplo) un tipo anulable (desde un acceso a una propiedad) con otro no anulable, el compilador de AssemblyScript en lugar de dar un error en el tiempo de compilación advirtiendo que uno de los valores es anulable, simplemente compila en silencio, dando oportunidad a que el código se rompa en tiempo de ejecución.

              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 // give compile time error about nullability1617let wrapper = new Wrapper(y)1819wrapper.n = wrapper.n + x // doesn't give compile time errors as it should

              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 // now `n` is guaranteed to be a BigInt

              Inicialización del valor

              Si tienes algún código como este:

              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() // initialized2value.x = 103value.y = 'content'

              También si tienes propiedades anulables en una entidad GraphQL, como esta:

              1type Total @entity {2  id: Bytes!3  amount: BigInt4}

              Y tienes un código similar a este:

              1let total = Total.load('latest')23if (total === null) {4  total = new Total('latest')5}67total.amount = total.amount + BigInt.fromI32(1)

              Tendrás que asegurarte de inicializar el valor total.amount, porque si intentas acceder como en la última línea para la suma, se bloqueará. Así que o bien la inicializas primero:

              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)

              O simplemente puedes cambiar tu esquema GraphQL para no usar un tipo anulable para esta propiedad, entonces la inicializaremos como cero en el paso codegen 😉

              1type Total @entity {2  id: Bytes!3  amount: BigInt!4}
              1let total = Total.load('latest')23if (total === null) {4  total = new Total('latest') // justo luego de haber iniciado la propiedad de no-anulable5}67total.amount = total.amount + BigInt.fromI32(1)

              Inicialización de las propiedades de la clase

              Si exportas alguna clase con propiedades que son otras clases (declaradas por ti o por la librería estándar) así:

              1class Thing {}23export class Something {4  value: Thing5}

              El compilador dará un error porque tienes que añadir un inicializador para las propiedades que son clases, o añadir el operador !:

              1export class Something {2  constructor(public value: Thing) {}3}45// o67export class Something {8  value: Thing910  constructor(value: Thing) {11    this.value = value12  }13}1415// or1617export class Something {18  value!: Thing19}

              Inicialización de Array

              La clase Array sigue aceptando un número para inicializar la longitud de la lista, sin embargo hay que tener cuidado porque operaciones como .push en realidad aumentarán el tamaño en lugar de añadirlo al principio, por ejemplo:

              1let arr = new Array<string>(5) // ["", "", "", "", ""]23arr.push('something') // ["", "", "", "", "", "something"] // size 6 :(

              Dependiendo de los tipos que estés utilizando, por ejemplo los anulables, y de cómo estés accediendo a ellos, podrías encontrarte con un error de ejecución como este:

              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

              Para realmente empujar al principio deberías o bien, inicializar el Array con tamaño cero, así:

              1let arr = new Array<string>(0) // []23arr.push('something') // ["something"]

              O debería mutar a través de un índice:

              1let arr = new Array<string>(5) // ["", "", "", "", ""]23arr[0] = 'something' // ["something", "", "", "", ""]

              Esquema GraphQL

              Esto no es un cambio directo de AssemblyScript, pero es posible que tengas que actualizar tu archivo schema.graphql.

              Ahora ya no puedes definir campos en tus tipos que sean Listas No Anulables. Si tienes un esquema como este:

              1type Something @entity {2  id: Bytes!3}45type MyEntity @entity {6  id: Bytes!7  invalidField: [Something]! # no longer valid8}

              Tendrás que añadir un ! al miembro del tipo Lista, así:

              1type Something @entity {2  id: Bytes!3}45type MyEntity @entity {6  id: Bytes!7  invalidField: [Something!]! # valid8}

              Esto cambió debido a las diferencias de anulabilidad entre las versiones de AssemblyScript, y está relacionado con el archivo src/generated/schema.ts (ruta por defecto, puede que lo hayas cambiado).

              Otros

              • Alineado Map#set y Set#add con el spec, devolviendo this (v0.9.2⁠)
              • Las arrays ya no heredan de ArrayBufferView, sino que son distintas (v0.10.0⁠)
              • Las clases inicializadas a partir de objetos literales ya no pueden definir un constructor (v0.10.0⁠)
              • El resultado de una operación binaria ** es ahora el entero denominador común si ambos operandos son enteros. Anteriormente, el resultado era un flotante como si se llamara a Math/f.pow (v0.11.0⁠)
              • Coerción NaN a false cuando casting a bool (v0.14.9⁠)
              • Al desplazar un valor entero pequeño de tipo i8/u8 o i16/u16, sólo los 3 o 4 bits menos significativos del valor RHS afectan al resultado, de forma análoga al resultado de un i32.shl que sólo se ve afectado por los 5 bits menos significativos del valor RHS. Ejemplo: someI8 << 8 previamente producía el valor 0, pero ahora produce someI8 debido a enmascarar el RHS como 8 & 7 = 0 (3 bits) (v0.17.0⁠)
              • Corrección de errores en las comparaciones de strings relacionales cuando los tamaños difieren (v0.17.8⁠)
              ⁠Editar en GitHub⁠

              CuraciónGraphQL Validations Migration Guide
              En esta página
              • Características
              • Nueva Funcionalidad
              • Optimizaciones
              • Otros
              • ¿Cómo actualizar?
              • Rompiendo los esquemas
              • Anulabilidad
              • Variable Shadowing
              • Comparaciones Nulas
              • Casting
              • Comprobación de anulabilidad con acceso a la propiedad
              • Sobrecarga de operadores con acceso a propiedades
              • Inicialización del valor
              • Inicialización de las propiedades de la clase
              • Inicialización de Array
              • Esquema GraphQL
              • Otros
              The GraphEstadoTestnetRecursos de marcaForoSeguridadPolítica de privacidadTérminos de servicio